Наверх

Часть 1. Метод getObject

Я думаю, все когда-либо слышали аббревиатуру xPDO, все знают, что она как-то связана с MODX. Многие слышали, что xPDO может показывать фокусы, с его помощью можно производить массовые операции с разными объектами, а Fi1osof и многие другие постоянно всем советуют изучать его.

Однако многих отпугивают такие заголовки, как, например

$this->_lazy и повторные запросы к БД при $object->toArray() и ->get();
или
xPDO::addDerivativeCriteria(), class_key, CRC и прочие связанные друг с другом тонкости

потому что начинать, конечно, надо с простого.

Вот в этой статье я и попытаюсь сделать введение в xPDO для тех, кто просто хочет понять, что это такое.

Для начала разверните где-нибудь тестовый пустой сайт (проще всего будет зарегистрироваться на https://modhost.pro/, создать бесплатный аккаунт и на нем развернуть один сайт). После чего поставьте себе компонент Console и создайте пару-тройку страниц с разными названиями.

Для начала научимся получать любые поля документов в нашем скрипте. Открываем «Компоненты -> Console» и пишем туда такой код и нажимаем «Выполнить»:
$res = $modx->getObject('modResource',1);
$output = $res->get('pagetitle');
print $output;
После выполнения этого кода вы увидите внизу pagetitle главной страницы. Поздравляю! Вы только что получили данные страницы с помощью xPDO!

Давайте, разберемся, что мы такого тут написали.

Ресурсы (на самом деле, не только ресурсы, а вообще всё в MODX) являются объектами (это термин из ООП, но если вы не знакомы с ООП, просто представляйте, что «объект» — это другими словами «сущность»). И чтобы что-то сделать с ресурсом (например, получить его свойства), нам этот объект надо сначала найти и «взять» — это мы делаем в первой строке getObject.
$modx->getObject() — дословно «получить объект». В скобках через запятую написано два параметра.

Первый параметр — это класс. Для ресурсов классом является modResource (на самом деле, не для всех, но пока нам это не важно). Благодаря указанию класса, MODX «понимает», что мы хотим работать именно с ресурсом, а не с чанком, пользователем или каким-то другим типом объектов.

Второй параметр — это id объекта (в дереве ресурсов все id прописаны в скобках). Меняя этот параметр можно получать данные любого ресурса. Попробуйте поменять его на 2 или 3, и вы увидите, что нам каждый раз показывается pagetitle того ресурса, который мы указали.

Таким образом, в переменной $res у нас находится объект, соответственно мы можем получить его свойства. Для этого мы использовали метод get:
->get() — дословно «получить». А что именно мы хотим получить, мы указываем в скобках. В данном случае мы хотим получить pagetitle, и мы это указали.

Ну и в последней строчке мы просто выводим содержимое переменной $output на экран.

Мы можем получить не только pagetitle, но и longtitle, content, publishedon и все остальные поля ресурса. А хотите увидеть все поля ресурсов? Тогда несколько меняем наш код:
$res = $modx->getObject('modResource',1);
$output = $res->toArray();
print "<pre>";
print_r($output);
->toArray() — возвращает все поля объекта в виде массива

Видите, сколько у ресурса полей? И значение каждого этого поля мы можем получить с помощью $res->get();

Думаю, на сегодня хватит, в следующей статье попробуем получить данные сразу нескольких объектов с помощью getCollection() и, возможно, попробуем отредактировать объект с помощью xPDO. G+

Оригинал статьи community.modx-cms.ru/blog/modx-xpdo/10247.html


40 комментариев

  1. Михаил Лавронов 31 июля 2013, 21:27(Комментарий был изменён) # 0
    Однозначно в закладки. Я начал изучать PHP и уже понимаю в нем немного. Хотел бы конечно параллельно на MODx что нибудь сделать. В планах расписано: аватарку, фронтенд добавление статей. Я надеюсь что Вы выпустите все задуманные уроки!
    1. Олег Муравьёв 05 августа 2013, 16:23(Комментарий был изменён) # 0
      Отличные статьи. Мне очень помогли в освоении xPDO. Продолжайте писать дальше у вас талант учителя!
      1. Саша Друмс 24 октября 2013, 17:04(Комментарий был изменён) # 0
        Попробовал получить параметры id через код:
        $res = $modx->getObject('modResource',1);
        $output = $res->get('id');
        return $output;
        но ничего не выводится, а так же некоторые другие параметры, к примеру parent. Так и должно быть?
        1. Илья Уткин 24 октября 2013, 17:23(Комментарий был изменён) # 0
          Ну код правильный. Скорее всего, проблема в другом месте. Попробуйте вместо
          return $output;
          написать
          print $output; die();
          или вызвать этот код на пустой странице с пустым шаблоном.
          1. Саша Друмс 24 октября 2013, 18:40(Комментарий был изменён) # 0
            Да, так всё работает. :-)
            1. Михаил 27 июля 2015, 12:19 # 0
              Илья, а в каком месте может быть проблема? У меня такая же ситуация… Хочется чтоб работало как надо )
              1. Илья Уткин 03 августа 2015, 08:06 # 0
                Так совет тот же тогда)
                Попробуйте вместо
                return $output;
                написать
                print $output; die();
                или вызвать этот код на пустой странице с пустым шаблоном.
                1. D.Zanzo 07 октября 2015, 18:36 # 0
                  Прикольно. Но было бы неплохо, чтобы ты объяснил, почему надо убить вызов в конце? Потому как у меня тоже не работает.
                  1. Илья Уткин 07 октября 2015, 20:35 # 0
                    Потому что проблема может быть в самом неожидвнном месте. Надо знать, конкретно где
                    1. D.Zanzo 07 октября 2015, 20:40 # 0
                      Спасибо, на самом деле я плохо знаю php. Я учу python, по этому мне не всегда понятен синтаксис. Решил посмотреть как сделать выгрузку 60000 фирм в модекс. Я подумал, что каждую можно сделать ресурсом. А как это сделать в модексе не знаю :D, По этому Ваши уроки по XPDO очень в тему, да и у меня сразу приходит понимания синтаксиса php. Спасибо, Дружище!
          2. Антон Матвеев 05 июня 2014, 12:26(Комментарий был изменён) # 0
            Здравствуйте, а скажите пожалуйста, где можно найти синтаксис xPDO ???
            то есть зарезервированные слова, конструкции, методы, действия ( или как это называется...)

            прочитал 3 урока, все понятно, и получается на практике повторить.

            Не понятно только одно, где можно посмотреть откуда берутся эти
            $modx->getObject
            $output
            print $output; die();
            print "<pre>"; 
            $modx->getCollection;
            foreach ...
            
            и так далее…
            и что обозначает "->" ??? :-) как ее словесно описать можно ?)

            Логически, то понятно, что они все делают, но вот где найти описание этих конструкций???

            1. Илья Уткин 05 июня 2014, 13:15 # 0
              Для понимания этого вам надо хоть чуть-чуть понять, что такое ООП. Стрелка обозначает обращение к методу объекта. То есть, у объекта modx есть метод getObgect. Почитайте, как я нашел для себя метод getChildIds: ilyaut.ru/xpdo/xpdo-for-dummies-part-2-the-practice-of/#comment-267
            2. олег 17 июня 2014, 11:43 # 0
              Илья, добрый день! Вот этот код
              $res = $modx->getObject('modResource',1);
              $output = $res->get('pagetitle');
              return $output;
              
              дает возможность работать только с id = 1, а как быть если мне надо выбрать pagetitle для объектов при выборке?
              Т.е, код немного поменяется, но чему будем равен $id?
              $res = $modx->getObject('modResource',$id);
              $output = $res->get('pagetitle');
              return $output;
              
              Заранее спасибо за ответ.
              1. Илья Уткин 17 июня 2014, 11:45 # 0
                Вам нужен метод getCollection. Придется, все-таки, хотя бы прочитать все уроки)))
              2. Андрей Иванов 01 июля 2014, 05:45 # 0
                Большое спасибо!
                Написано на уровне хорошо проработанного, качественного учебника для начинающих: грамотно и понятно! Просто замечательно, что существуют такие русскоязычные ресурсы по MODX.
                1. Евгений 07 августа 2014, 19:14 # 0
                  Илья, подскажи пожалуйста как получить номер (id) шаблона ресурса?
                  Думал все просто:
                  $res = $modx->getObject('modResource',172);
                  return $res->get('template');
                  но не тут-то было.
                  1. Илья Уткин 19 августа 2014, 06:43 # 0
                    Странно… У меня этот код нормально работает. Существует ли ресурс? Выводит ли другие поля ресурса? Работает ли
                    print_r($res->toArray());
                    1. Евгений 19 августа 2014, 08:42 # 0
                      Спасибо, Илья.
                      В общем-то разобрался. Я пытался это сделать через Console, а он почему-то ничего не выводил. Может это только у меня такой глюк.
                      В сниппете все нормально работает.
                  2. Alex 19 сентября 2015, 07:35 # 0
                    Приветствую, Илья.

                    Часто нахожусь на твоем сайте и тут увидел, что как-то странно у тебя стал отображаться код

                    joxi.ru/Dr8ojJDSBPDPA6

                    Раньше было все ОК

                    Поправь, пожалуйста
                    1. Илья Уткин 21 сентября 2015, 07:52 # 0
                      Cпасибо, поправил
                    2. Алексей 18 ноября 2015, 03:34 # 0
                      Илья, благодарю за урок! Давно искал…
                      1. Саша 06 января 2016, 14:49 # 0
                        Привет, Илья!

                        А можно ли как-то получить поле из базы данных и после чего изменить какое-то значение и сохранить?
                        1. Илья Уткин 09 января 2016, 14:37 # 0
                          Да, можно, смотри следующие уроки =)
                        2. Amsterdam 09 августа 2016, 10:52 # 0
                          Как сделать проверку на присутствие аттач файла к форме formit??
                          1. Илья Уткин 09 августа 2016, 10:58 # 0
                            А как этот вопрос с темой статьи связан?

                            Проверка зависит от способа прикрепления файла. Есть стандартный функционал PHP — тогда надо проверять массив $_FILES
                            1. Amsterdam 09 августа 2016, 11:06 # 0
                              Статья про xPDO, вопрос по xPDO. только про решение на нем вот этого вопроса.

                              Файл прикреплен стандартно, через input=file. Пытаюсь написать хук для formit, который будет проверять — если аттач есть, то выполняется определенное действие (в моем случае, отправляет юзеру письмо — «спасибо за аттач!»). Но не получается проверку сделать, блин…

                              Пробовал на php проверку поставить if(isset($_FILES['file'])){… }. но тоже не работает. так вообще можно? часть хука на php, часть на xPDO?
                              1. Илья Уткин 09 августа 2016, 11:15 # 0
                                К xPDO тут отношения никакого. Нужно искать в отрыве от MODX и xPDO: php проверить прикреплен ли файл к форме
                                1. Amsterdam 09 августа 2016, 11:35 # 0
                                  подошла вот такая проверка

                                  if ($_FILES['contact_attachment']['size'] > 0) {
                            2. AX 20 мая 2018, 00:45 # 0
                              Есть вот такой сниппет
                              <?php
                              $q = $modx->newQuery('modResource');
                              $q->where(array('pagetitle' => $idpm, 'parent:IN' => array('5','10')));
                              $resource = $modx->getObject('modResource', $q);
                              $iddd = $resource->id;
                              return $iddd;
                              id ресурсов выбирает отлично, а как получить значение TV параметра? пробовал tv.name — не работает
                              1. Александр 20 мая 2018, 03:45(Комментарий был изменён) # 0
                                Можно вот так
                                $tv = $resource->getTVvalue(1);
                                Или вот так, если TV-шек много
                                $tvs = $resource->getMany('TemplateVarResources');
                                
                                foreach($tvs as $k => $name){
                                    $tvs[$k] = $name->toArray(); // получить все TV-шки и всю информацию
                                    $tv = $name->get('value');  // только значение
                                }
                                
                                1. AX 20 мая 2018, 08:07 # 0
                                  в первом случае у меня выдает ошибку
                                  Fatal error: Call to a member function getTVvalue() on a non-object in
                                  как кстати и в случае если бы я использовал функцию get для получения значения вот здесь
                                  $iddd = $resource->id;
                                  не знаю почему…

                                  а во втором случае я не понял — я получаю все значения TV что есть в базе? а как мне потом выбрать, то, которое соответствует выбранному мне ресурсу?
                                  ну и опять же на get будет выдавать ошибку.
                                  1. Александр 20 мая 2018, 10:09 # 0
                                    во втором варианте вы получаете те TV, которые есть у конкретного ресурса, т.к.
                                    $tvs = $resource->getMany('TemplateVarResources');
                                    Ну а фатальная ошибка скорее всего из-за того, что вы просто скопировали код, не изменив единичку на тот id, который вам нужно получить.

                                    $tv = $resource->getTVvalue('номер id или наименование TV');
                                    1. AX 20 мая 2018, 11:10 # 0
                                      менял конечно единичку и на id на название TV, проблема не в этом и вообще не понял в чем. В итоге написал еще один сниппет, скопировав туда код, найденный в интернете
                                      <?php
                                      $query = $modx->newQuery('modResource');
                                      $query->where( array('pagetitle' => $idpm, 'parent' => 5) );
                                      $resource = $modx->getObject('modResource', $query);
                                      $tv ='';
                                      if ($resource) {
                                        $tv = $resource->getTVvalue('tipnag');  
                                      }
                                      по мне отличается от моего только наличием условия и объявлением переменной, но этот код работает. Пробовал в своем объявлять переменную — все равно не работает(
                                      В общем, проблема решена, только я не понял как и в чем она была))
                                      1. Александр 20 мая 2018, 12:37(Комментарий был изменён) # 0
                                        Думаю, что где-то допустили ошибку.

                                        Если вопрос решили, это хорошо. Но разобраться и понять все же будет не лишним.

                                        На мой взгляд если использовать запрос newQuery, то писать весь код таким образом, чтобы уже в нем получать все то, что нужно и с чем предстоит работать.

                                        Тогда я бы написал так
                                        $q = $modx->newQuery('modResource');
                                        $q->where([
                                            'parent:IN' => [2,3]
                                        ]);
                                        $q->leftJoin('modTemplateVarResource', 'TemplateVarResources');
                                        $q->select([
                                            'modResource.*',
                                            'TemplateVarResources.*'
                                        ]);
                                        
                                        if($q->prepare() && $q->stmt->execute()){
                                            $resources = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
                                        }
                                        
                                        $data = [];
                                        foreach($resources as $resource){
                                            $data[] = [
                                                'id'    => $resource['id'];,
                                                'tv'    => $resource['value']
                                            ];
                                        }
                                        
                                        return $data;
                                        
                                        1. Илья Уткин 21 мая 2018, 07:55 # 0
                                          Проблема решена не из-за объявления переменной (в PHP это необязательно), а из-за условия
                                          if ($resource) {

                                          ОшибкаCall to a member function… on a non-object говорит о том, что ресурс не найден. Поэтому перед тем, как что-то делать с ресурсом, нужно проверить, получен ли вообще этот ресурс.
                                          1. AX 21 мая 2018, 08:20 # 0
                                            да, но в исходном коде, который работал ilyaut.ru/xpdo/xpdo-for-dummies-part-1/#comment-2167
                                            таких проблем не было и условия тоже не было
                                            1. Илья Уткин 21 мая 2018, 08:50 # 0
                                              Потому что там не вызывается метод объекта, а просто выводится его свойство id. Так как объекта нет, то и свойства нет. PHP, скорее всего, генерирует предупреждение, но оно не критическое и работу не прерывает.
                                              1. AX 21 мая 2018, 09:00 # 0
                                                А свойство-tv параметр нельзя вызвать аналогично id?

                                                И еще вопрос — в процессе эксплуатация сниппета выяснилось, что данному запросу
                                                $query->where( array('pagetitle' => $idpm, 'parent' => 5) );
                                                $resource = $modx->getObject('modResource', $query);
                                                
                                                может удовлетворять не одна запись, а несколько. В основном одна, но иногда может быть несколько. getObject как я понимаю берет первую из них работает с ней. А как быть когда нужно из этой выборки проверить условие tv_name == $idpm2 и уже в случае выполнения этого условия брать TV параметр
                                                $tv = $resource->getTVvalue('tipnag');
                                                1. Илья Уткин 21 мая 2018, 09:14 # 0
                                                  1. Нет, ТВ-параметр — это отдельный объект, а не свойство ресурса.
                                                  2. Нужно использовать метод getCollection и в цикле проверять все полученные ресурсы.
                                                  1. AX 21 мая 2018, 09:40 # 0
                                                    С первым вопрос все стало на свои места, спасибо.
                                                    А с getCollection такая же история, нужно проверять
                                                    if ($resource) {
                                                    или может еще какие тонкости есть?
                                                    Потому что с getObject читал много уроков, да и эту статью, но нигде нет об этой проверке, в итоге случайно нашел рабочий код и благодаря Ваши пояснениям разобрался в чем дело.

                                Авторизация

                                через сервис Loginza:


                                Шаблоны MODX

                                1 2 Дальше »

                                Объектная
                                модель
                                MODX