1
0
mirror of synced 2024-12-14 23:26:04 +03:00
doctrine2/manual/new/docs/en/working-with-objects.txt

87 lines
3.4 KiB
Plaintext

++ Dealing with relations
++ Many-to-Many relations
+++ Creating a new link
Lets say we have two classes User and Group which are linked trhough a GroupUser association class. When working with transient (new) records the fastest way for adding a User and couple of Groups for it is:
<code type="php">
$user = new User();
$user->name = 'Some User';
$user->Group[0]->name = 'Some Group';
$user->Group[1]->name = 'Some Other Group';
$user->save();
</code>
However in real world scenarious you often already have existing groups, where you want to add a given user. The most efficient way of doing this is:
<code type="php">
$gu = new GroupUser();
$gu->user_id = $userId;
$gu->group_id = $groupId;
$gu->save();
</code>
+++ Deleting a link
The right way to delete links between many-to-many associated records is by using the DQL DELETE statement. Convenient and recommended way of using DQL DELETE is trhough the Query API.
<code type="php">
$deleted = Doctrine_Query::create()
->delete()
->from('GroupUser')
->addWhere('user_id = 5')
->whereIn('group_id', $groupIds);
->execute();
// print out the deleted links
print $deleted;
</code>
Another way to {{unlink}} the relationships between related objects is through the {{Doctrine_Record::unlink}} method. However, you should avoid using this method unless you already have the parent model, since it involves querying the database first.
<code type="php">
$user = $conn->getTable('User')->find(5);
$user->unlink('Group', array(0, 1));
$user->save();
</code>
While the obvious and convinient way of deleting a link between User and Group would be the following, you still should *NOT* do this:
<code type="php">
$user = $conn->getTable('User')->find(5);
$user->GroupUser
->remove(0)
->remove(1);
$user->save();
</code>
This is due to a fact that $user->GroupUser loads all group links for given user. This can time-consuming task if user belongs to many groups. Even if the user belongs to few groups this will still execute an unnecessary SELECT statement.
++ Component overview
++ Fetching objects
+++ Field lazy-loading
Whenever you fetch an object that has not all of its fields loaded from database then the state of this object is called proxy. Proxy objects can load the unloaded fields lazily.
Lets say we have a User class with the following definition:
<code type="php">
class User extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('name', 'string', 20);
$this->hasColumn('password', 'string', 16);
$this->hasColumn('description', 'string');
}
}
</code>
In the following example we fetch all the Users with the fields name and password loaded directly. Then we lazy-load a huge field called description for one user.
<code type="php">
$users = Doctrine_Query::create()->select('u.name, u.password')->from('User u');
// the following lazy-loads the description fields and executes one additional database query
$users[0]->description;
</code>
Doctrine does the proxy evaluation based on loaded field count. It does not evaluate which fields are loaded on field-by-field basis. The reason for this is simple: performance. Field lazy-loading is very rarely needed in PHP world, hence introducing some kind of variable to check which fields are loaded would introduce unnecessary overhead to basic fetching.