
Давненько уже «не брал в руки перо», но очень хочется систематизировать свои знания и написать, наверно, один из первых пошаговых руководств по работе с ORB (не знаю как точно, но я называю такие вещи — ActiveRecord) фрэймворком
xPDO (на котором построена MODx Revolution). Может быть это и не фрэймворком во всей мощи этого понимания, но по моему мнению с возложенными на себя задачами он справляется великолепно.
Что такое AR/ORM ?
Для тех кто в танке —
ru.wikipedia.org/wiki/ActiveRecord (http://ru.wikipedia.org/wiki/ORM)
А если простыми словами — ActiveRecord освобождает вам от необходимости писать SQL запросы вручную, и делать выборки, просто работайте с переменными-объектами, свойтсва объектов представляют «столбцы таблицы», экземпляры объектов — строки. (Вобще звучит мутно и непонятно, лучше один раз увидеть и полюбить навсегда :) )
Несколько месяцев назад я остро ощутил потребность в AR фрэймворке для уменьшения рутинной работы с базой данных в проектах не связанных с МОДх. Опенсорс вариантов существует, конечно же масса. Но полновесный фрэймворк (типа Zend Framework или Yii) мне тянуть не хотелось (для поставленных задач). Соответсвенно вспомнил про творение Джейсона Коварда — xPDO.
Долго я оттягивал момент разирательства и когда всё же решил — упёрся в самое больное место господ Коварда и МакКормика — осутствие внятных рабочих примеров в документации к их замечательным скриптам. (Наличие доволно объемной официальной документации
svn.modxcms.com/docs/display/xPDO20/Home мало проясняло ситуацию :) особенно в той части как работать с xPDO проекте вне MODx). Лично мне пришлось два раза перечитать почти все темы на форуме в разделе xPDO, чтобы «завести эту берданку» (честно был момент когда я хотел бросить эту гиблую затею :) ). Этим опытом и поделюсь ниже. (При этом настоятельно советую просмотреть оф. документацию т.к. я сейчас не буду вдаваться в подробности и тонкости, главное дать рабочий базовый пример)
Подготовительный этап
Для начала возьмём базу данных для экспериментов (можете взять любую вашу), я же экспериментирую на
Sakila sample database.
Как её скачать и установить расписано по ссылке (немножко через задницу всё делается, но зато в вашем распоряжении готовая громадная БД с множеством связей, можно практиковать очень изощренный запросы :) ).
Далее качаем сам скрипт
xPDO —
www.xpdo.org/downloads.html (на данный момент я взял xPDO-2.0.0-rc1).
Приступаем
Считаем, что БД вы установили правильно и через phpMyAdmin она нормально доступна. Считаем, что БД имеет имя "
sakila", имя пользователя БД "
root" и пароль тоже "
root".
Разархивируем xPDO наш тестовый сервер в папку "
xpdo", скажем.
Также создадим заранее папки
«models» и
«cache» рядом с «xpdo».
→ Создаем в корне рядом с папкой «xpdo» файл
«dbConnection.php» с содержимым
<?php
include("xpdo/xpdo.class.php");
$xpdo= new xPDO('mysql:host=localhost;dbname=sakila',"root","root",
array (
XPDO::OPT_CACHE_PATH => 'cache/',
XPDO::OPT_TABLE_PREFIX => '',
XPDO::OPT_HYDRATE_FIELDS => true,
XPDO::OPT_HYDRATE_RELATED_OBJECTS => true,
XPDO::OPT_HYDRATE_ADHOC_FIELDS => true,
XPDO::OPT_VALIDATE_ON_SAVE => true,
),
array (
PDO::ATTR_ERRMODE => PDO_ERRMODE_SILENT,
PDO::ATTR_PERSISTENT => false,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
)
);
?>
Здесь происходит создание объекта класса xPDO (с которым потом всё время и работать) в строке mysql:host=db_host;dbname=db_name',«db_login»,«db_pass» замените если требуется на ваши данные.
О предназначении остальных массивов можно почитать в официальной документации — сейчас важен только параметр XPDO::OPT_CACHE_PATH => 'cache/' он указывает на папку для кэша, которую мы создали выше (можете изменить если надо).
→ создаём файл
«dbGenerator.php» с содержимым
<?php
include("dbConnection.php");
$manager= $xpdo->getManager();
$generator= $manager->getGenerator();
$xml= $generator->writeSchema('models/MyDBModel.mysql.schema.xml', 'MyDBModel', 'xPDOObject', '');
?>
а теперь запустите скрипт dbGenerator.php (он произведет так называемый reverse-engineer схемы по уже готовой БД)
да вы видите белый экран броузера (если не произошло ошибки :)), но так и должно быть.
Откройте папку «models» и о чудо! там появился файл MyDBModel.mysql.schema.xml это файл схемы БД, его можно менять при необходимости о том, что и как можно менять тоже можно найти в документации (я честно говоря пока сам не полностью разобрался, поэтому не берусь учить, сейчас мы обойдёмся без изменений).
→ далее создаем файл
«dbParser.php» с содержимым
<?php
include("dbConnection.php");
$manager= $xpdo->getManager();
$generator= $manager->getGenerator();
$generator->parseSchema('models/MyDBModel.mysql.schema.xml','models/');
?>
запустив теперь этот файл вы проведёте так называемый forward-engineer ранее сгенерированной схемы в готовую к употреблению модель
загляните в папку «models» заметьте появившуюся папку «MyDBModel» — там и лежит модель нашей БД отформатированная специальным образом для быстрого и эффективного использования.
Этап подготовки закончен. Теперь радуемся чудесам фрэймворка.
→
Например
создаем файл
«test.php» с содержимым
<?php
include("dbConnection.php");
$xpdo->addPackage('MyDBModel','models/','');
$name = $xpdo->getObject('Actor', 1);
if($name)
{
echo "Имя актёра - ".$name->first_name." ".$name->last_name." / ".$name->last_update;
}
else
{
echo "Ничего не найдено :(";
}
?>
Вот и произошла уличная магия — на экране вы увидели
«Имя актёра — PENELOPE GUINESS / 2006-02-15 04:34:33».
А теперь по порядку — сначала строка
$xpdo->addPackage('MyDBModel','models/',''); говорит скрипту, что сейчас мы хотим работать с моделью
МyDBModel из папки
models/ (мы её предварительно сгенерировали).
$name = $xpdo->getObject('Actor', 1);
производит выборку строки из таблицы
Actor в модели
МyDBModel с primary key (обычно это поле id) = 1 (поставьте другое число и увидите, что результат будет другой).
Далее проверка ну пустой результат и вывод данных
first_name, last_name и last_update. Внимательный читатель конечно же понял, что эти свойства объекта $name есть имена столбцов в нашей таблице
Actor. И так можно доставать любые столбцы в любых таблицах (в рамках нашей модели, конечно же).
Идём дальше —
Как выбрать сразу многострок с опр. значением любого столбца, не только ключа ?
$collect = $xpdo->getCollection('Actor',array('first_name'=>'PENELOPE') );
foreach($collect as $actor)
{
echo $actor->first_name." ".$actor->last_name."
";
}
выбираем всех актеров с именем PENELOPE.
Задавать параметры для запроса в виде массива (здесь array('first_name'=>'PENELOPE') ) можно и в функции getObject. Вобще функции довольно гибкие и почти все поддерживают разные варианты обращения. Самый верный помощник в этом деле — какой нибудь PHP IDE с автокомплитом кода (NetBeans, например, сам выводит возможные варианты и параметры функций).
→
а теперь создадим новую запись об актере$newActor = $xpdo->newObject('Actor',array(
'first_name' => 'Star',
'last_name' => 'SuperStar',
));
if($newActor->save())
{
echo "Запись успешно добавлена !";
}
Запись в БД происходит при вызове $newActor->
save(), там же и производим проверку на успех.
→
И конечно же удалим наделанное :)$actor = $xpdo->getObject('Actor',array('first_name'=>'Star'));
if ($actor->remove()) {
echo 'Удаление прошло успешно !';
}
Философия проста — чтобы чтото удалить, нужно это найти и получить, а потом уж «резать». А также угадайте с трёх раз зачем нужен метод
removeCollection.
→
для изменения строк есть метод set
$actor = $xpdo->getObject('Actor', 1);
echo "До - ".$actor->first_name;
$actor->set('first_name','IVAN');
$actor->save();
$actor = $xpdo->getObject('Actor', 1);
echo "
После - ".$actor->first_name;
Думаю для начала хватит.
Там осталось ещё много интересностей типа расширенного запроса «newQuery» и методов быстрого «доставания» связанных данных из разных таблиц (getObjectGraph, getCollectionGraph и другие). Но с этим я разберусь и изложу чуть позже.
И на закуску кэширование произвольной инфы
$xpdo->getCacheManager();
$str = 'My cached data text.';
$xpdo->cacheManager->set('myVar',$str,3600);
echo $xpdo->cacheManager->get('myVar');
//$xpdo->cacheManager->delete('myVar');
Хранится всё это в папке «cache», которую мы задали при инциализации соединения (посмотрите напоявившийся там файл).
Думаю в этом коде всё пердельно ясно (3600 — это кол-во секунд на которые кэш будет действовать, после этого он очищется, так что в иделае нужно сделать проверку на пустоту). Тонкость в том, что вызов
$xpdo->getCacheManager(); в документации отсутсвует, но без этой строки у меня кэш упорно отказывался работать… может быть я что-то не так делаю? :)
Ссылки:
→
Знакомство с xPDO ч.2 или xPDO для «гиков»
Комментарии (7)
RSS свернуть / развернутьпо-моему, подобная штука реализована в SilverStripe
Solo
iJack
эм, а как же Revo, под который, если я правильно понимаю, xPDO и делали?
Или кеширование всех спасет?
pitbull
Просто любая надстройка наш штатными возможностями PHP — это по определению расход доп. памяти и процессорного времени.
А как известно Рэво имеет официальные минимальные системные требования куда большие чем для Эво.
iJack
pitbull
Кстати, а ID созданной записи как получить можно. Он возвращает его как результат $newActor->save() или через $newActor->id?
Carw
$newActor->save() — как результат выдает 1 в случае удачной операции.
iJack
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.