Permalink
Browse files

Defining models finished

  • Loading branch information...
1 parent 8b48c99 commit 3dc2fe8edc2b37a8a46f8ae663fc37ceb6723697 @dominics dominics committed Mar 21, 2012
Showing with 380 additions and 407 deletions.
  1. +156 −128 source/en/manual/defining-models.rst
  2. +218 −279 source/en/manual/working-with-models.rst
  3. +6 −0 source/ja/manual/extensions.rst
View
284 source/en/manual/defining-models.rst
@@ -2398,48 +2398,60 @@ Doctrine offers various table options. All table options can be set via
the ``Doctrine_Record::option`` function.
For example if you are using MySQL and want to use INNODB tables it can
-be done as follows:
+be done as follows::
- class MyInnoDbRecord extends Doctrine_Record { public function
-setTableDefinition() { $this->hasColumn('name', 'string');
-
-::
-
- $this->option('type', 'INNODB');
+ class MyInnoDbRecord extends Doctrine_Record
+ {
+ public function setTableDefinition()
+ {
+ $this->hasColumn('name', 'string');
+ $this->option('type', 'INNODB');
+ }
}
-}
-
Here is the same example in YAML format. You can read more about YAML in
the :doc:`yaml-schema-files` chapter:
- MyInnoDbRecord: columns: name: string options: type: INNODB
+.. code-block:: yaml
-In the following example we set the collate and character set options:
+ MyInnoDbRecord:
+ columns:
+ name: string
+ options:
+ type: INNODB
- class MyCustomOptionRecord extends Doctrine_Record { public function
-setTableDefinition() { $this->hasColumn('name', 'string');
+In the following example we set the collate and character set options::
-::
+ class MyCustomOptionRecord extends Doctrine_Record
+ {
+ public function setTableDefinition()
+ {
+ $this->hasColumn('name', 'string');
- $this->option('collate', 'utf8_unicode_ci');
- $this->option('charset', 'utf8');
+ $this->option('collate', 'utf8_unicode_ci');
+ $this->option('charset', 'utf8');
+ }
}
-}
-
Here is the same example in YAML format. You can read more about YAML in
the :doc:`yaml-schema-files` chapter:
- MyCustomOptionRecord: columns: name: string options: collate:
-utf8_unicode_ci charset: utf8
+.. code-block:: yaml
+
+ MyCustomOptionRecord:
+ columns:
+ name: string
+ options:
+ collate: utf8_unicode_ci
+ charset: utf8
It is worth noting that for certain databases (Firebird, MySql and
PostgreSQL) setting the charset option might not be enough for Doctrine
to return data properly. For those databases, users are advised to also
-use the ``setCharset`` function of the database connection:
+use the ``setCharset`` function of the database connection::
- $conn = Doctrine_Manager::connection(); $conn->setCharset('utf8');
+ $conn = Doctrine_Manager::connection();
+ $conn->setCharset('utf8');
==============
Record Filters
@@ -2451,97 +2463,104 @@ model that is invalid. So it allows you to essentially add properties
dynamically to a model through the use of one of these filters.
To attach a filter you just need to add it in the :php:meth:`setUp` method of
-your model definition:
-
- class User extends Doctrine_Record { public function
-setTableDefinition() { $this->hasColumn('username', 'string', 255);
-$this->hasColumn('password', 'string', 255); }
-
-::
+your model definition::
- public function setUp()
+ class User extends Doctrine_Record
{
- $this->hasOne('Profile', array(
- 'local' => 'id',
- 'foreign' => 'user_id'
- ));
- $this->unshiftFilter(new Doctrine_Record_Filter_Compound(array('Profile')));
- }
-
-}
-
-class Profile extends Doctrine_Record { public function
-setTableDefinition() { $this->hasColumn('user_id', 'integer');
-$this->hasColumn('first_name', 'string', 255);
-$this->hasColumn('last_name', 'string', 255); }
+ public function setTableDefinition()
+ {
+ $this->hasColumn('username', 'string', 255);
+ $this->hasColumn('password', 'string', 255);
+ }
-::
+ public function setUp()
+ {
+ $this->hasOne('Profile', array(
+ 'local' => 'id',
+ 'foreign' => 'user_id'
+ ));
+ $this->unshiftFilter(new Doctrine_Record_Filter_Compound(array('Profile')));
+ }
+ }
- public function setUp()
+ class Profile extends Doctrine_Record
{
- $this->hasOne('User', array(
- 'local' => 'user_id',
- 'foreign' => 'id'
- ));
- }
+ public function setTableDefinition()
+ {
+ $this->hasColumn('user_id', 'integer');
+ $this->hasColumn('first_name', 'string', 255);
+ $this->hasColumn('last_name', 'string', 255);
+ }
-}
+ public function setUp()
+ {
+ $this->hasOne('User', array(
+ 'local' => 'user_id',
+ 'foreign' => 'id'
+ ));
+ }
+ }
Now with the above example we can easily access the properties of the
``Profile`` relationship when using an instance of ``User``. Here is an
-example:
+example::
- $user = Doctrine_Core::getTable('User') ->createQuery('u')
-->innerJoin('u.Profile p') ->where('p.username = ?', 'jwage')
-->fetchOne();
+ $user = Doctrine_Core::getTable('User')
+ ->createQuery('u')
+ ->innerJoin('u.Profile p')
+ ->where('p.username = ?', 'jwage')
+ ->fetchOne();
-echo $user->first_name . ' ' . $user->last_name;
+ echo $user->first_name . ' ' . $user->last_name;
When we ask for the ``first_name`` and ``last_name`` properties they
do not exist on the ``$user`` instance so they are forwarded to the
``Profile`` relationship. It is the same as if you were to do the
-following:
+following::
- echo $user->Profile->first_name . ' ' . $user->Profile->last_name;
+ echo $user->Profile->first_name . ' ' . $user->Profile->last_name;
You can write your own record filters pretty easily too. All that is
required is you create a class which extends
``Doctrine_Record_Filter`` and implements the :php:meth:`filterSet` and
-:php:meth:`filterGet` methods. Here is an example:
-
- class MyRecordFilter extends Doctrine_Record_Filter { public function
-filterSet(Doctrine_Record $record, $name, $value) { // try and set the
-property
-
-::
+:php:meth:`filterGet` methods. Here is an example::
- throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record)));
- }
-
- public function filterGet(Doctrine_Record, $name)
+ class MyRecordFilter extends Doctrine_Record_Filter
{
- // try and get the property
+ public function filterSet(Doctrine_Record $record, $name, $value)
+ {
+ // try and set the property
+ throw new Doctrine_Record_UnknownPropertyException(sprintf(
+ 'Unknown record property / related component "%s" on "%s"',
+ $name,
+ get_class($record)
+ ));
+ }
- throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record)));
+ public function filterGet(Doctrine_Record, $name)
+ {
+ // try and get the property
+ throw new Doctrine_Record_UnknownPropertyException(sprintf(
+ 'Unknown record property / related component "%s" on "%s"',
+ $name,
+ get_class($record)
+ ));
+ }
}
-}
-
-Now you can add the filter to your models:
-
- class MyModel extends Doctrine_Record { // ...
-
-::
+Now you can add the filter to your models::
- public function setUp()
+ class MyModel extends Doctrine_Record
{
// ...
- $this->unshiftFilter(new MyRecordFilter());
+ public function setUp()
+ {
+ // ...
+ $this->unshiftFilter(new MyRecordFilter());
+ }
}
-}
-
.. note::
Remember to be sure to throw an instance of the
@@ -2577,48 +2596,49 @@ Delete Cascades
Doctrine provides a second application-level cascade style: delete.
Unlike the :php:meth:`save` cascade, the delete cascade needs to be turned on
-explicitly as can be seen in the following code snippet:
-
- // models/User.php
-
-class User extends BaseUser { // ...
+explicitly as can be seen in the following code snippet::
-::
-
- public function setUp()
+ // models/User.php
+ class User extends BaseUser
{
- parent::setup();
-
// ...
+ public function setUp()
+ {
+ parent::setup();
- $this->hasMany('Address as Addresses', array(
+ // ...
+
+ $this->hasMany('Address as Addresses', array(
'local' => 'id',
'foreign' => 'user_id',
'cascade' => array('delete')
- )
- );
+ ));
+ }
}
-}
-
Here is the same example in YAML format. You can read more about YAML in
-the :doc:`yaml-schema-files` chapter:
+the :doc:`yaml-schema-files` chapter
.. code-block:: yaml
- # schema.yml
-
-User: # ... relations: # ... Addresses: class: Address local: id
-foreign: user_id cascade: [delete]
+ # schema.yml
+ User:
+ # ...
+ relations:
+ # ...
+ Addresses:
+ class: Address
+ local: id
+ foreign: user_id
+ cascade: [delete]
The ``cascade`` option is used to specify the operations that are
cascaded to the related objects on the application-level.
.. note::
- Please note that the only currently supported value is
- ``delete``, more options will be added in future releases of
- Doctrine.
+ Please note that the only currently supported value is ``delete``, more
+ options will be added in future releases of Doctrine.
In the example above, Doctrine would cascade the deletion of a ``User``
to it's associated ``Addresses``. The following describes the generic
@@ -2671,41 +2691,49 @@ application-level delete cascades except:
Database-level delete cascades are applied on the foreign key
constraint. Therefore they're specified on that side of the relation
that owns the foreign key. Picking up the example from above, the
-definition of a database-level cascade would look as follows:
-
- // models/Address.php
+definition of a database-level cascade would look as follows::
-class Address extends Doctrine_Record { public function
-setTableDefinition() { $this->hasColumn('user_id', 'integer');
-$this->hasColumn('address', 'string', 255); $this->hasColumn('country',
-'string', 255); $this->hasColumn('city', 'string', 255);
-$this->hasColumn('state', 'string', 2); $this->hasColumn('postal_code',
-'string', 25); }
-
-::
-
- public function setUp()
+ // models/Address.php
+ class Address extends Doctrine_Record
{
- $this->hasOne('User', array(
+ public function setTableDefinition() {
+ $this->hasColumn('user_id', 'integer');
+ $this->hasColumn('address', 'string', 255);
+ $this->hasColumn('country', 'string', 255);
+ $this->hasColumn('city', 'string', 255);
+ $this->hasColumn('state', 'string', 2);
+ $this->hasColumn('postal_code', 'string', 25);
+ }
+
+ public function setUp()
+ {
+ $this->hasOne('User', array(
'local' => 'user_id',
'foreign' => 'id',
'onDelete' => 'CASCADE'
- )
- );
+ ));
+ }
}
-}
-
Here is the same example in YAML format. You can read more about YAML in
the :doc:`yaml-schema-files` chapter:
.. code-block:: yaml
- # schema.yml
-
-Address: columns: user_id: integer address: string(255) country:
-string(255) city: string(255) state: string(2) postal_code: string(25)
-relations: User: local: user_id foreign: id onDelete: CASCADE
+ # schema.yml
+ Address:
+ columns:
+ user_id: integer
+ address: string(255)
+ country: string(255)
+ city: string(255)
+ state: string(2)
+ postal_code: string(25)
+ relations:
+ User:
+ local: user_id
+ foreign: id
+ onDelete: CASCADE
The ``onDelete`` option is translated to proper DDL/DML statements when
Doctrine creates your tables.
View
497 source/en/manual/working-with-models.rst
@@ -1,3 +1,5 @@
+.. vim: set ts=4 sw=4 tw=79 :
+
*******************
Working with Models
*******************
@@ -6,20 +8,20 @@ Working with Models
Define Test Schema
==================
- **NOTE** Remember to delete any existing schema information and
+.. note::
+
+ Remember to delete any existing schema information and
models from previous chapters.
$ rm schema.yml $ touch schema.yml $ rm -rf models/\*
-For the next several examples we will use the following schema:
+For the next several examples we will use the following schema::
- // models/User.php
+ // models/User.php
-class User extends Doctrine\_Record { public function
-setTableDefinition() { $this->hasColumn('username', 'string', 255,
-array( 'type' => 'string', 'length' => '255' ) );
-
-::
+ class User extends Doctrine_Record { public function
+ setTableDefinition() { $this->hasColumn('username', 'string', 255,
+ array( 'type' => 'string', 'length' => '255' ) );
$this->hasColumn('password', 'string', 255, array(
'type' => 'string',
@@ -54,8 +56,8 @@ array( 'type' => 'string', 'length' => '255' ) );
// models/Email.php
-class Email extends Doctrine\_Record { public function
-setTableDefinition() { $this->hasColumn('user\_id', 'integer', null,
+class Email extends Doctrine_Record { public function
+setTableDefinition() { $this->hasColumn('user_id', 'integer', null,
array( 'type' => 'integer' ) );
::
@@ -80,8 +82,8 @@ array( 'type' => 'integer' ) );
// models/Phonenumber.php
-class Phonenumber extends Doctrine\_Record { public function
-setTableDefinition() { $this->hasColumn('user\_id', 'integer', null,
+class Phonenumber extends Doctrine_Record { public function
+setTableDefinition() { $this->hasColumn('user_id', 'integer', null,
array( 'type' => 'integer' ) );
::
@@ -107,7 +109,7 @@ array( 'type' => 'integer' ) );
// models/Group.php
-class Group extends Doctrine\_Record { public function
+class Group extends Doctrine_Record { public function
setTableDefinition() { $this->setTableName('groups');
$this->hasColumn('name', 'string', 255, array( 'type' => 'string',
'length' => '255' ) ); }
@@ -128,8 +130,8 @@ $this->hasColumn('name', 'string', 255, array( 'type' => 'string',
// models/UserGroup.php
-class UserGroup extends Doctrine\_Record { public function
-setTableDefinition() { $this->hasColumn('user\_id', 'integer', null,
+class UserGroup extends Doctrine_Record { public function
+setTableDefinition() { $this->hasColumn('user_id', 'integer', null,
array( 'type' => 'integer', 'primary' => true ) );
::
@@ -144,27 +146,27 @@ array( 'type' => 'integer', 'primary' => true ) );
}
Here is the same example in YAML format. You can read more about YAML in
-the [doc yaml-schema-files :name] chapter:
+the :doc:`yaml-schema-files` chapter:
# schema.yml
User: columns: username: string(255) password: string(255) relations:
-Groups: class: Group local: user\_id foreign: group\_id refClass:
+Groups: class: Group local: user_id foreign: group_id refClass:
UserGroup foreignAlias: Users
-Email: columns: user\_id: integer address: string(255) relations: User:
+Email: columns: user_id: integer address: string(255) relations: User:
foreignType: one
-Phonenumber: columns: user\_id: integer phonenumber: string(255)
-primary\_num: boolean relations: User: foreignAlias: Phonenumbers
+Phonenumber: columns: user_id: integer phonenumber: string(255)
+primary_num: boolean relations: User: foreignAlias: Phonenumbers
Group: tableName: groups columns: name: string(255)
-UserGroup: columns: user\_id: type: integer primary: true group\_id:
+UserGroup: columns: user_id: type: integer primary: true group_id:
type: integer primary: true
Now that you have your schema defined you can instantiate the database
-by simply running the ``generate.php`` script we so conveniently created
+by simply running the :file:`generate.php` script we so conveniently created
in the previous chapter.
$ php generate.php
@@ -183,9 +185,8 @@ same getters and setters as for the record properties.
You can use any of the three ways above, however the last one is the
recommended one for array portability purposes.
- // test.php
-
-// ... $user = new User(); $user['username'] = 'jwage';
+// test.php
+$user = new User(); $user['username'] = 'jwage';
$user['password'] = 'changeme';
$email = $user->Email;
@@ -198,39 +199,35 @@ When accessing a one-to-one related record that doesn't exist, Doctrine
automatically creates the object. That is why the above code is
possible.
- // test.php
-
-// ... $user->Email->address = 'jonwage@gmail.com'; $user->save();
+// test.php
+$user->Email->address = 'jonwage@gmail.com'; $user->save();
When accessing one-to-many related records, Doctrine creates a
``Doctrine_Collection`` for the related component. Lets say we have
``users`` and ``phonenumbers`` and their relation is one-to-many. You
can add ``phonenumbers`` easily as shown above:
- // test.php
-
-// ... $user->Phonenumbers[]->phonenumber = '123 123';
+// test.php
+$user->Phonenumbers[]->phonenumber = '123 123';
$user->Phonenumbers[]->phonenumber = '456 123';
$user->Phonenumbers[]->phonenumber = '123 777';
Now we can easily save the user and the associated phonenumbers:
- // test.php
-
-// ... $user->save();
+// test.php
+$user->save();
Another way to easily create a link between two related components is by
-using ``Doctrine_Record::link()``. It often happens that you have two
+using :php:meth:`Doctrine_Record::link`. It often happens that you have two
existing records that you would like to relate (or link) to one another.
In this case, if there is a relation defined between the involved record
classes, you only need the identifiers of the related record(s):
Lets create a few new ``Phonenumber`` objects and keep track of the new
phone number identifiers:
- // test.php
-
-// ... $phoneIds = array();
+// test.php
+$phoneIds = array();
$phone1 = new Phonenumber(); $phone1['phonenumber'] = '555 202 7890';
$phone1->save();
@@ -245,8 +242,7 @@ $phoneIds[] = $phone2['id'];
Let's link the phone numbers to the user, since the relation to
``Phonenumbers`` exists for the ``User`` record
- // test.php
-
+// test.php
$user = new User(); $user['username'] = 'jwage'; $user['password'] =
'changeme'; $user->save();
@@ -257,50 +253,44 @@ If a relation to the ``User`` record class is defined for the
First create a user to work with:
- // test.php
-
-// ... $user = new User(); $user['username'] = 'jwage';
+// test.php
+$user = new User(); $user['username'] = 'jwage';
$user['password'] = 'changeme'; $user->save();
Now create a new ``Phonenumber`` instance:
- // test.php
-
-// ... $phone1 = new Phonenumber(); $phone1['phonenumber'] = '555 202
+// test.php
+$phone1 = new Phonenumber(); $phone1['phonenumber'] = '555 202
7890'; $phone1->save();
Now we can link the ``User`` to our ``Phonenumber``:
- // test.php
-
-// ... :code:`phone1->link('User', array(`\ user['id']));
+// test.php
+$phone1->link('User', array($user['id']));
We can create another phone number:
- // test.php
-
-// ... $phone2 = new Phonenumber(); $phone2['phonenumber'] = '555 100
+// test.php
+$phone2 = new Phonenumber(); $phone2['phonenumber'] = '555 100
7890'; $phone2->save();
Let's link this ``Phonenumber`` to our ``User`` too:
- // test.php
-
-// ... :code:`phone2->link('User', array(`\ user['id']));
+// test.php
+$phone2->link('User', array($user['id']));
--------------------------
Retrieving Related Records
--------------------------
-You can retrieve related records by the very same ``Doctrine_Record``
+You can retrieve related records by the very same :php:class:`Doctrine_Record`
methods as in the previous subchapter. Please note that whenever you
access a related component that isn't already loaded Doctrine uses one
``SQL SELECT`` statement for the fetching, hence the following example
executes three ``SQL SELECT``s.
- // test.php
-
-// ... $user = Doctrine\_Core::getTable('User')->find(1);
+// test.php
+$user = Doctrine_Core::getTable('User')->find(1);
echo $user->Email['address'];
@@ -309,9 +299,8 @@ echo $user->Phonenumbers[0]->phonenumber;
Much more efficient way of doing this is using DQL. The following
example uses only one SQL query for the retrieval of related components.
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->leftJoin('u.Email e') ->leftJoin('u.Phonenumbers p') ->where('u.id =
?', 1);
@@ -330,15 +319,16 @@ object / collection individually or by calling save on the object that
owns the other objects. You can also call
``Doctrine_Connection::flush`` which saves all pending objects.
- // test.php
-
-// ... $user->Email['address'] = 'koskenkorva@drinkmore.info';
+// test.php
+$user->Email['address'] = 'koskenkorva@drinkmore.info';
$user->Phonenumbers[0]['phonenumber'] = '123123';
$user->save();
- **NOTE** In the above example calling ``$user->save()`` saves the
+.. note::
+
+ In the above example calling :php:meth:`$user->save` saves the
``email`` and ``phonenumber``.
------------------------
@@ -352,32 +342,29 @@ one object to another.
You can clear all references by doing the following:
- // test.php
-
-// ... $user->clearRelated();
+// test.php
+$user->clearRelated();
Or you can clear a specific relationship:
- // test.php
-
-// ... $user->clearRelated('Email');
+// test.php
+$user->clearRelated('Email');
This is useful if you were to do something like the following:
- // test.php
-
-// ... if ($user->Email->exists()) { // User has e-mail } else { // User
+// test.php
+if ($user->Email->exists()) { // User has e-mail } else { // User
does not have a e-mail }
$user->clearRelated('Email');
Because Doctrine will automatically create a new ``Email`` object if the
user does not have one, we need to clear that reference so that if we
-were to call ``$user->save()`` it wouldn't save a blank ``Email`` record
+were to call :php:meth:`$user->save` it wouldn't save a blank ``Email`` record
for the ``User``.
We can simplify the above scenario even further by using the
-``relatedExists()`` method. This is so that you can do the above check
+:php:meth:`relatedExists` method. This is so that you can do the above check
with less code and not have to worry about clearing the unnecessary
reference afterwards.
@@ -388,32 +375,28 @@ User does not have a e-mail }
Deleting Related Records
------------------------
-You can delete related records individually be calling ``delete()`` on a
+You can delete related records individually be calling :php:meth:`delete` on a
record or on a collection.
Here you can delete an individual related record:
- // test.php
-
-// ... $user->Email->delete();
+// test.php
+$user->Email->delete();
You can delete an individual record from within a collection of records:
- // test.php
-
-// ... $user->Phonenumbers[3]->delete();
+// test.php
+$user->Phonenumbers[3]->delete();
You could delete the entire collection if you wanted:
- // test.php
-
-// ... $user->Phonenumbers->delete();
+// test.php
+$user->Phonenumbers->delete();
Or can just delete the entire user and all related objects:
- // test.php
-
-// ... $user->delete();
+// test.php
+$user->delete();
Usually in a typical web application the primary keys of the related
objects that are to be deleted come from a form. In this case the most
@@ -422,19 +405,20 @@ statement. Lets say we have once again ``Users`` and ``Phonenumbers``
with their relation being one-to-many. Deleting the given
``Phonenumbers`` for given user id can be achieved as follows:
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->delete('Phonenumber')
-->addWhere('user\_id = ?', 5) ->whereIn('id', array(1, 2, 3));
+// test.php
+$q = Doctrine_Query::create() ->delete('Phonenumber')
+->addWhere('user_id = ?', 5) ->whereIn('id', array(1, 2, 3));
$numDeleted = $q->execute();
Sometimes you may not want to delete the ``Phonenumber`` records but to
simply unlink the relations by setting the foreign key fields to null.
This can of course be achieved with DQL but perhaps to most elegant way
-of doing this is by using ``Doctrine_Record::unlink()``.
+of doing this is by using :php:meth:`Doctrine_Record::unlink`.
+
+.. note::
- **NOTE** Please note that the ``unlink()`` method is very smart. It
+ Please note that the :php:meth:`unlink` method is very smart. It
not only sets the foreign fields for related ``Phonenumbers`` to
null but it also removes all given ``Phonenumber`` references from
the ``User`` object.
@@ -443,9 +427,8 @@ Lets say we have a ``User`` who has three ``Phonenumbers`` (with
identifiers 1, 2 and 3). Now unlinking the ``Phonenumbers`` 1 and 3 can
be achieved as easily as:
- // test.php
-
-// ... $user->unlink('Phonenumbers', array(1, 3));
+// test.php
+$user->unlink('Phonenumbers', array(1, 3));
echo $user->Phonenumbers->count(); // 1
@@ -460,24 +443,24 @@ Testing the Existence of a Relation
The below example would return false because the relationship has not
been instantiated yet:
- // test.php
-
-// ... :code:`user = new User(); if (isset(`\ user->Email)) { // ... }
+// test.php
+$user = new User(); if (isset($user->Email)) { // ... }
Now the next example will return true because we instantiated the
``Email`` relationship:
- // test.php
-
-// ... $obj->Email = new Email();
+// test.php
+$obj->Email = new Email();
if(isset($obj->Email)) { // ... }
======================
Many-to-Many Relations
======================
- **CAUTION** Doctrine requires that Many-to-Many relationships be
+.. caution::
+
+ Doctrine requires that Many-to-Many relationships be
bi-directional. For example: both ``User`` must have many ``Groups``
and ``Group`` must have many ``User``.
@@ -490,20 +473,18 @@ through a ``GroupUser`` association class. When working with transient
(new) records the fastest way for adding a ``User`` and couple of
``Group``s for it is:
- // test.php
-
-// ... $user = new User(); $user->username = 'Some User';
+// test.php
+$user = new User(); $user->username = 'Some User';
$user->Groups[0]->username = 'Some Group'; $user->Groups[1]->username =
'Some Other Group'; $user->save();
However in real world scenarios you often already have existing groups,
where you want to add a given user. The most efficient way of doing this
is:
- // test.php
-
-// ... $groupUser = new GroupUser(); $groupUser->user\_id = $userId;
-$groupUser->group\_id = $groupId; $groupUser->save();
+// test.php
+$groupUser = new GroupUser(); $groupUser->user_id = $userId;
+$groupUser->group_id = $groupId; $groupUser->save();
---------------
Deleting a Link
@@ -513,10 +494,9 @@ 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 through the Query API.
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->delete('UserGroup')
-->addWhere('user\_id = ?', 5) ->whereIn('group\_id', array(1, 2));
+// test.php
+$q = Doctrine_Query::create() ->delete('UserGroup')
+->addWhere('user_id = ?', 5) ->whereIn('group_id', array(1, 2));
$deleted = $q->execute();
@@ -525,24 +505,21 @@ 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.
- // test.php
-
-// ... $user = Doctrine\_Core::getTable('User')->find(5);
+// test.php
+$user = Doctrine_Core::getTable('User')->find(5);
$user->unlink('Group', array(1, 2)); $user->save();
You can also unlink ALL relationships to ``Group`` by omitting the
second argument:
- // test.php
-
-// ... $user->unlink('Group');
+// test.php
+$user->unlink('Group');
While the obvious and convenient way of deleting a link between ``User``
and ``Group`` would be the following, you still should NOT do this:
- // test.php
-
-// ... $user = Doctrine\_Core::getTable('User')->find(5);
+// test.php
+$user = Doctrine_Core::getTable('User')->find(5);
$user->GroupUser->remove(0)->remove(1); $user->save();
This is due to a fact that the call to ``$user->GroupUser`` loads all
@@ -569,11 +546,10 @@ hydrated.
Lets consider we have ``Users`` and ``Phonenumbers`` with their relation
being one-to-many. Now consider the following plain sql query:
- // test.php
-
-// ... $sql = 'SELECT u.id, u.username, p.phonenumber FROM user u LEFT
-JOIN phonenumber p ON u.id = p.user\_id'; $results =
-:code:`conn->getDbh()->fetchAll(`\ sql);
+// test.php
+$sql = 'SELECT u.id, u.username, p.phonenumber FROM user u LEFT
+JOIN phonenumber p ON u.id = p.user_id'; $results =
+$conn->getDbh()->fetchAll($sql);
If you are familiar with these kind of one-to-many joins it may be
familiar to you how the basic result set is constructed. Whenever the
@@ -602,14 +578,13 @@ other things such as:
Now consider the DQL equivalent of the SQL query we used:
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.id, u.username,
+// test.php
+$q = Doctrine_Query::create() ->select('u.id, u.username,
p.phonenumber') ->from('User u') ->leftJoin('u.Phonenumbers p');
-$results = $q->execute(array(), Doctrine\_Core::HYDRATE\_ARRAY);
+$results = $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
-print\_r($results);
+print_r($results);
The structure of this hydrated array would look like:
@@ -640,7 +615,7 @@ The structure of this hydrated array would look like:
This structure also applies to the hydration of objects(records) which
is the default hydration mode of Doctrine. The only differences are that
-the individual elements are represented as ``Doctrine_Record`` objects
+the individual elements are represented as :php:class:`Doctrine_Record` objects
and the arrays converted into ``Doctrine_Collection`` objects. Whether
dealing with arrays or objects you can:
@@ -664,29 +639,27 @@ smart identifier caching solution.
you fetch an object and modify some of its properties, then re-fetch
that same object later, the modified properties will be overwritten
by default. You can change this behavior by changing the
- ``ATTR\_HYDRATE_OVERWRITE`` attribute to ``false``.
+ ``ATTR_HYDRATE_OVERWRITE`` attribute to ``false``.
--------------
Sample Queries
--------------
**Count number of records for a relationship:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.\*, COUNT(DISTINCT
-p.id) AS num\_phonenumbers') ->from('User u') ->leftJoin('u.Phonenumbers
+// test.php
+$q = Doctrine_Query::create() ->select('u.\*, COUNT(DISTINCT
+p.id) AS num_phonenumbers') ->from('User u') ->leftJoin('u.Phonenumbers
p') ->groupBy('u.id');
$users = $q->fetchArray();
-echo $users[0]['Phonenumbers'][0]['num\_phonenumbers'];
+echo $users[0]['Phonenumbers'][0]['num_phonenumbers'];
**Retrieve Users and the Groups they belong to:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->leftJoin('u.Groups g');
$users = $q->fetchArray();
@@ -695,181 +668,164 @@ foreach ($users[0]['Groups'] as $group) { echo $group['name']; }
**Simple WHERE with one parameter value:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->where('u.username = ?', 'jwage');
$users = $q->fetchArray();
**Multiple WHERE with multiple parameters values:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->leftJoin('u.Phonenumbers p') ->where('u.username = ? AND p.id = ?',
array(1, 1));
$users = $q->fetchArray();
.. tip::
- You can also optionally use the ``andWhere()`` method to add
+ You can also optionally use the :php:meth:`andWhere` method to add
to the existing where parts.
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->leftJoin('u.Phonenumbers p') ->where('u.username = ?', 1)
->andWhere('p.id = ?', 1);
$users = $q->fetchArray();
-**Using ``whereIn()`` convenience method:**
-
- // test.php
+**Using :php:meth:`whereIn` convenience method:**
-// ... $q = Doctrine\_Query::create() ->from('User u') ->whereIn('u.id',
+// test.php
+$q = Doctrine_Query::create() ->from('User u') ->whereIn('u.id',
array(1, 2, 3));
$users = $q->fetchArray();
**The following is the same as above example:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u') ->where('u.id IN
+// test.php
+$q = Doctrine_Query::create() ->from('User u') ->where('u.id IN
(1, 2, 3)');
$users = $q->fetchArray();
**Using DBMS function in your WHERE:**
- // test.php
-
-// ... $userEncryptedKey = 'a157a558ac00449c92294c7fab684ae0'; $q =
-Doctrine\_Query::create() ->from('User u')
-->where("MD5(CONCAT(u.username, 'secret\_key')) = ?",
+// test.php
+$userEncryptedKey = 'a157a558ac00449c92294c7fab684ae0'; $q =
+Doctrine_Query::create() ->from('User u')
+->where("MD5(CONCAT(u.username, 'secret_key')) = ?",
$userEncryptedKey);
$user = $q->fetchOne();
-$q = Doctrine\_Query::create() ->from('User u')
+$q = Doctrine_Query::create() ->from('User u')
->where('LOWER(u.username) = LOWER(?)', 'jwage');
$user = $q->fetchOne();
**Limiting result sets using aggregate functions. Limit to users with
more than one phonenumber:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.\*, COUNT(DISTINCT
-p.id) AS num\_phonenumbers') ->from('User u') ->leftJoin('u.Phonenumbers
-p') ->having('num\_phonenumbers > 1') ->groupBy('u.id');
+// test.php
+$q = Doctrine_Query::create() ->select('u.\*, COUNT(DISTINCT
+p.id) AS num_phonenumbers') ->from('User u') ->leftJoin('u.Phonenumbers
+p') ->having('num_phonenumbers > 1') ->groupBy('u.id');
$users = $q->fetchArray();
**Join only primary phonenumbers using WITH:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
-->leftJoin('u.Phonenumbers p WITH p.primary\_num = ?', true);
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
+->leftJoin('u.Phonenumbers p WITH p.primary_num = ?', true);
$users = $q->fetchArray();
**Selecting certain columns for optimization:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.username, p.phone')
+// test.php
+$q = Doctrine_Query::create() ->select('u.username, p.phone')
->from('User u') ->leftJoin('u.Phonenumbers p');
$users = $q->fetchArray();
**Using a wildcard to select all ``User`` columns but only one
``Phonenumber`` column:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.\*, p.phonenumber')
+// test.php
+$q = Doctrine_Query::create() ->select('u.\*, p.phonenumber')
->from('User u') ->leftJoin('u.Phonenumbers p');
$users = $q->fetchArray();
**Perform DQL delete with simple WHERE:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->delete('Phonenumber')
-->addWhere('user\_id = 5');
+// test.php
+$q = Doctrine_Query::create() ->delete('Phonenumber')
+->addWhere('user_id = 5');
$deleted = $q->execute();
**Perform simple DQL update for a column:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->update('User u')
-->set('u.is\_active', '?', true) ->where('u.id = ?', 1);
+// test.php
+$q = Doctrine_Query::create() ->update('User u')
+->set('u.is_active', '?', true) ->where('u.id = ?', 1);
$updated = $q->execute();
**Perform DQL update with DBMS function. Make all usernames lowercase:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->update('User u')
+// test.php
+$q = Doctrine_Query::create() ->update('User u')
->set('u.username', 'LOWER(u.username)');
$updated = $q->execute();
**Using mysql LIKE to search for records:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->where('u.username LIKE ?', '%jwage%');
$users = $q->fetchArray();
**Use the INDEXBY keyword to hydrate the data where the key of record
entry is the name of the column you assign:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u INDEXBY
+// test.php
+$q = Doctrine_Query::create() ->from('User u INDEXBY
u.username');
$users = $q->fetchArray();
**Now we can print the user with the username of jwage:**
- // test.php
-
-// ... print\_r($users['jwage']);
+// test.php
+print_r($users['jwage']);
**Using positional parameters**
- $q = Doctrine\_Query::create() ->from('User u') ->where('u.username =
+ $q = Doctrine_Query::create() ->from('User u') ->where('u.username =
?', array('Arnold'));
$users = $q->fetchArray();
**Using named parameters**
- $q = Doctrine\_Query::create() ->from('User u') ->where('u.username =
+ $q = Doctrine_Query::create() ->from('User u') ->where('u.username =
:username', array(':username' => 'Arnold'));
$users = $q->fetchArray();
**Using subqueries in your WHERE. Find users not in group named Group
2:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u') ->where('u.id NOT
+// test.php
+$q = Doctrine_Query::create() ->from('User u') ->where('u.id NOT
IN (SELECT u.id FROM User u2 INNER JOIN u2.Groups g WHERE g.name = ?)',
'Group 2');
@@ -883,19 +839,17 @@ $users = $q->fetchArray();
**Use INNER JOIN to retrieve users who have groups, excluding the group
named Group 2**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->innerJoin('u.Groups g WITH g.name != ?', 'Group 2')
$users = $q->fetchArray();
**Use WHERE condition to retrieve users who have groups, excluding the
group named Group 2**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u')
+// test.php
+$q = Doctrine_Query::create() ->from('User u')
->leftJoin('u.Groups g') ->where('g.name != ?', 'Group 2');
$users = $q->fetchArray();
@@ -906,26 +860,24 @@ query:
**First lets create a sample query to test with:**
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->from('User u');
+// test.php
+$q = Doctrine_Query::create() ->from('User u');
-**You can use array hydration with the ``fetchArray()`` method:**
+**You can use array hydration with the :php:meth:`fetchArray` method:**
$users = $q->fetchArray();
**You can also use array hydration by specifying the hydration method to
-the second argument of the ``execute()`` method:**
-
- // test.php
+the second argument of the :php:meth:`execute` method:**
-// ... $users = $q->execute(array(), Doctrine\_Core::HYDRATE\_ARRAY)
+// test.php
+$users = $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY)
**You can also specify the hydration method by using the
-``setHydrationMethod()`` method:**
+:php:meth:`setHydrationMethod` method:**
$users =
-$q->setHydrationMode(Doctrine\_Core::HYDRATE\_ARRAY)->execute(); // So
+$q->setHydrationMode(Doctrine_Core::HYDRATE_ARRAY)->execute(); // So
is this
.. note::
@@ -939,9 +891,8 @@ is this
**Sometimes you may want to totally bypass hydration and return the raw
data that PDO returns:**
- // test.php
-
-// ... $users = $q->execute(array(), Doctrine\_Core::HYDRATE\_NONE);
+// test.php
+$users = $q->execute(array(), Doctrine_Core::HYDRATE_NONE);
.. tip::
@@ -950,9 +901,8 @@ data that PDO returns:**
**If you want to just fetch one record from the query:**
- // test.php
-
-// ... $user = $q->fetchOne();
+// test.php
+$user = $q->fetchOne();
// Fetch all and get the first from collection $user =
$q->execute()->getFirst();
@@ -968,19 +918,17 @@ can load the unloaded fields lazily.
In the following example we fetch all the Users with the ``username``
field loaded directly. Then we lazy load the password field:
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.username')
+// test.php
+$q = Doctrine_Query::create() ->select('u.username')
->from('User u') ->where('u.id = ?', 1)
$user = $q->fetchOne();
The following lazy-loads the ``password`` field and executes one
additional database query to retrieve the value:
- // test.php
-
-// ... $user->password;
+// test.php
+$user->password;
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
@@ -993,103 +941,95 @@ fetching.
Arrays and Objects
==================
-``Doctrine\_Record`` and ``Doctrine_Collection`` provide methods to
-facilitate working with arrays: ``toArray()``, ``fromArray()`` and
-``synchronizeWithArray()``.
+:php:class:`Doctrine_Record` and ``Doctrine_Collection`` provide methods to
+facilitate working with arrays: :php:meth:`toArray`, :php:meth:`fromArray` and
+:php:meth:`synchronizeWithArray`.
--------
To Array
--------
-The ``toArray()`` method returns an array representation of your records
+The :php:meth:`toArray` method returns an array representation of your records
or collections. It also accesses the relationships the objects may have.
If you need to print a record for debugging purposes you can get an
array representation of the object and print that.
- // test.php
-
-// ... print\_r($user->toArray());
+// test.php
+print_r($user->toArray());
If you do not want to include the relationships in the array then you
need to pass the ``$deep`` argument with a value of //false//:
- // test.php
-
-// ... print\_r($user->toArray(false));
+// test.php
+print_r($user->toArray(false));
----------
From Array
----------
If you have an array of values you want to use to fill a record or even
-a collection, the ``fromArray()`` method simplifies this common task.
-
- // test.php
+a collection, the :php:meth:`fromArray` method simplifies this common task.
-// ... $data = array( 'name' => 'John', 'age' => '25', 'Emails' =>
+// test.php
+$data = array( 'name' => 'John', 'age' => '25', 'Emails' =>
array( array('address' => 'john@mail.com'), array('address' =>
'john@work.com') );
-$user = new User(); :code:`user->fromArray(`\ data); $user->save();
+$user = new User(); $user->fromArray($data); $user->save();
----------------------
Synchronize With Array
----------------------
-``synchronizeWithArray()`` allows you to... well, synchronize a record
+:php:meth:`synchronizeWithArray` allows you to... well, synchronize a record
with an array. So if have an array representation of your model and
modify a field, modify a relationship field or even delete or create a
relationship, this changes will be applied to the record.
- // test.php
-
-// ... $q = Doctrine\_Query::create() ->select('u.*, g.*') ->from('User
+// test.php
+$q = Doctrine_Query::create() ->select('u.*, g.*') ->from('User
u') ->leftJoin('u.Groups g') ->where('id = ?', 1);
$user = $q->fetchOne();
Now convert it to an array and modify some of the properties:
- // test.php
-
-// ... $arrayUser = $user->toArray(true);
+// test.php
+$arrayUser = $user->toArray(true);
$arrayUser['username'] = 'New name'; $arrayUser['Group'][0]['name'] =
'Renamed Group'; $arrayUser['Group'][] = array('name' => 'New Group');
Now use the same query to retrieve the record and synchronize the record
-with the ``$arrayUser`` variable:
-
- // test.php
+with the ``$arrayUser`` variable::
-// ... $user = Doctrine\_Query::create() ->select('u.*, g.*')
-->from('User u') ->leftJoin('u.Groups g') ->where('id = ?', 1)
-->fetchOne();
+ // test.php
+ $user = Doctrine_Query::create() ->select('u.*, g.*')
+ ->from('User u') ->leftJoin('u.Groups g') ->where('id = ?', 1)
+ ->fetchOne();
-:code:`user->synchronizeWithArray(`\ arrayUser); $user->save();
+ $user->synchronizeWithArray($arrayUser); $user->save();
==========================
Overriding the Constructor
==========================
Sometimes you want to do some operations at the creation time of your
objects. Doctrine doesn't allow you to override the
-``Doctrine\_Record::\__construct()`` method but provides an
-alternative:
+:php:meth:`Doctrine_Record::__construct` method but provides an
+alternative::
- class User extends Doctrine\_Record { public function construct() {
-$this->username = 'Test Name'; $this->doSomething(); }
+ class User extends Doctrine_Record { public function construct() {
+ $this->username = 'Test Name'; $this->doSomething(); }
-::
+ public function doSomething()
+ {
+ // ...
+ }
- public function doSomething()
- {
// ...
- }
-
- // ...
-}
+ }
The only drawback is that it doesn't provide a way to pass parameters to
the constructor.
@@ -1101,5 +1041,4 @@ Conclusion
By now we should know absolutely everything there is to know about
models. We know how to create them, load them and most importantly we
know how to use them and work with columns and relationships. Now we are
-ready to move on to learn about how to use the [doc
-dql-doctrine-query-language :name].
+ready to move on to learn about how to use the :doc:`dql-doctrine-query-language`.
View
6 source/ja/manual/extensions.rst
@@ -1,3 +1,9 @@
+.. vim: set ts=4 sw=4 tw=79 :
+
+**********
+Extensions
+**********
+
Doctrineエクステンションは任意のプロジェクトに入れて有効にできる再利用可能なDoctrineエクステンションを作成する方法です。エクステンションはコードの命名や、オートロードなどDoctrineの標準に従う単なるコードです。
エクステンションを使うには最初にどこにエクステンションがあるのかDoctrineにわかるように設定しなければなりません:

0 comments on commit 3dc2fe8

Please sign in to comment.