Привязка встроенных объектов к кастомным
В силу ряда причин, мне потребовалось в свой кастомный объект, имеющий свою таблицу в бд и наследующий xPDOSimpleObject, добавить привязку к стандартному объекту MODX. Например, modUser.
Сделать это с помощью aggregates и composites в схеме моего кастомного объекта не получилось (собственно, добавление в схему связи с нативным modx-объектом ни к чему не привело — связи не появилось). Я полагаю, это свзяано с тем, что в схеме modx.mysql.schema.xml свзяи с моим кастомным объектом как не было, так и нет.
Поскольку мне необходимы были дополнительные поля в атрибутах пользователя, а поле extended для этого не подходило в связи с необходимостью выборки по одному из дополнительных полей, я для пущего удобства, а так же из любви к искусству присвоил объект modUser переменной моего кастомного класса так, что самого пользователя можно получать без лишних телодвижений так:
Чтобы этого добиться, надо взять файл, созданный после парсинга вашей схемы (подробно останавливаться на этом моменте не буду, на данном сайте она описана подробно, а так же у Василия есть целый учебный курс по созданию компонентов, гед этот вопрос так же отлично освещен) и описывающий наш кастомный класс. Как правило, все такие файлы изначально выглядят так:
Чтобы при выполнении команды
Мы в переменной $foo получали объект нашего класса с привязанным к его переменной соответствующим объектом класса modUser, необходимо в нашем классе переопределить некоторые методы класса xPDOSimpleObject:
Другими словами, мы сначала получаем инстанс объкта с полями, заполненными из БД (выполняем метод load родительского класса), а потом присваиваем переменной $User объект класса modUser стандартным методом xPDO :: getObject(), при этом, в качестве критерия используется значение поля userid нашего кастомного объекта.
Теперь при получении объекта стандартным образом, например
мы без лишних строк и усилий получаем сразу и связанный с ним объект modUser.
Если же нам надо получать так же и связанные объекты при получении коллекции наших кастомных объектов методом xPDO :: getCollection(), нужно для нашего кастомного класса переопределить так же и метод loadCollection таким образом:
Как мы видим, принцип действия такой же — выполняем одноименный метод родительского класса, получая массив объектов нашего класса по критерию, потом итерируем этот массив, добавляя каждому элементу к переменной $User соответствующий ему объект modUser.
Так же, если нужно удалять привязанный объект вместе с кастомным, при этом главный в этой связке именно кастомный, можно перегрузить так же метод класса remove.
Если связанный объект уже находится в переменной кастомного, код будет еще проще
Здесь действуем в обратном порядке — сначала получаем и удаляем связанный объект, а потом выполняем метод remove родительского класса.
В итоге при выполнении $ourObject->remove() удалится из БД как сам наш объект, так и связанный с ним modUser.
Не уверен, возможно MODX предлагет более простой инструментарий для связывания стандартных и кастомных объектов, но я не нашел. За подсказку в комментариях буду очень благодарен.
Надеюсь, моя писанина сможет быть кому-то полезной:))
Сделать это с помощью aggregates и composites в схеме моего кастомного объекта не получилось (собственно, добавление в схему связи с нативным modx-объектом ни к чему не привело — связи не появилось). Я полагаю, это свзяано с тем, что в схеме modx.mysql.schema.xml свзяи с моим кастомным объектом как не было, так и нет.
Поскольку мне необходимы были дополнительные поля в атрибутах пользователя, а поле extended для этого не подходило в связи с необходимостью выборки по одному из дополнительных полей, я для пущего удобства, а так же из любви к искусству присвоил объект modUser переменной моего кастомного класса так, что самого пользователя можно получать без лишних телодвижений так:
$myCustomClassInstance->User instanceof modUser //true
То есть, мои кастомные классы содержат объекты, с которыми связаны, подобно нативным классам MODX. Например, объект класса modUser содержит в своих переменных так же и свзанные объекты, такие как профиль ($user->Profile), группу и т.д.Чтобы этого добиться, надо взять файл, созданный после парсинга вашей схемы (подробно останавливаться на этом моменте не буду, на данном сайте она описана подробно, а так же у Василия есть целый учебный курс по созданию компонентов, гед этот вопрос так же отлично освещен) и описывающий наш кастомный класс. Как правило, все такие файлы изначально выглядят так:
<?php
class DSProfile extends xPDOSimpleObject {}
Чтобы при выполнении команды
$foo = $modx->getObject('DSProfile',$criteria);
Мы в переменной $foo получали объект нашего класса с привязанным к его переменной соответствующим объектом класса modUser, необходимо в нашем классе переопределить некоторые методы класса xPDOSimpleObject:
class DSProfile extends xPDOSimpleObject {
public $User;
public static function load(xPDO & $xpdo, $className, $criteria, $cacheFlag= true) {
$thisObj = parent :: load($xpdo, $className, $criteria, $cacheFlag);
$thisObj->User = $xpdo->getObject('modUser',$thisObj->userid);
return $thisObj;
}
Другими словами, мы сначала получаем инстанс объкта с полями, заполненными из БД (выполняем метод load родительского класса), а потом присваиваем переменной $User объект класса modUser стандартным методом xPDO :: getObject(), при этом, в качестве критерия используется значение поля userid нашего кастомного объекта.
Теперь при получении объекта стандартным образом, например
$dsprofile = $modx->getObject('DSProfile', $id);
мы без лишних строк и усилий получаем сразу и связанный с ним объект modUser.
Если же нам надо получать так же и связанные объекты при получении коллекции наших кастомных объектов методом xPDO :: getCollection(), нужно для нашего кастомного класса переопределить так же и метод loadCollection таким образом:
public static function loadCollection(xPDO & $xpdo, $className, $criteria= null, $cacheFlag= true) {
$collection = parent :: loadCollection($xpdo, $className, $criteria, $cacheFlag);
$newCol = array();
foreach($collection as $key => $item){
$item->User = $xpdo->getObject('modUser', $item->userid);
$newCol[$key] = $item;
}
return $newCol;
}
Как мы видим, принцип действия такой же — выполняем одноименный метод родительского класса, получая массив объектов нашего класса по критерию, потом итерируем этот массив, добавляя каждому элементу к переменной $User соответствующий ему объект modUser.
Так же, если нужно удалять привязанный объект вместе с кастомным, при этом главный в этой связке именно кастомный, можно перегрузить так же метод класса remove.
public function remove(){
if($op = $this->xpdo->getObject('modUser', ['id' => $this->userid])){
$op->remove();
}
parent::remove();
}
Если связанный объект уже находится в переменной кастомного, код будет еще проще
public function remove(){
$this->User->remove();
parent :: remove();
}
Здесь действуем в обратном порядке — сначала получаем и удаляем связанный объект, а потом выполняем метод remove родительского класса.
В итоге при выполнении $ourObject->remove() удалится из БД как сам наш объект, так и связанный с ним modUser.
Не уверен, возможно MODX предлагет более простой инструментарий для связывания стандартных и кастомных объектов, но я не нашел. За подсказку в комментариях буду очень благодарен.
Надеюсь, моя писанина сможет быть кому-то полезной:))
Комментарии: 7
Сделать это с помощью aggregates и composites в схеме моего кастомного объекта не получилось (собственно, добавление в схему связи с нативным modx-объектом ни к чему не привело — связи не появилось).Вот здесь ты просто где-то ошибся.
К своему объекту можно привязать что угодно — для того и нужны aggregates и composites. Например, вот связь сервиса HybridAuth с юзером. Вот она же, но уже в самом классе.
А вот связать объект MODX со своим чуть сложнее, нужно проявить фантазию. Мне нравится делать это при загрузке metadata своей модели.
А вот связать объект MODX со своим чуть сложнее, нужно проявить фантазию. Мне нравится делать это при загрузке metadata своей модели.Как раз то что я искал последние 3 дня… Супер!
Вот же блин, стока лишней работы, а вопрос всего лишь в одной строчке:)))
Спасибо за подсказку, пойду всё нафик перепишу:))
Спасибо за подсказку, пойду всё нафик перепишу:))
Думаю, стоит перенести этот тикет в раздел «Вопросы» =)
Перенёс *стыдливо потупил взор*
Мне тоже пригодилось, спасибо!)
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.