Что такое Entities?
Entities (классы модели) - объекты PHP, которым не надо расширять или реализовывать никакие абстрактные классы или интерфейсы. Есть некоторые ограничения, например,
- они не могут быть final или иметь методы final;
- реализовывать clone или wakeup;
... Entity имеет свойства сохраняемые в базе данных и получаемые из нее.
Пример модели: BUG TRACKER
Требования: Ошибка имеет описание, дату создания, статус, корреспондента и разработчика Ошибка может происходить с разными продуктами (платформами) Продукт имеет название Корреспондент и разработчик - оба пользователи системы Пользователь может сообщить об ошибке Назначенный разработчик должен исправить ошибку Пользователь может видеть все ошибки о которых он сообщил или для решения которых он назначен Ошибки могут быть представлены как список с постраничным выводом
Создание проекта
Установите Doctrine2
$ pear channel-discover pear.doctrine-project.org $ pear install --alldeps doctrine/DoctrineORMСоздайте каталог проекта
$ mkdir project $ cd projectСтруктура должна быть такой
project |-- config | |-- xml | `-- yaml `-- entities
Начало проектирования модели
Создайте классы
// Bug.php class Bug { protected $id; protected $description; protected $created; protected $status; } // Product.php class Product { protected $id; protected $name; public function getId() { return $this->id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } // User.php class User { protected $id; public $name; // public for educational purpose, see below public function getId() { return $this->id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } }Создание связей
// entities/Bug.php use Doctrine\Common\Collections\ArrayCollection; class Bug { // ... (previous code) protected $products = null; public function __construct() { $this->products = new ArrayCollection(); } } // entities/User.php use Doctrine\Common\Collections\ArrayCollection; class User { // ... (previous code) protected $reportedBugs = null; protected $assignedBugs = null; public function __construct() { $this->reportedBugs = new ArrayCollection(); $this->assignedBugs = new ArrayCollection(); } }Для отладки классов не используйте var_dump() и тд, используйте Doctrine\Common\Util\Debug::dump() Создаем связи между пользователем и ошибкой
// entities/Bug.php class Bug { // ... (previous code) protected $engineer; protected $reporter; public function setEngineer($engineer) { $engineer->assignedToBug($this); $this->engineer = $engineer; } public function setReporter($reporter) { $reporter->addReportedBug($this); $this->reporter = $reporter; } public function getEngineer() { return $this->engineer; } public function getReporter() { return $this->reporter; } } // entities/User.php class User { // ... (previous code) protected $reportedBugs = null; protected $assignedBugs = null; // Используется именование методов в прошедшем времени, // это обозначает что назначение уже произошло и // и методы используются лишь для обеспечения согласованности ссылки. // Очевидно что одностороннее использование методов // User::addReportedBug() и User::assignedToBug() // в пользовательском коде не добавит ошибку в коллекцию // в свойствах Bug::$reporter или Bug::$engineer. // Использование этих методов и вызов Doctrine не обновят // представление коллекций в базе данных. public function addReportedBug($bug) { $this->reportedBugs[] = $bug; } public function assignedToBug($bug) { $this->assignedBugs[] = $bug; } }
Метаданные отображения для классов модели
Далее надо добавить метаданные для Doctrine, чтобы классы модели могли быть сохранены в базе данных. Это можно сделать 3 способами: XML, YAML, аннотации. В первом и втором случае, мы создаем файлы и кладем их в каталоги project/config/xml и project/config/yaml соотвественно. В последнем - аннотации добавляются непосредственно в код класса. Пример для продукта
// entities/Product.php /** * @Entity @Table(name="products") **/ class Product { /** @Id @Column(type="integer") @GeneratedValue **/ protected $id; /** @Column(type="string") **/ protected $name; // .. (other code) } <!-- config/xml/Product.dcm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Product" table="products"> <id name="id" type="integer"> <generator strategy="AUTO" /> </id> <field name="name" type="string" /> </entity> </doctrine-mapping> # config/yaml/Product.dcm.yml Product: type: entity table: products id: id: type: integer generator: strategy: AUTO fields: name: type: stringДля поля id дерективы указывают на то, что будет использован механизм генерации родной для СУБД (AUTO INCREMENT для MySQL, например). Для Bug
// entities/Bug.php /** * @Entity @Table(name="bugs") **/ class Bug { /** * @Id @Column(type="integer") @GeneratedValue **/ protected $id; /** * @Column(type="string") **/ protected $description; /** * @Column(type="datetime") **/ protected $created; /** * @Column(type="string") **/ protected $status; /** * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") **/ protected $engineer; /** * @ManyToOne(targetEntity="User", inversedBy="reportedBugs") **/ protected $reporter; /** * @ManyToMany(targetEntity="Product") **/ protected $products; // ... (other code) } <!-- config/xml/Bug.dcm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Bug" table="bugs"> <id name="id" type="integer"> <generator strategy="AUTO" /> </id> <field name="description" type="text" /> <field name="created" type="datetime" /> <field name="status" type="string" /> <many-to-one target-entity="User" field="reporter" inversed-by="reportedBugs" /> <many-to-one target-entity="User" field="engineer" inversed-by="assignedBugs" /> <many-to-many target-entity="Product" field="products" /> </entity> </doctrine-mapping> # config/yaml/Bug.dcm.yml Bug: type: entity table: bugs id: id: type: integer generator: strategy: AUTO fields: description: type: text created: type: datetime status: type: string manyToOne: reporter: targetEntity: User inversedBy: reportedBugs engineer: targetEntity: User inversedBy: assignedBugs manyToMany: products: targetEntity: ProductТут определны две ссылки на сущность User. Имя класса связанной сущности задается тэгом targetEntity. Имеет место двунаправленная связь, поэтому с помощью тэга inversedBy указываем атрибут связанной сущности, соответствующей нашему объекту. И наконец для User
// entities/User.php /** * @Entity @Table(name="users") **/ class User { /** * @Id @GeneratedValue @Column(type="integer") * @var int **/ protected $id; /** * @Column(type="string") * @var string **/ protected $name; /** * @OneToMany(targetEntity="Bug", mappedBy="reporter") * @var Bug[] **/ protected $reportedBugs = null; /** * @OneToMany(targetEntity="Bug", mappedBy="engineer") * @var Bug[] **/ protected $assignedBugs = null; // .. (other code) } <!-- config/xml/User.dcm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="User" table="users"> <id name="id" type="integer"> <generator strategy="AUTO" /> </id> <field name="name" type="string" /> <one-to-many target-entity="Bug" field="reportedBugs" mapped-by="reporter" /> <one-to-many target-entity="Bug" field="assignedBugs" mapped-by="engineer" /> </entity> </doctrine-mapping> # config/xml/User.dcm.yml User: type: entity table: users id: id: type: integer generator: strategy: AUTO fields: name: type: string oneToMany: reportedBugs: targetEntity: Bug mappedBy: reporter assignedBugs: targetEntity: Bug mappedBy: engineerСвязи один-ко-многим уже определены на стороне владельца (Bug), поэтому поэтому просто указываем его атрибут с помощью тэга mappedBy.
Настройка EntityManager
Выборку и сохранение сущностей в базе данных обеспечивает EntityManager. Для этого его необходимо создать и настроить.
// bootstrap_doctrine.php // See :doc:`Configuration <../reference/configuration>` for up to date autoloading details. use Doctrine\ORM\Tools\Setup; require_once "Doctrine/ORM/Tools/Setup.php"; Setup::registerAutoloadPEAR(); // Create a simple "default" Doctrine ORM configuration for XML Mapping $isDevMode = true; $config = Setup::createXMLMetadataConfiguration(array(__DIR__."/config/xml"), $isDevMode); // or if you prefer yaml or annotations //$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/entities"), $isDevMode); //$config = Setup::createYAMLMetadataConfiguration(array(__DIR__."/config/yaml"), $isDevMode); // database configuration parameters $conn = array( 'driver' => 'pdo_sqlite', 'path' => __DIR__ . '/db.sqlite', ); // obtaining the entity manager $entityManager = \Doctrine\ORM\EntityManager::create($conn, $config);Продолжение следует (или нет) ...
Генерировать БД из объектов - по моему это ересь !
ОтветитьУдалитьНе уверен, что понимаю о чем вы ;-) Но в общем нахожу принцип orm довольно актуальным
Удалить