[Решено] Подмена данных при формировании запросов xPDOQuery?

Пытаюсь из поля products взять массив со списком id и получить их pagetitle и добавить в Grid таблицу. Отдельно этот код работает в консоли:

$item = $this->modx->getObject('modExtraItem', 'modExtraItem.id');
        $productsList = $item->get('products');

        foreach($productsList as $product) {
            $p = $this->modx->getObject('modResource', $product);
            $id = $p->get('id');
            $c->innerJoin('modResource', 'modResource');
            $c->where(array(
                'modResource.id' => $id,
            ));
            $c->select(array($this->modx->getSelectColumns('modExtraItem', 'modExtraItem')));
            $c->select(array('modExtraItem.products as products_name'));
        }

Выводит список через запятую:

Заголовок 1, Заголовок 3, Заголовок 7

Возможно ли в процессоре getlist.class.php подменять вывод select на отформатированный свой?

/**
     * @param xPDOQuery $c
     *
     * @return xPDOQuery
     */
    public function prepareQueryBeforeCount(xPDOQuery $c)
    {
        $query = trim($this->getProperty('query'));

        // Подмена результата
        $item = $this->modx->getObject('modExtraItem', 'modExtraItem.id');
        $productsList = $item->get('products');

        foreach($productsList as $product) {
            $p = $this->modx->getObject('modResource', $product);
            $id = $p->get('id');
            $c->innerJoin('modResource', 'modResource');
            $c->where(array(
                'modResource.id' => $id,
            ));
            $c->select(array($this->modx->getSelectColumns('modExtraItem', 'modExtraItem')));
            $c->select(array('modExtraItem.products as products_name'));
        }
        // Подмена результата

        if ($query) {
            $c->where([
                'name:LIKE' => "%{$query}%",
                'OR:category_id:LIKE' => "%{$query}%"
            ]);
        }

        return $c;
    }
Мне нужно в таблице вместо id'шников выводить их заголовки из таблицы modResource.
SEQUEL.ONE
13 июня 2020, 21:13
modx.pro
1
157
0

Комментарии: 11

Илья Уткин
15 июня 2020, 18:27
0
Посмотри вот здесь пример: modx.pro/howto/9135-object-relations-in-customextra/
    SEQUEL.ONE
    15 июня 2020, 18:57
    0
    Не нашёл =( Нужно массив из поля одной таблицы связать с таблицей modResource и вывести их pagetitle через запятую. Массив в таблице имеет вот такую структуру:

    ["2","4","6"]
    Сергей Шлоков
    15 июня 2020, 18:49
    0
    $p = $this->modx->getObject('modResource', $product);
    $id = $p->get('id');
    Я правильно понимаю, что $product и $id будут идентичны? Вот думаю, удивляться или уже пора перестать.
      SEQUEL.ONE
      15 июня 2020, 18:53
      0
      Да, я распечатываю массив с id и через цикл получаю id ресурсов по одному.
        Aleksandr Huz
        15 июня 2020, 22:42
        0
        Вопрос в том, зачем получать id, если оно уже получено? ($product)

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

        Можно так:
        1. Создаем переменную
        protected $productsList = [];

        2. Получаем список id товаров и заголовки
        public function prepareQueryBeforeCount(xPDOQuery $c)
        {
            $item = $this->modx->getObject('modExtraItem', 'modExtraItem.id');
            $products= $item->get('products');
        
            $q = $this->modx->newQuery('modResource');
            $q->where(array('id:IN' => $products));
            $q->select(array('id','pagetitle'));
            if($q->prepare() && $q->stmt->execute()) {
                $this->productsList = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
            }
        
            return $c;
        }

        3. Выводим нужный массив
        public function outputArray(array $array, $count = false)
        {
            return parent::outputArray($this->productsList, $count);
        }

        P.S. Код, не проверял, в комментах набросал, возможно есть ошибки.
          SEQUEL.ONE
          15 июня 2020, 23:09
          0
          Эта задача перекликается с этой modx.pro/help/20443
            SEQUEL.ONE
            15 июня 2020, 23:12
            0
            После того как вывели массив, как его добавить в dataIndex Grid таблицы? Нужно что еще прописывать? Или оставить там 'products'?
              Aleksandr Huz
              15 июня 2020, 23:14
              0
              Должно быть доступно 2 поля, которые мы выбрали: id и pagetitle. Если для комбо, то оставляем как есть.
                SEQUEL.ONE
                15 июня 2020, 23:26
                0
                Что-то я въехать не могу, добавил код:

                <?php
                
                class modExtraItemGetListProcessor extends modObjectGetListProcessor
                {
                    public $objectType = 'modExtraItem';
                    public $classKey = 'modExtraItem';
                    public $defaultSortField = 'id';
                    public $defaultSortDirection = 'DESC';
                    protected $productsList = [];
                    //public $permission = 'list';
                
                    /**
                     * @return bool
                     */
                    public function initialize()
                    {
                        if ($this->getProperty('combo') && !$this->getProperty('limit') && $id = (int)$this->getProperty('id')) {
                            $this->item_id = $id;
                        }
                
                        return true;
                    }
                
                    /**
                     * We do a special check of permissions
                     * because our objects is not an instances of modAccessibleObject
                     *
                     * @return boolean|string
                     */
                    public function beforeQuery()
                    {
                        if (!$this->checkPermissions()) {
                            return $this->modx->lexicon('access_denied');
                        }
                
                        return true;
                    }
                
                
                    /**
                     * @param xPDOQuery $c
                     *
                     * @return xPDOQuery
                     */
                    public function prepareQueryBeforeCount(xPDOQuery $c)
                    {
                        $query = trim($this->getProperty('query'));
                
                        $c->leftJoin('modExtraCategory', 'modExtraCategory', 'modExtraCategory.id = modExtraItem.category_id');
                        $c->select(array($this->modx->getSelectColumns('modExtraItem', 'modExtraItem')));
                        $c->select(array('modExtraCategory.name as category_name'));
                
                        $c->leftJoin('modUser', 'modUser', 'modUser.id = modExtraItem.createdby');
                        $c->select(array($this->modx->getSelectColumns('modExtraItem', 'modExtraItem')));
                        $c->select(array('modUser.username as createdby_name'));
                
                        $item = $this->modx->getObject('modExtraItem', 'modExtraItem.id');
                        $products = $item->get('products');
                
                        $q = $this->modx->newQuery('modResource');
                        $q->where(array('id:IN' => $products));
                        $q->select(array('id','pagetitle'));
                        if($q->prepare() && $q->stmt->execute()) {
                            $this->productsList = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
                        }
                
                        if ($query) {
                            $c->where([
                                'name:LIKE' => "%{$query}%",
                                'OR:category_id:LIKE' => "%{$query}%"
                            ]);
                        }
                
                        return $c;
                    }
                
                
                    /**
                     * @param xPDOObject $object
                     *
                     * @return array
                     */
                    public function prepareRow(xPDOObject $object)
                    {
                        $array = $object->toArray();
                        $array['actions'] = [];
                
                        // Edit
                        $array['actions'][] = [
                            'cls' => '',
                            'icon' => 'icon icon-edit',
                            'title' => $this->modx->lexicon('modextra_item_update'),
                            //'multiple' => $this->modx->lexicon('modextra_items_update'),
                            'action' => 'updateItem',
                            'button' => true,
                            'menu' => true,
                        ];
                
                        if (!$array['active']) {
                            $array['actions'][] = [
                                'cls' => '',
                                'icon' => 'icon icon-power-off action-green',
                                'title' => $this->modx->lexicon('modextra_item_enable'),
                                'multiple' => $this->modx->lexicon('modextra_items_enable'),
                                'action' => 'enableItem',
                                'button' => true,
                                'menu' => true,
                            ];
                        } else {
                            $array['actions'][] = [
                                'cls' => '',
                                'icon' => 'icon icon-power-off action-gray',
                                'title' => $this->modx->lexicon('modextra_item_disable'),
                                'multiple' => $this->modx->lexicon('modextra_items_disable'),
                                'action' => 'disableItem',
                                'button' => true,
                                'menu' => true,
                            ];
                        }
                
                        // Remove
                        $array['actions'][] = [
                            'cls' => '',
                            'icon' => 'icon icon-trash-o action-red',
                            'title' => $this->modx->lexicon('modextra_item_remove'),
                            'multiple' => $this->modx->lexicon('modextra_items_remove'),
                            'action' => 'removeItem',
                            'button' => true,
                            'menu' => true,
                        ];
                
                        return $array;
                    }
                
                    public function outputArray(array $array, $count = false)
                    {
                        return parent::outputArray($this->productsList, $count);
                    }
                
                }
                
                return 'modExtraItemGetListProcessor';
                В items.grid.js прописано

                {
                            header: _('modextra_products'),
                            dataIndex: 'products',
                            sortable: false,
                            width: 150,
                        },
                Не отображается ничего



                Вот это поле нужно подменять, но оставить id'шники в таблице. Таблица имеет название products.

                  Aleksandr Huz
                  16 июня 2020, 09:21
                  1
                  +1
                  Теперь понятно. Значит нам в массив нужно добавить поле с заголовками товаров.

                  Примерно, так:
                  public function prepareRow(xPDOObject $object)
                  {
                          $array = $object->toArray();
                          
                          $q = $this->modx->newQuery('modResource');
                          if(!is_array($array['products'])) {
                              $array['products'] = explode(',', $array['products']);
                          }
                          $q->where(array('id:IN' => $array['products']));
                          $q->select(array('pagetitle'));
                          if($q->prepare() && $q->stmt->execute()) {
                              $resources = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
                              $array['productsTitle'] = array_map(function($res){
                                  return $res['pagetitle'];
                              },$resources);
                              $array['productsTitle'] = implode(',', $array['productsTitle']);
                          }
                          
                  
                          $array['actions'] = [];
                  
                        ....
                  }
                  Теперь в место products подставляем productsTitle

                  Удаляем ненужный код:
                  функцию — outputArray
                  и вот эти строчки тоже ни к чему
                  $item = $this->modx->getObject('modExtraItem', 'modExtraItem.id');
                  $products = $item->get('products');
                    SEQUEL.ONE
                    16 июня 2020, 18:29
                    0
                    Круто! Огромное спасибо, работает! А вот по этому https://modx.pro/help/20443 тикетсу не подскажите как настроить вывод значений в окне редактирования?
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        11