Наверх

Часть 2 (Практика). Вывод свойств нескольких объектов

Итак, нам нужно выполнить следующее задание:
Задание. Написать сниппет, который выводит на страницу заголовки, аннотации и даты публикации всех новостей, если их всего пять или меньше, а если новостей больше пяти, пусть выводит содержание ресурса «Новости» (того самого контейнера, который является родительским ресурсом всех новостей).

Допустим, id ресурса с новостями 22. Тогда получить все дочерние ресурсы с заголовками, аннотациями и пр. мы можем так:
$where = array('parent' => 22);
$resources = $modx->getCollection('modResource',$where);
foreach ($resources as $res) {
      $output .= '<h2>'.$res->get('pagetitle').'</h2>';
      $output .= '<p>'.$res->get('introtext').'</p>';
      $output .= '<p><small>Дата: '.$res->get('publishedon').'</small></p>';
}
return $output;

Теперь добавим в наш код условие с количеством ресурсов:
$where = array('parent' => 22);
$resources = $modx->getCollection('modResource',$where);
if (count($resources) > 5) {

} else {
    foreach ($resources as $res) {
      $output .= '<h2>'.$res->get('pagetitle').'</h2>';
      $output .= '<p>'.$res->get('introtext').'</p>';
      $output .= '<p><small>Дата: '.$res->get('publishedon').'</small></p>';
    }
}
return $output;
Ну и, наконец, выводим контент ресурса «Новости», если самих новостей получилось больше пяти:
$where = array('parent' => 22);
$resources = $modx->getCollection('modResource',$where);
if (count($resources) > 5) {
    $res = $modx->getObject('modResource',22);
    $output = $res->get('content');
} else {
    foreach ($resources as $res) {
      $output .= '<h2>'.$res->get('pagetitle').'</h2>';
      $output .= '<p>'.$res->get('introtext').'</p>';
      $output .= '<p><small>Дата: '.$res->get('publishedon').'</small></p>';
    }
}
return $output;

G+


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

  1. Roman Iljin 11 февраля 2014, 12:52(Комментарий был изменён) # 0
    Спасибо за уроки! Вникаю и осваиваю.
    $where = array('parent' => 22);
    $resources = $modx->getCollection('modResource',$where);
    Данный код выведет непосредственных потомков ресурса с id=22.
    А как сделать рекурсивный вывод всех ресурсов находящихся в папке с id=22?
    1. Илья Уткин 11 февраля 2014, 13:43(Комментарий был изменён) # 0
      Посмотрим, как это реализовано, например, в Wayfinder:
      520 строчка:
          public function getData() {
              $depth = !empty($this->_config['level']) ? $this->_config['level'] : 10;
              $ids = $this->getChildIds($this->_config['id'],$depth);
              $resourceArray = array();
      ...
      О, у Wayfinder'а есть метод getChildIds, по названию можно предположить, что он возвращает id-шники дочерних ресурсов. Ищем его:
      485 строчка:
          public function getChildIds($startId = 0,$depth = 10) {
              $ids = array();
              if (!empty($this->_config['contexts'])) {
                  $contexts = explode(',',$this->_config['contexts']);
                  $contexts = array_unique($contexts);
                  $currentContext = $this->modx->context->get('key');
                  $activeContext = $currentContext;
                  $switched = false;
                  foreach ($contexts as $context) {
                      if ($context != $currentContext) {
                          $this->modx->switchContext($context);
                          $switched = true;
                          $currentContext = $context;
                      }
      
                      $contextIds = $this->modx->getChildIds($startId,$depth);
                      if (!empty($contextIds)) {
                          $ids = array_merge($ids,$contextIds);
                      }
                  }
      ...
      Стоп, $this->modx->getChildIds($startId,$depth);, значит, у MODX есть свой метод getChildIds, будем использовать его. Если поискать, можно найти, где он находится: на 726 строчке класса самого MODX.

      Таким образом, код, который получает все дочерние ресурсы будет выглядеть как-то так:
      $ids = $modx->getChildIds(22,50);
      $where = array('id:IN' => $ids);
      $resources = $modx->getCollection('modResource',$where);
      Я думаю, уровень вложенности 50 вам хватит?)) Но лучше поставить тот уровень вложенности, который вам подойдет.

      А теперь посмотрим на задачу — зачем нам получать все эти объекты? Может, нам как раз надо получить id-шники и подставить в запрос как дополнительное условие? Тогда нам нужна лишь первая строчка.
      1. Roman Iljin 11 февраля 2014, 15:59(Комментарий был изменён) # 0
        Огромное спасибо за подробный ответ! Тоже была изначально мысль покопаться в Wayfinder, но растерялся в его структуре.
        1. Александр Н 24 октября 2016, 19:36 # 0
          Пытаюсь вывести id всех потомков через запятую, используя ваш пример

          <?php
          $ids = $modx->getChildIds(9,3);
          $where = array(
              'id:IN' => $ids
              );
          $resources = $modx->getCollection('modResource',$where);
          foreach ($resources as $k => $res) {
            $output .= ''.$k.',';
          }
          print $output;
          Если в случае примера «ближайших» потомков всё в порядке. то в этом случае получаю серьёзные ошибки

          (ERROR @ core/xpdo/om/xpdoquery.class.php : 739)
          Encountered empty IN condition with key id
          (ERROR @ /core/xpdo/om/xpdoobject.class.php : 240)
          Error 42000 executing statement: 
          Array
          (
              [0] => 42000
              [1] => 1064
              [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
          )
           (WARN @ core/components/console/processors/exec.class.php(15) : eval()'d code : 10)
          PHP notice: Undefined variable: output
          Подскажите пожалуйста, в чём проблема?
          1. Илья Уткин 25 октября 2016, 08:16 # 0
            Encountered empty IN condition with key id
            Видимо, дочерних ресурсов не найдено. Попробуйте сначала вывести просто
            $ids = $modx->getChildIds(9,3);
            print implode(',', $ids);
            1. Александр Н 25 октября 2016, 12:35 # 0
              Дочерние ресурсы точно есть — второго и третьего уровня.
              При использовании кода выше ничего не выводит, но и ошибок нет.
              1. Евгений 13 августа 2018, 03:25(Комментарий был изменён) # 0
                Вот рабочий код:
                $child = $modx->getChildIds(146, 10, array('context' => 'web'));
                $collection = $modx->getCollection('modResource', array(
                    'id:IN' => $child,
                    'published' => true,
                    'deleted' => false,
                ));
      2. Galeups 23 апреля 2014, 00:01 # 0
        Илья, огромное спасибо за уроки. Начал изучение внутренностей MODx благодаря Вам.
        Немного не понятна вот эта конструкция:
        $where = array('parent' => 22);
        Я понимаю, что это условие выборки, но при чем здесь массив?
        Сразу извините, если вопрос показался очень глупым, но хочу разобраться до конца.
        1. Илья Уткин 23 апреля 2014, 00:09 # 0
          А как можно другим способом задать условие?

          Даже человеческим языком это будет «Ресурсы, у которых родитель равен 23»
          1. Galeups 23 апреля 2014, 11:48 # 0
            Кажется понял свою ошибку.
            Мы объявляем отдельный массив с одним элементом 'parent'.
            Просто смутило, что выборки то ещё нет, и как мы можем в не объявленном массиве что то искать по условию.
            Я думал, что в этой конструкции уже работаем с полученным массивом элементов…
            Не пинайте сильно, пойду учить параллельно php…
        2. Алекс 02 февраля 2016, 05:28(Комментарий был изменён) # 0
          Привет, чет не пашет из консольки.да и вообще чего-то половина белый экран при команде выполнить(( уроков
          $where = array('parent' => 22);
          $resources = $modx->getCollection('modResource',$where);
          foreach ($resources as $res) {
                $output .= '<h2>'.$res->get('pagetitle').'</h2>';
                $output .= '<p>'.$res->get('introtext').'</p>';
                $output .= '<p><small>Дата: '.$res->get('publishedon').'</small></p>';
          }
          return $output;
          1. Илья Уткин 02 февраля 2016, 07:36 # 0
            Ну, видимо, ресурса с id 22 на сайте нет… Или у него нет дочерних ресурсов. Код в уроках упрощенный, естественно, надо проверять всё на существование:
            if (!$modx->getObject('modResource', 22)) {
              print "Ресурс с id 22 не найден";
              return;
            }
            $where = array('parent' => 22);
            $resources = $modx->getCollection('modResource',$where);
            if (!$resources) {
              print "У ресурса 22 нет дочерних ресурсов";
              return;
            }
            foreach ($resources as $res) {
                  $output .= '<h2>'.$res->get('pagetitle').'</h2>';
                  $output .= '<p>'.$res->get('introtext').'</p>';
                  $output .= '<p><small>Дата: '.$res->get('publishedon').'</small></p>';
            }
            print $output;
            return;
          2. Юрий Войтюк 30 ноября 2017, 10:04 # 0
            Спасибо за уроки. Есть вопрос. А как задавать условия с двумя и более полями?
            Если я просто добавляю новый элемент в массив, например:
            $where = array(
                'parent' => 7,
                'id' => 9
                );
            

            То условие задается как: parent = 7 И id = 9
            А если мне например вместо условия И понадобится ИЛИ?
            1. Илья Уткин 30 ноября 2017, 12:55 # 0
              $where = array(
                  'parent' => 7,
                  'OR:id' => 9
              );
              1. Юрий Войтюк 30 ноября 2017, 13:04 # 0
                Спасибо!
            2. Вадим Бошовский 27 декабря 2017, 13:34 # 0
              Добрый день! Пытаюсь написать скрип для проверки оплаты пользователем аккаунту. Суть в том что если пользователь авторизован то нужно проверить оплачен у него аккаунт или нет. Если оплачен то открыть доступ к урокам, а если нет то открыть только к 3 первым урокам. Опыта большого на php имею, только начинаю. а сроки горят(((. Вот сделал небольшие наброски хотя и ими назвать стыдно. подсказали что нужно использовать getObject. Вот такая структура ресурсов yadi.sk/i/beyXQqGD3QzzsD. Пользователю который оплатил должна сразу ставиться галочка опубликован.
              <?php
              <?
              $whereLog = array(
                  'parent'=> 3,
                  'description' => $login,
                  'publishedon' => true
                  );
              $login = $modx->getObject('modResource', $whereLog);
              if(isset($login)){
                 if($login == $id->get('publishedby'))
              $output = $login('$id');

              и второй набросок
              $where = array('parent' => 22);
              $resources = $modx->getCollection('modResource',$where);
              if ($login == $id) > 5) {
                  $res = $modx->getObject('modResource', '$id');
                  $output = $res->get('publishedon');
              } else {
              1. Илья Уткин 08 января 2018, 15:20 # 0
                Свойство «опубликован» будет применяться для любого пользователя. Тут нужно работать именно с доступом к ресурсам — разбираться с правами пользователей, группами и пр.

                Лучше воспользоваться готовым компонентом: modstore.pro/payandsee
              2. Олег 12 ноября 2019, 16:31 # 0
                Разобрался

                $ids = $modx->getChildIds(11,3,array('context' => 'web'));
                print implode(',', $ids);
                
                $where = array(
                    'id:IN' => $ids,
                );
                
                $resources = $modx->getCollection('modResource', $where);
                $output = '<p>Вложенные ресурсы</p>';
                $output .= '<p>Всего ресурсов: '.count($resources).'</p>';
                foreach ($resources as $res) {
                       $output .= '<h2> '.$res->get('pagetitle').'</h2>';
                }
                echo $output;
                
                

                Авторизация

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


                Шаблоны MODX

                1 2 Дальше »

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