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() они доступны в качестве массива объектов класса.