-
Notifications
You must be signed in to change notification settings - Fork 52
Ru:QuickStart
(Тексты и примеры взяты из статьи на habrahabr.ru от Артема Ласкова, переработаны и дополнены)
Эта часть фрейморка, расположенная в папке meta предоставляет возможность описать сущности и их свойства, а также создать необходимые классы вашего будущего приложения. Схема оформляется в формате XML, которую можно валидировать по приложенной meta.dtd.
Пример схемы:
<?xml version="1.0"?>
<!DOCTYPE metaconfiguration SYSTEM "meta.dtd">
<metaconfiguration>
<classes>
<class name="Author" table="authors">
<properties>
<identifier/>
<property name="name" type="String" size="50" required="true"/>
</properties>
<pattern name="StraightMapping"/>
</class>
<class name="Book" table="books">
<properties>
<identifier/>
<property name="title" type="String" size="50" required="true"/>
<property name="author" type="Author" relation="OneToOne" required="true" fetch="lazy"/>
</properties>
<pattern name="StraightMapping"/>
</class>
</classes>
</metaconfiguration>
Что здесь интересного:
-
Для каждой сущности указывается какими свойствами она обладает и какой их тип. На основе этого, meta-builder порекомендует какие изменения в схеме БД нужно сделать, а также этим можно воспользоваться для валидации данных объектов по форме (Form).
-
Нужно указывать связи (relation) между объектами в мете. Эти связи затем будут отражены в сгенерированных классах. Возможные связи между объектами - OneToOne, OneToMany и ManyToMany.
-
OneToOne используется когда в таблице объекта есть поле, связывающее его с другим объектом.
-
OneToMany - когда такого поля нет, но другой объект ссылается на текущий (связь в обратном направлении).
-
ManyToMany - связь двух таблиц через дополнительную таблицу, реализующую данную связь (составной primary key на двух полях, ссылающихся на идентификаторы связываемых таблиц)
-
Pattern — представляет собой шаблон класса.
-
StraightMapping — прямой маппинг объекта на одну запись в таблице БД.
-
DictionaryClass — тот же StraightMapping, но объекту добавляется property name.
-
EnumerationClass — перечисление. Класс, который не имеет таблицы в БД, а является линейным списком (id => name). Применимо для поля таблицы, число состояний которого строго определено (например, месяца, знаки зодиака, и т. д.). Может использоваться в другом объекте только через отношение OneToOne.
-
AbstractClass — абстрактный класс. Используется для определения в схеме абстрактных классов, от которых в этой же схеме другие классы будет наследоваться.
-
SpookedClass — класс описывается и объявляется в мета, но не генерируется. Таким образом сам класс должен быть создан вручную. Используется, например, когда часть классов берется из другого репозитория подключеного через submodule (git) или svn:externals.
-
SpookedEnumeration — тоже что и SpookedClass, но для Enumeration.
-
ValueObject — класс не связан ни с какой таблицей в базе и у него не генерируется DAO. Может использоваться в другом объекте только через отношение OneToOne.
-
Параметр fetch при связывании объектов — это указание на способ загрузки связанных объектов при загрузке текущего. Есть три способа связывания объектов:
-
fetch="join" - При загрузке из базы данных объекта данные связанных объектов будут загружены тем же запросом через join. Применимо на небольших базах и нежелательно использовать при кешировании данных. Если fetch не указан, значит по умолчанию используется join.
-
fetch="cascade" - Объект будут загружен отдельным запросом сразу после сборки основного объекта.
-
fetch="lazy" - При загрзке основного объекта связанный не будет загружен. Загрузка связанного объекта будет происходить по id только при попытке получения его из основного объекта.
Помимо самого xml для генерации объектов нужен файл конфигурации проекта на php. В корне onPHP есть файл global.inc.php.tpl, который является шаблоном для файла конфигурации. Копируем его и изменяем следующим образом:
- добаляем константу PATH_CLASSES — место, там, где у вас будут лежать сгенерированные классы.
- добавляем в set_include_path():
set_include_path(
get_include_path()
.PATH_CLASSES.PATH_SEPARATOR
.PATH_CLASSES.'Auto'.PATH_SEPARATOR
.PATH_CLASSES.'Auto'.DIRECTORY_SEPARATOR.'Business'.PATH_SEPARATOR
.PATH_CLASSES.'Auto'.DIRECTORY_SEPARATOR.'DAOs'.PATH_SEPARATOR
.PATH_CLASSES.'Auto'.DIRECTORY_SEPARATOR.'Proto'.PATH_SEPARATOR
.PATH_CLASSES.'Business'.PATH_SEPARATOR
.PATH_CLASSES.'DAOs'.PATH_SEPARATOR
.PATH_CLASSES.'Proto'.PATH_SEPARATOR
);
- добавляем параметры соединения с БД:
DBPool::me()->setDefault(
DB::spawn('PgSQL', 'user', 'password', 'localhost', 'dbname')->
setEncoding('utf-8')
);
В папке meta есть скрипт bin/build.php, который с помощью рядом находящихся классов и превращает xml-схему в классы. Его следует использовать так:
Usage: build.php [options] [project-configuration-file.inc.php] [metaconfiguration.xml]
Если meta сгенерировалась успешно, то в каталоге, который был указан в константе PATH_CLASSES должны были появиться 4 подкаталога:
- Auto с классами, которые содержат не подлежащие изменению классы и которые перегенерируются всякий раз при запуске build.php;
- Business: бизнес-объекты, которые можно и нужно изменять, дополняя необходимой логикой;
- DAOs: Data Access Objects, объекты доступа к данным, в которые можно поместить часто используемые выборки объектов из базы;
- Proto: классы, описывающие прототипы объектов, их свойства.
Пример использования созданных классов:
require "global.inc.php";
DBPool::me()->getLink()->begin();
$author = Author::create()->
setName('Martin Fowler');
Author::dao()->add($author);
$book = Book::create()->
setTitle('Patterns of Enterprise Application Architecture')->
setAuthor($author);
Book::dao()->add($book);
DBPool::me()->getLink()->commit();