301 lines
7.9 KiB
ReStructuredText
301 lines
7.9 KiB
ReStructuredText
Doctrine explained in 10 quick steps
|
|
====================================
|
|
|
|
You can follow this tutorial step by step yourself and end up with a simple
|
|
Doctrine application. It assumed that you installed Doctrine via PEAR. To work
|
|
with another setup just take a look into the :doc:`Installation help
|
|
<../reference/introduction>`.
|
|
|
|
1. Allows you to map PHP Objects to database tables
|
|
---------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
class Post
|
|
{
|
|
protected $id;
|
|
protected $title;
|
|
protected $body;
|
|
}
|
|
|
|
::
|
|
|
|
mysql> CREATE TABLE Post (id INT AUTO_INCREMENT PRIMARY KEY, title
|
|
VARCHAR(255), body TEXT);
|
|
|
|
mysql> DESCRIBE Post;
|
|
+-------+--------------+------+-----+---------+----------------+
|
|
| Field | Type | Null | Key | Default | Extra |
|
|
+-------+--------------+------+-----+---------+----------------+
|
|
| id | int(11) | NO | PRI | NULL | auto_increment |
|
|
| title | varchar(255) | YES | | NULL | |
|
|
| body | text | YES | | NULL | |
|
|
+-------+--------------+------+-----+---------+----------------+
|
|
|
|
.. tip::
|
|
|
|
Objects mapped with Doctrine are called Entities. They don't need to extend
|
|
a base class and even allow constructors with required parameters.
|
|
|
|
You are responsible for implementing getters, setters and constructors of
|
|
your entities yourself. This gives you full freedom to design your business
|
|
objects as you wish.
|
|
|
|
2. Using Annotations, XML or YAML for Metadata Mapping
|
|
------------------------------------------------------
|
|
|
|
.. configuration-block::
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
/** @Entity **/
|
|
class Post
|
|
{
|
|
/** @Id @GeneratedValue @Column(type="integer") **/
|
|
protected $id;
|
|
/** @Column(type="string") **/
|
|
protected $title;
|
|
/** @Column(type="text") **/
|
|
protected $body;
|
|
}
|
|
|
|
.. code-block:: yaml
|
|
|
|
Post:
|
|
type: entity
|
|
id:
|
|
id:
|
|
type: integer
|
|
generator:
|
|
strategy: AUTO
|
|
fields:
|
|
title:
|
|
type: string
|
|
body:
|
|
type: text
|
|
|
|
.. code-block:: xml
|
|
|
|
<?xml version="1.0" ?>
|
|
<doctrine-mapping>
|
|
<entity name="Post">
|
|
<id name="id type="integer">
|
|
<generator strategy="AUTO" />
|
|
</id>
|
|
<field name="title" type="string" />
|
|
<field name="body" type="text" />
|
|
</entity>
|
|
</doctrine-mapping>
|
|
|
|
|
|
3. Object References map to Foreign keys
|
|
----------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
/** @Entity **/
|
|
class Post
|
|
{
|
|
// .. previous code
|
|
|
|
/**
|
|
* @ManyToOne(targetEntity="User")
|
|
**/
|
|
protected $author;
|
|
|
|
public function __construct(User $user)
|
|
{
|
|
$this->author = $user;
|
|
}
|
|
}
|
|
|
|
/** @Entity **/
|
|
class User
|
|
{
|
|
/** @Id @GeneratedValue @Column(type="integer") **/
|
|
protected $id;
|
|
/** @Column(type="string") **/
|
|
protected $name;
|
|
}
|
|
|
|
$user = new User();
|
|
$post = new Post($user);
|
|
|
|
|
|
::
|
|
|
|
mysql> CREATE TABLE Post (id INT AUTO_INCREMENT PRIMARY KEY, title
|
|
VARCHAR(255), body TEXT, author_id INT);
|
|
|
|
mysql> CREATE TABLE User (id INT AUTO_INCREMENT PRIMARY KEY, name
|
|
VARCHAR(255));
|
|
|
|
mysql> ALTER TABLE Post ADD FOREIGN KEY (author_id) REFERENCES User (id);
|
|
|
|
mysql> DESCRIBE Post;
|
|
+-----------+--------------+------+-----+---------+----------------+
|
|
| Field | Type | Null | Key | Default | Extra |
|
|
+-----------+--------------+------+-----+---------+----------------+
|
|
| id | int(11) | NO | PRI | NULL | auto_increment |
|
|
| title | varchar(255) | YES | | NULL | |
|
|
| body | text | YES | | NULL | |
|
|
| author_id | int(11) | YES | MUL | NULL | |
|
|
+-----------+--------------+------+-----+---------+----------------+
|
|
|
|
.. tip::
|
|
|
|
This means you don't have to mess with foreign keys yourself, just use
|
|
references to connect objects with each other and let Doctrine handle the
|
|
rest.
|
|
|
|
4. Collections handle sets of objects references
|
|
------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
|
|
class Post
|
|
{
|
|
// .. previous code
|
|
|
|
/**
|
|
* @OneToMany(targetEntity="Comment", mappedBy="post",
|
|
* cascade={"persist"})
|
|
**/
|
|
protected $comments;
|
|
|
|
public function __construct(User $author)
|
|
{
|
|
$this->author = $author;
|
|
$this->posts = new ArrayCollection();
|
|
}
|
|
|
|
public function addComment($text)
|
|
{
|
|
$this->comments[] = new Comment($this, $text);
|
|
}
|
|
}
|
|
|
|
/** @Entity **/
|
|
class Comment
|
|
{
|
|
/** @Id @GeneratedValue @Column(type="integer") **/
|
|
protected $id;
|
|
/** @Column(type="text") **/
|
|
protected $comment;
|
|
/**
|
|
* @ManyToOne(targetEntity="Post", inversedBy="comments")
|
|
**/
|
|
protected $post;
|
|
|
|
public function __construct(Post $post, $text)
|
|
{
|
|
$this->post = $post;
|
|
$this->comment = $text;
|
|
}
|
|
}
|
|
|
|
$post->addComment("First..");
|
|
$post->addComment("Second!");
|
|
|
|
5. Easy to setup for the default configuration case
|
|
---------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
|
|
use Doctrine\ORM\Tools\Setup;
|
|
use Doctrine\ORM\EntityManager;
|
|
|
|
require_once 'Doctrine/Common/ClassLoader.php';
|
|
|
|
$loader = new \Doctrine\Common\ClassLoader("Doctrine");
|
|
$loader->register();
|
|
|
|
$dbParams = array(
|
|
'driver' => 'pdo_mysql',
|
|
'user' => 'root',
|
|
'password' => '',
|
|
'dbname' => 'tests'
|
|
);
|
|
$path = 'path/to/entities';
|
|
$config = Setup::createAnnotationMetadataConfiguration($path, true);
|
|
$entityManager = EntityManager::create($dbParams, $config);
|
|
|
|
|
|
6. The EntityManager needs to know about your new objects
|
|
---------------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
|
|
$entityManager->persist($user);
|
|
$entityManager->persist($post);
|
|
|
|
.. warning::
|
|
|
|
This does not lead to INSERT/UPDATE statements yet. You need to call
|
|
EntityManager#flush()
|
|
|
|
|
|
7. EntityManager#flush() batches SQL INSERT/UPDATE/DELETE statements
|
|
--------------------------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
|
|
$entityManager->flush();
|
|
|
|
.. tip::
|
|
|
|
Batching all write-operations against the database allows Doctrine to wrap all
|
|
statements into a single transaction and benefit from other performance
|
|
optimizations such as prepared statement re-use.
|
|
|
|
8. You can fetch objects from the database through the EntityManager
|
|
--------------------------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
|
|
$post = $entityManager->find("Post", $id);
|
|
|
|
9. ..or through a Repository
|
|
----------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
|
|
$authorRepository = $entityManager->getRepository("Author");
|
|
$author = $authorRepository->find($authorId);
|
|
|
|
$postRepository = $entityManager->getRepository("Post");
|
|
$post = $postRepository->findOneBy(array("title" => "Hello World!"));
|
|
|
|
$posts = $repository->findBy(
|
|
array("author" => $author),
|
|
array("title" => "ASC")
|
|
);
|
|
|
|
|
|
10. Or complex finder scenarios with the Doctrine Query Language
|
|
----------------------------------------------------------------
|
|
|
|
.. code-block:: php
|
|
|
|
<?php
|
|
// all posts and their comment count
|
|
$dql = "SELECT p, count(c.id) AS comments " .
|
|
"FROM Post p JOIN p.comments GROUP BY p";
|
|
$results = $entityManager->createQuery($dql)->getResult();
|