I need to assing a value (a previously created entites Id)to reference column in a doctrine 2 model, For example
/**
* #Entity #Table(name="products")
*/
class product {
/**
*
* #ManyToOne(targetEntity="category")
*/
protected $category;
public function assignCategoryId($id) {
$this->category_id=$id;
}
}
I assume that category_id is created by doctrine 2 as referance column name,
Don't ask why I want to assign the id not the object itself, because it has to be this way. Is there a way to do this ? Any idea ?
While #Orbling's answer is correct you don't actually have to load the entity from the database. Instead you can use a reference:
// method on Product entity
public function setCategory(Category $category)
{
$this->category = $category;
}
// then set the category on the product
$product->setCategory($entityManager->getReference('category', $categoryId));
You can find the documentation here.
In order to do that, you would create a category entity and assign it to the relationship property.
$category = $entityManager->find('category', $categoryID);
$product = new product();
$product->category = $category;
That would create the relationship I believe.
Related
I have 2 tables employees and employee_locations. One employee has many locations. I need to find out one employee record with related latest employee_locations record. I wrote below query.
$employees = Employee::find([1])->with('employees.employee_locations')->latest()->first();
I am getting below error
BadMethodCallException
Method Illuminate\Database\Eloquent\Collection::with does not exist.
Your issue is that the find method retrieves a collection of Eloquent objects, on which the with method can not be used. You must first specify your relations for the Employee objects and then use find.
The below code will retrieve the employee with the ids specified in find method and locations for each employee:
$employees = Employee::with('employees.employee_locations')->find([1])
create a relation in your model. Something like this:
class Employee extends Model
{
protected $table = 'employees';
public function location()
{
return $this->hasMany(EmployeeLocation::class, 'employeed_id');
}
}
class EmployeeLocation extends Model
{
protected $table = 'employee_locations';
}
$employees = Employee::with('location')->first();
or you do
$employees = Employee::with('location')->find(<employeed_id>);
Try This method
$employees = Employee::with('employees')->where('employeesid',$employeesid)-
>get()->find($employeesid);
I just want to update a column table based on a condition. Here my code :
this.session.Query<EventEntity>()
.Where(e => [...])
.Update(c => new { Enabled = true });
This call generates the following SQL :
insert into HT_event SELECT evententit0_.Id as Id FROM event evententit0_ WHERE [...]
UPDATE event SET Enabled=? WHERE (Id) IN (select Id from HT_event)
Why NHibernate creates a temp table to store ids instead of directly generates a correct IN clause ? How can I disable this behavior ?
To give more information, I use a table per class hierarchy inheritance mapping with mapping by code. My EventEntity is an abstract class :
public abstract class EventEntity { ... }
public class EventMap : ClassMapping<EventEntity> { ... }
I have a few others entities that inherit from EventEntity
public abstract class MatchEntity { ... }
public class MatchMap : JoinedSubclassMapping<MatchEntity> { ... }
Thx for your help !
Hibernate propose a way to customize the bulk id strategy, but it's not available for NHibernate at this moment : https://github.com/nhibernate/nhibernate-core/issues/2004.
I've got an NHibernate 4 project with several collection relationships. I'm unit-testing the object model, exercising all the collections. Most work fine, but in one case, the child collection is cascade-saved properly, but on loading the parent entity and examining the collection property, the child collection is empty.
Here are the abbreviated classes. GatewayUser is the parent object, and it has a collection of Student. The collection has a private backing property, and AddStudent/RemoveStudent methods.
Further complications: I'm using the NHibernate.AspNet.Identity library for OAuth2 user management, and GatewayUser inherits from IdentityUser. That in turn inherits from the the library's internal base entity class, which is different from my project's own base class.
public class GatewayUser : IdentityUser
{
public GatewayUser()
{
}
public virtual string FirstName { get; set; }
// ...More value properties and OAuth stuff omitted
// students associated with this user
private IList<Student> _students = new List<Student>();
public virtual IList<Student> Students
{
get { return new ReadOnlyCollection<Student>(_students); }
}
public virtual GatewayUser AddStudent(Student s)
{
if (_students.Contains(s))
return this;
s.GatewayUser = this;
_students.Add(s);
return this;
}
public virtual GatewayUser RemoveStudent(Student s)
{
if (_students.Contains(s))
{
_students.Remove(s);
}
return this;
}
Student is more ordinary; it inherits from my own BaseEntity class, has many value properties, and its own child collection of ProgramApplication items. Interestingly, this collection saves and loads fine; it's got the same structure (private backer, etc.) as the failing collection in GatewayUser.
The mapping is complicated, because the library internally maps its classes with NHiberante.Mapping.ByCode.Conformist classes (which I have no prior experience with).
I'm mapping my own classes with NHibernate automapping, because I have so many classes and properties to map. To get it all working, I copied the library's mapping helper class, and modified it a bit to add my base entity classes to it's list called baseEntityToIgnore. I also had to create a conformist mapping for GatewayUser, since it has a different base entity type, and my automapping wouldn't pick it up.
The unit test looks like this:
[Test]
public void GatewayUserCascadesStudents()
{
var u = new GatewayUser() { FirstName = "Mama", LastName = "Bear", UserName = "somebody#example.com" };
var s1 = new Student() { FirstName = "First", LastName = "Student" };
var s2 = new Student() { FirstName = "Second", LastName = "Student" };
u.AddStudent(s1).AddStudent(s2);
using (var s = NewSession())
using (var tx = s.BeginTransaction())
{
s.Save(u);
tx.Commit();
}
GatewayUser fetched = null;
int count = 0;
using (var s = NewSession())
{
fetched = s.Get<GatewayUser>(u.Id);
count = fetched.Students.Count;
}
Assert.AreEqual(2, count);
}
The generated SQL inserts into both AspNetUsers and GatewayUser (reflecting the inheritance relationship), and inserts two records into Student. All good. On fetching, the SELECT joins the two user tables, and I get a GatewayUser object, but accessing the Students collection does not trigger a SELECT on the Student table. But if I change the mapping to Lazy(CollectionLazy.NoLazy), the SQL to select eagerly load Students appears in the log, but the collection is not populated. If I switch the database from SQLite to Sql Server, I see the student records in the table. The generated SQL (when NoLazy is applied) will fetch them. So on the database end, things look fine.
I have to think my Frankenstein mapping situation is to blame. I'm mixing the library's conformist mapping with Fluent mapping, and there are two different base entity classes. However, the generated schema looks correct, and the save cascades correctly, so I don't know if that's the issue.
Found my own answer. My mapping of the parent class's list was like this:
public class GatewayUserMap : JoinedSubclassMapping
{
public GatewayUserMap()
{
Key(g => g.Column("Id"));
Property(c => c.FirstName, m => m.Length(50));
// ... more properties
List(gu => gu.Students, map =>
{
map.Key(c => c.Column("GatewayUser_Id"));
map.Cascade(Cascade.All | Cascade.DeleteOrphans);
map.Index(li => li.Column("ListIndex"));
map.Access(Accessor.Field | Accessor.NoSetter);
}
);
}
}
I have a private backing field for the collection. Removing Accessor.NoSetter from the collection mapping fixed it. In fact, it still worked without Accessor.Field -- I guess the mapper does a good job of looking around for one, and using it if found. Changing the name of the private backer from "_students" to "funnyName" prevented the mapper from finding it.
I have a model Work with this relation
public function types()
{
return $this->belongsTo('App\Models\Type');
}
And a model Type with this relation
public function works()
{
return $this->hasMany('App\Models\Work');
}
I try to access in my view show view to type but I've a lot of errors
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$name
I try this : $work->types()->name for get data.
In my DB, my table 'Works' have a foreignkey 'type_id'.
I would like to get the 'type' of the post. There can be only one per post.
Thank you very much !
Semantically you want to make your relationships like so:
Work
// A work is of a single type
public function type()
{
return $this->belongsTo('App\Models\Type');
}
Type
// A type of work can have many items of work
public function works()
{
return $this->hasMany('App\Models\Work');
}
You can then access the relationship like so:
$type = Work::first()->type // return object of type Type
$works = Type::first()->works // return collection of objects of type Work
EDIT
By accessing the relationship with () you are returning the underlying query builder instance of the relationship and you will need to finish your statement with ->get() like so:
$works = Type::first()->works()->get();
You should have on Work Model:
public function type()
{
return $this->belongsTo('App\Models\Type');
}
and on your view:
$work->type->name;
Since you are not using default id as foreign key you should add
protected $primaryKey = "type_id";
in your model
I'm having trouble on inserting a new record having a parent .
<?php
/**
* This is the model class for table "tbl_a".
* #property integer $id
....
*/
class A extends CACtiveRecord{
}
?>
<?php
/**
* This is the model class for table "tbl_b".
* #property integer $id
....
* The followings are the available model relations:
* #property A $a
*/
class B extends CACtiveRecord{
//codes...
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'a' => array(self::BELONGS_TO , 'A', 'id'),
);
}
}
?>
This is the structure of my model classes.
here the 'id' of tbl_b is set as the primary key and also is the foreign key referencing tbl_a. 'id' of tbl_a is its primary key.
My issue here is, when i tried to save model object of B ($b->save()), after setting all the attributes excluding 'id' (But the property 'a' of the object[$b] is set with an active record of model 'A' say having primary key 10), an exception is thrown on inserting the record because of no 'id' is set to it. But when I tried the same after setting the 'id' of the model object, it inserted correctly.
Why we need to set the foreign key attribute of the child model even the related property is set?
Is there any solution for this. So that the foreign key reference id is taken automaticaly from the related model obj?
Thanks in advance.
Is will be automatically generated only if your database support it. Yii will not create id by himself. If you are using MySQL as your RDMS, primary key should be marked as auto_increment. But in your situation, you are using foreign key as your primary key. So the most preferable way for you is to overload beforeSave method of B model and fetch a::id as b::id:
public function beforeSave()
{
if (parent::beforeSave())
{
$this->id = $this->a->id;
return true;
}
return false;
}