Skip to content
  1. Система
  2. Что такое xPDO?
  3. Класс xPDO

Класс xPDO ​

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

В качестве надстройки PDO ​

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

И хотя xPDO не расширяет напрямую PDO (не является его классом-наследником), он предоставляет те же методы, что и PDO, что позволяет xPDO быть посредником между всеми вызовами базы данных. Это позволяет использовать кеширование результатов запросов и другие продвинутые техники оптимизации того, как ваши приложения взаимодействуют с базой данных (например, кешируя результаты запросов к БД в файлы или память, вы можете избежать соединений к БД, если все запрашиваемое уже есть в кеше).

Наконец, наследуя xPDO своими классами, вы можете добиться выполнения всех требуемых вами задач. Например, вы можете добавить специфичные для конкретной предметной области методы или расширить базовые методы в ваших наследниках и использовать экземпляры как центральные объекты предметной области для взаимодействия с вашей моделью. Так построена Система управления контентом MODX Revolution: центральный класс modX расширяет xPDO и добавляет методы, которые формируют предметную область приложения MODX.

Пример расширения класса xPDO: class myClass extends xPDO

и определения конструктора:

php
function __construct($options = array()) {
  $options = array(
    xPDO::OPT_CACHE_PATH => '/path/to/my/cache/dir',
    xPDO::OPT_TABLE_PREFIX => 'myprefix_',
    xPDO::OPT_HYDRATE_FIELDS => true,
    xPDO::OPT_HYDRATE_RELATED_OBJECTS => true,
    xPDO::OPT_HYDRATE_ADHOC_FIELDS => true,
    xPDO::OPT_VALIDATE_ON_SAVE => true,
  );
  parent :: __construct(
    'mysql:host=localhost;dbname=myxpdodb;charset=utf8',
    'username',
    'password',
    $options,
    array (
      PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
      PDO::ATTR_PERSISTENT => false,
      PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
    )
  );
  $this->setPackage('mypackage', 'path/to/my/model/');
}

Подробнее о конструкторе ниже.

В качестве сервисного слоя ​

В добавление к PDO, xPDO может обертывать другие объекты, с которыми хотите работать в своей модели.

Например, вы можете загрузить Smarty как объект, который можно вызывать напрямую из экземпляра xPDO:

php
if ($className= $xpdo->loadClass('Smarty','/path/to/smarty/smarty.class.php', false, true)) {
  $xpdo->smarty= & new $className ($xpdo);
}

$xpdo->smarty->someFunc();

xPDO предоставляет также удобный метод сделать это в одну строчку:

php
if ($xpdo->getService('myService', 'myServiceClass', '/path/to/model/root/', array('param1' => $param1, 'param2' => $param2)) {
  $xpdo->myService->doSomething();
}

При этом если сервисный экземпляр уже загружен в текущем запросе, он не будет загружен снова, а будет возвращена ссылка на него. Это создаёт простой способ обеспечивать повторно использование сервисных объектов для общих задач.

В качестве объектно-реляционного отображения ​

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

Конструктор xPDO ​

По умолчанию xPDO конструктор вызывается так: $xpdo= new xPDO($dsn, $username, $password, $options, $driverOptions)

Параметры ​

В конструкторе доступно 5 параметров, но единственный необходимый это первый:

$dsn ​

Этот параметр запрашивает значение DSN соединения, которое задаётся в следующем формате: mysql:host=MYHOSTNAME;dbname=MYDBNAME;charset=MYCHARSET

Нужно просто поменять значение имен хоста, базы данных и кодировки. Больше информации доступно в документации PDO на PHP.net.

$username и $password ​

Это логин и пароль к базе данных. Установите их, если хотите использовать соединения к БД в xPDO.

$options ​

Позволяет передать в конструктор массив характерных для xPDO свойств.

Некоторые из этих свойств имеют предопределенные значения, например, следующие (но не ограничены ими):

ПараметрОписание
xPDO::OPT_AUTO_CREATE_TABLESЕсли true, создает таблицы, соответствующие запрашиваемым классам, в случае если эти таблицы еще не существуют в базе данных
xPDO::OPT_BASE_CLASSESМассив имен классов, загружаемых во время создания экземпляра класса xPDO
xPDO::OPT_BASE_PACKAGESСтрока имен пакетов и путей к ним, в формате "имя_пакета1:путь_до_пакета1,имя_пакета1:путь_до_пакета1,...", загружаемые при создании экземпляра класса xPDO
xPDO::OPT_CACHE_COMPRESSЕсли установлена, любой экземпляр класса xPDOCache, использующий провайдера, который поддерживает сжатие данных, будет использовать эту опцию по умолчанию (например, xPDOMemCache)
xPDO::OPT_CACHE_DBЕсли установлена, будет включено кеширование наборов данных запросов к БД
xPDO::OPT_CACHE_DB_COLLECTIONSЕсли установлена, кеширование наборов данных запросов к БД будет пытаться кешировать целые коллекции
xPDO::OPT_CACHE_DB_OBJECTS_BY_PKЕсли установлена, кеширование наборов данных запросов к БД будет создавать элементы кеша по первичному ключу в дополнение к используемой подписи запроса
xPDO::OPT_CACHE_DB_EXPIRESЕсли установлена, определяет число секунд, которые существует кеш наборов данных; 0 означает, что кеш не истекает
xPDO::OPT_CACHE_DB_HANDLERЕсли установлена, определяет наследника класса xPDOCache для управления кеширование наборов данных
xPDO::OPT_CACHE_EXPIRESЕсли установлена, определяет число секунд жизни кеша для любого провайдера по умолчанию; 0 означает, что кеш не истекает
xPDO::OPT_CACHE_FORMATЕсли установлена, определяет формат файлов кеша, используемых в xPDOFileCache; по умолчанию PHP, но доступны JSON и сериализованный (начиная с версии xPDO 2.1)
xPDO::OPT_CACHE_KEYЕсли установлена, определяет ключ кеша по умолчанию; значение по умолчанию default
xPDO::OPT_CACHE_PATHЕсли установлена, определяет пользовательскую переменную класса cachePath для объекта xPDO, которая может использоваться при кешировании
xPDO::OPT_CACHE_ATTEMPTSЕсли установлена, определяет число попыток, которое xPDOFileCache будет блокировать на запись существующий элемент кеша; по умолчанию 1. (начиная с версии xPDO 2.1
xPDO::OPT_CACHE_ATTEMPT_DELAYЕсли установлена, определяет число микросекунд задержки между попытками блокировки элементов кеша на запись; по умолчанию 10000 (начиная с версии xPDO 2.1)
xPDO::OPT_CONNECTIONSДополнительно определяет набор соединений с БД при создании экземпляра класса xPDO (начиная с версии xPDO 2.2)
xPDO::OPT_CONN_INITОпределяет настройки, которые должны быть выбраны для соединения при его инициализации; применяется, если определены несколько соединений (начиная с версии xPDO 2.2)
xPDO::OPT_CONN_MUTABLEОпределяет могут ли данные из соединения быть изменены, например, перезаписаны (начиная с версии xPDO 2.2)
xPDO::OPT_HYDRATE_FIELDSЕсли true, поля будут гидратированы
xPDO::OPT_HYDRATE_RELATED_OBJECTSЕсли true, связанные объекты будут гидратированы
xPDO::OPT_HYDRATE_ADHOC_FIELDSЕсли true, ad-hoc поля (не описанные в карте класса, создаваемые на лету) будут гидратированы
xPDO::OPT_LOADER_CLASSESМассив имен классов для загрузки во время создания экземпляра xPDO объекта. (устарело с версии 2.0.0-pl
xPDO::OPT_ON_SET_STRIPSLASHESЕсли установлена, stripslashes() применяется для значений, устанавливаемых методом xPDOObject::set()
xPDO::OPT_TABLE_PREFIXЕсли установлена, все классы будут ссылаться на таблицы, начинающиеся с данного префикса
xPDO::OPT_VALIDATOR_CLASSЕсли установлена, будет использоваться пользовательский класс валидации, производный от xPDOValidator (который используется по умолчанию)
xPDO::OPT_VALIDATE_ON_SAVEЕсли true, объекты xPDOObject будут проверяться своими Валидаторами перед сохранением

$driverOptions ​

Необязательный массив настроек, специфичных для каждого PDO драйвера. Больше информации в справочнике PHP.

Соединения с базой данных и xPDO ​

Способность подключения к базе данных в xPDO задана в конструкторе. Объект xPDO одновременно может поддерживать только одно соединение, но вы можете создавать столько экземпляров xPDO, сколько вам потребуется. Синтаксис конструктора следующий:

php
xPDO::__construct($dsn, $username= '', $password= '', $options= array(), $driverOptions= null)

Итак предположим, что нам нужно соединиться с базой данной 'text' на localhost с портом 3306, в кодировке utf-8:

php
$dsn = 'mysql:host=localhost;dbname=test;port=3306;charset=utf-8';
$xpdo = new xPDO($dsn,'username','password');

И готово!

Опционально можно проверить соединение, просто добавив далее следующую строку:

php
echo $o=($xpdo->connect()) ? 'Соединено' : 'Не соединено';

xPDO создаёт объект PDO, и таким образом соединяется с базой данных, только когда вызывается метод PDO и требуется соединение. Эта особенность «соединение-по-требованию» позволяет xPDO получать данные из кеша без дополнительного соединения к базе данных (конечно, если данные в кеше уже сохранены).

Пример соединения ​

php
<?php

define('MODX_CORE_PATH', '/path/to/revo/core/');
define('MODX_CONFIG_KEY','config');
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';

// Параметры базы данных
$host = 'localhost';
$username = 'your_username';
$password = 'your_password';
$dbname = 'your_database';
$port = 3306;
$charset = 'utf-8';

$dsn = "mysql:host=$host;dbname=$dbname;port=$port;charset=$charset";
$xpdo = new xPDO($dsn, $username, $password);

// Тестирование соединения
echo $o = ($xpdo->connect()) ? 'Connected' : 'Not Connected';

// Делаем запрос к базе данных и выводим количество результатов:
$results = $xpdo->query("SELECT id FROM some_table");
$recordCount = $results->rowCount();
print $recordCount;

Установка нескольких соединений (xPDO 2.2+) ​

xPDO 2.2 добавило возможность устанавливать несколько соединений и включает параметры конфигурации для определения неизменяемых атрибутов для каждого соединения. Это позволяет использовать xPDO с разного рода master/slave конфигурациями баз данных. Под этой особенностью понимается не соединение к конкретному узлу базы данных, а настройка master/slave конфигураций, где один (или более) узлов доступны только для чтения, и хотя бы один узел доступен для записи (т.е. mutable). В этом случае вы можете запрашивать исходное соединение только на чтение, и xPDO автоматически переключится на доступное для записи соединение, если над объектом базы данных производится операция записи.

xPDO::OPT_CONNECTIONS ​

Для определения дополнительных соединений для экземпляра xPDO, можно передать массив конфигураций соединений (конфигурации так же являются массивами) в параметр $options конструктора xPDO. Каждый массив соединения определяет такие же параметры, как и вызов конструктора xPDO. Пример вызова конструктора с несколькими соединениями только для чтения:

php
$xpdo = new xPDO('mysql:host=127.0.0.1:19570;dbname=xpdotest;charset=utf8', 'username', 'password' array(
  xPDO::OPT_CONN_MUTABLE => true,
  xPDO::OPT_CONN_INIT => array(xPDO::OPT_CONN_MUTABLE => false),
  xPDO::OPT_CONNECTIONS => array(
      array(
        'dsn' => 'mysql:host=127.0.0.1:19571;dbname=xpdotest;charset=utf8',
        'username' => 'username',
        'password' => 'password',
        'options' => array(
          xPDO::OPT_CONN_MUTABLE => false,
        ),
        'driverOptions' => array(),
      ),
      array(
        'dsn' => 'mysql:host=127.0.0.1:19572;dbname=xpdotest;charset=utf8',
        'username' => 'username',
        'password' => 'password',
        'options' => array(
          xPDO::OPT_CONN_MUTABLE => false,
        ),
        'driverOptions' => array(),
      ),
    ),
));

xPDO::OPT_CONN_MUTABLE ​

Этот параметр определяет доступность соединения для записи (true) или только для чтения (false). Устанавливается в массиве $options конструктора, а так же в дополнительных соединениях.

xPDO::OPT_CONN_INIT ​

Этот параметр определяет условия, которым должно удовлетворять соединение, чтобы рассматриваться в качестве используемого для исходного соединения, создаваемого в xPDO. В конфигурациях master/slave обычное значение для этого параметра (которое устанавливается только раз в главных конфигурационных настройках) указывает использовать соединение, доступное только для чтения.

php
xPDO::OPT_CONN_INIT => array(xPDO::_OPT_CONN_MUTABLE => false)

Это обеспечивает, что xPDO выбирает соединение с параметром xPDO::_OPT_CONN_MUTABLE, установленным в значение false. Если производится операция на запись при инициализированном соединении, доступном только для чтения, будет выбрано новое соединение, доступное для записи, и закешировано для последующего использования другими операциями записи в данном цикле выполнения.

Гидратирование полей ​

Что такое гидратирование? ​

Гидратирование (Hydration) это процесс, при котором поля и связанные объекты, представленные экземплярами класса xPDOObject, заполняются значениями. По умолчанию, эти поля доступны только с помощью методов get(), getOne() и getMany() класса xPDOObject и должны быть определены подходящими метаданными в карте объекта. Тем не менее, существует несколько настроек, которые вы можете использовать для расширения процесса того, как xPDO гидратирует поля и связанные объекты.

Эти настройки применяются при передаче следующих параметров в параметр $config конструктора xPDO:

ПараметрОписание
xPDO::OPT_HYDRATE_FIELDSЕсли true, поля будут гидратированы в качестве публичных переменных объекта.
xPDO::OPT_HYDRATE_RELATED_OBJECTSЕсли true, связанные объекты будут гидратированы в качестве публичных переменных объекта.
xPDO::OPT_HYDRATE_ADHOC_FIELDSЕсли true, ad-hoc поля (не описанные в карте класса, создаваемые на лету) будут разрешены и гидратированы в качестве публичных переменных объекта (при этом должна быть установлена настройка xPDO::OPT_HYDRATE_FIELDS).

Гидратированные Поля ​

Если параметр xPDO::OPT_HYDRATE_FIELDS установлен в значении true, в дополнение к доступу к полям через метод xPDOObject::get() все поля объекта становятся доступными через публичные переменные объекта. Пример:

php
$object->set('name',$name);
echo $object->name;

Этот код выведет значение поля 'name' объекта $object, при условии что поле 'name' определено в схеме объекта.

Замечание: Это "сырые" значения Доступ к полям объекта напрямую выводит только "сырые" значения, т.е. в таком виде, как они выгружены из базы данных, игнорируя метаданные, определенные для поля, и избегая любую логику, примененную в методе get() вашего класса, наследуемого от xPDOObject (а так же, всех его родительских классов). Рекомендуется всегда использовать метод get() для доступа к полям объектов, за исключением некоторых особых случаев, когда вам могут потребоваться сырые значения из базы данных, которые не должны быть изменены логикой метода get().

Гидратирование Ad Hoc Полей ​

Если параметр xPDO::OPT_HYDRATE_ADHOC_FIELDS установлен в значении true, для произвольных полей, не определенных в карте класса, так же будет проводиться гидратация. Теперь все поля, даже не указанные в схеме объекта будут заполняться. Например, мы хотим установить произвольное поле 'dollars' для объекта Person:

php
$object->set('name','Вася Пупкин');
$object->set('dollars',45);
echo $object->get('name') .' имеет '. $object->get('dollars') . ' долларов.';

Этот код вернет Вася Пупкин имеет 45 долларов., даже если поле 'dollars' не определено в схеме, конечно, только в том случае, если включены параметры xPDO::OPT_HYDRATE_ADHOC_FIELDS и xPDO::OPT_HYDRATE_FIELDS.

Гидратирование связанных объектов ​

Если xPDO::OPT_HYDRATE_RELATED_OBJECTS установлена в значение true, все связанные объекты так же будут доступны в качестве публичных переменных объекта. По умолчанию связанные объекты доступны только через методы getOne() или getMany() класса xPDOObject, но этот параметр (как xPDO::OPT_HYDRATE_FIELDS)

загружает все связанные объекты напрямую в переменные. Пример:

php
$user->getMany('UserSettings');
foreach ($user->UserSettings as $setting) {
  echo $setting->get('key').' = ' . $setting->get('value') . '<br />';
}

Этот код вернет список ключей и значений пользовательских настроек, принадлежащих объекту $user, которые по умолчанию загружаются через getMany().

One против Many Объекты, загружаемые через getOne() доступны напрямую как объекты соответствующего класса, в то время как через метод getMany() они доступны в качестве массива объектов класса.