Jump to main content Jump to doc navigation

xPDO - это объектно-реляционный мост, встроенный в MODX. Проще говоря, это то, как MODX подключается к базе данных и как он взаимодействует с различными таблицами.

В MODX 2.x, класс modX непосредственно расширяет xPDO. Хотя в ретроспективе это не лучший шаблон разработки, это означает, что всякий раз, когда у вас есть доступ к экземпляру modX, вы можете использовать любой из методов xPDO на нем.

Что такое xPDO?

xPDO (open eXtensions to PDO) - это легковесная ORB (object-relational bridge, объектно-реляционный мост) библиотека, работающая на PHP 5, которая помогает пользоваться преимуществами последних стандартов работы с базами данных в PHP, расширением PDO (PHP Data Objects). xPDO реализует очень простой, но эффективный паттерн для доступа к данным Active Record, а также гибкую модель предметной области, позволяющую отделить логику области от логики, специфичной для той или иной базы данных, когда это вам нужно.

Но xPDO - это немного больше, чем простая реализация паттерна. Это еще и способ абстрагирования бизнес-логики приложения от фактически используемых для доступа к данным в БД SQL-запросов и связанных переменных (prepared statements), а также легко описать и обеспечить реализации объектной модели для нескольких целевых платформ баз данных.

Задачей xPDO является быстрое обеспечение фундамента веб-приложения, который легко расширить до полноценной объектной модели, которая может быть оптимизирована насколько это возможно без зависимостей от конкретной платформы.

Глоссарий

В контексте xPDO важно знать следующие термины:

  • Packages - коллекции моделей. В ядре MODX все модели являются частью пакета modx, плюс есть несколько подпакетов, таких какmodx.media и modx.package. Чтобы xPDO узнал о моделях в пакете, его необходимо зарегистрировать с помощью $xpdo->addPackage().
  • Models - классы, которые представляют конкретную таблицу базы данных. Это абстракция, которую вы будете использовать чаще всего: вместо непосредственного взаимодействия с SQL вы загружаете модель, настраиваете ее свойства и сохраняете.
  • Schemas - XML-файлы, которые определяют различные модели, доступные в пакете, и их поля (свойства). Они используются только в разработке, во время которой они будут обрабатываться (обычно называемые «встроенными») в модельных классах и картах.
  • Maps - php-файлы, содержащие массивы, которые определяют метаданные для пакетов и схем. Они находятся в директории модели драйвера базы данных (например: model/modx/mysql/modresource.map.inc.php). Эти файлы обычно не обрабатываются вручную, а создаются из файла схемы.

Есть еще много вещей, которые нужно узнать о xPDO, но если вы понимаете эти 4, у вас есть прочная основа, чтобы разобраться в остальной части документации.

Пример

На различных страницах вы можете узнать больше о различных способах работы с данными в xPDO. Если вы больше разбираетесь в коде, приведенный ниже пример покажет вам различные взаимодействия xPDO.

if (!$modx->addPackage('education', '/path/to/model/')) {
   die('Can\'t load package, try again later.');
}

// Поступить в Гарвард (или создать новую школу с таким же названием)
$school = $modx->getObject('School', ['name' => 'Harvard']);
if (!$school) {
    $school = $modx->newObject('School');
    $school->set('name', 'Harvard');
    $school->save();
}

// Найдите 100 студентов, которые являются выпускниками и отсортируйте по фамилии
$c = $modx->newQuery('Student');
$c->where([
    'school' => $school->get('id'),
    'is_alumni' => true,
    'start_year' => $_GET['start_year'] ?? date('Y') - 5,
]);
$c->sortby('lastname', 'ASC');
$c->limit(100);

foreach ($modx->getIterator('Student', $c) as $student) {
    echo $student->get('firstname') . ' ' . $student->get('lastname') . ' started studying in ' . $student->get('start_year');

    if ($graduation = $student->getOne('Graduation')) {
        echo ' and graduated in ' . $graduation->get('year') . ".\n";
    }
    else {
        echo " and has not graduated.\n";
    }
}

Некоторые замечания по поводу приведенного выше кода:

  • Это чисто гипотетически, нет никакого кода пакета/модели для вас, чтобы использовать.
  • В строке 6 мы задаем условия для загрузки объекта School в виде массива. Вы также можете указать целое число, чтобы получить объект по его первичному ключу, предоставить xPDOQuery или предоставить необработанный SQL. Всегда четко указывайте тип условия, которое вы задаете; приведите к int, если вы используете первичный ключ (особенно если он получен из пользовательского ввода), или предоставьте синтаксис массива.
  • В строке 14 мы создаем новый экземпляр xPDOQuery для нашей модели Student. Это конструктор запросов. Имя переменной $c, сокращенное от condition, довольно часто встречается в экземплярах xPDOQuery. xPDOQuery может выполнять условия, объединения, сортировку и многое другое. Для отладки сгенерированного запроса можно добавить $c->prepare(); echo $c->toSQL();
  • В строке 18 мы используем данные $_GET без применения какой-либо очистки. К счастью для нас, xPDO использует подготовленные операторы, поэтому вы автоматически защищены от SQL-инъекций при использовании query Builder.
  • Линии 23, 26 и 29 используют Эхо для возврата данных. Вы никогда не должны (редко) делать это в реальном коде. В идеале вы должны предоставить данные ($student->toArray()) шаблону (например, chunk, с $modx->getChunk(), который является методом modX, а не xPDO), чтобы сохранить ваши данные и разметку отдельно.
  • Строка 25 использует метод getOne() для получения связанного объекта. Отношение должно быть определено в модели. Вместо getOne, вы могли бы также затронуть отношения непосредственно ($student->Graduation), который будет ленивый загружен, или (при условии, что Graduation модель имеет поле student, содержащий студенческий) вы могли бы использовать $modx->getObject('Graduation', ['student' => $student->get('id')]).

Взгляните на различные подразделы, чтобы узнать больше о конкретных аспектах xPDO.

Легко понять шаблоны

Но xPDO-это немного больше, чем простая реализация шаблона. Это также способ абстрагирования бизнес-объектов от реальных SQL-запросов и подготовленных операторов, используемых для доступа к реляционной структуре базы данных, представляющей их, а также способ простого описания и предоставления оптимизированных реализаций объектной модели для нескольких целевых платформ баз данных.

При разработке xPDO использовались несколько паттернов проектирования, которые хорошо описаны в книге Мартина Фаулера «Архитектура корпоративных программных приложений» («Patterns of Enterprise Application Architecture»). Среди них есть следующие и не только:

  • Domain Model
  • Active Record
  • Data Mapper
  • Lazy Load
  • Identity Field
  • Single Table Inheritance
  • Metadata Mapping
  • Query Object

Перед программированием с использованием xPDO будет очено полезно ознакомиться с этими паттернами (и другими из каталога Фаулера). Понимание этих концепций поможет не только в изучении xPDO, но и многих других вещей, связанных с программированием.

Почему это было создано

xPDO был вдохновлен необходимостью быстро создать каркас для веб-приложения, который легко расширить в полномасштабную объектную модель, которая могла бы быть максимально оптимизирована для платформы базы данных, на которой она развертывалась, без создания зависимостей от платформы или кошмаров обслуживания. И это должно было обеспечить как можно меньший объем кода; реализация эффективной объектно-реляционной структуры персистентности в PHP требует этого.

Support the team building MODX with a monthly donation.

The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.

Backers

  • modmore
  • STERC
  • Digital Penguin
  • Jens Wittmann – Gestaltung & Entwicklung
  • Fabian Christen
  • Dannevang Digital
  • Sepia River Studios
  • CrewMark
  • Chris Fickling
  • deJaya
  • eydolan
  • Lefthandmedia
  • Murray Wood
  • Following Sea
  • Anton Tarasov
  • Stéphane Jäggi
  • Raffy
  • Snow Creative
  • A. Moreno
  • Nick Clark
  • JT Skaggs
  • Helen
  • YJ
  • krisznet
  • Richard
  • Yanni

Budget

$306 per month—let's make that $500!

Learn more