Получить все TV-поля ресурса в Fenom

Добрый день!
Подскажите пожалуйста, я могу получить данные какого то ресурса, например с id=5:
{5 | resource}
Но там не будет TV.
Данные TV ресурса могу получить так:
{5 | resource : "tv_name"}
Возможно ли получить в переменную ВСЕ TV поля ресурса с их значениями?
Например хочу так:
{set $res_five = 5 | resource}
и что бы потом мог использовать переменную $res_five и брать из неё данные TV, например:
{$res_five["tv_name"]}
Я знаю как можно это сделать написав свой сниппет, но может это уже доступно в Fenom, или забить и просто использовать {5 | resource: «tv_name»}?
gloobus
28 июня 2023, 15:41
modx.pro
780
0

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

Артур Шевченко
28 июня 2023, 18:02
0
Если у вас есть списочные данные, не надо делать 100500 ТВ, используйте Migx.
    gloobus
    29 июня 2023, 09:27
    0
    Использую, но у меня 100500 Migx'ов :)
    Dan
    Dan
    29 июня 2023, 07:39
    0
    У fenom, если не ошибаюсь, нет метода получения коллекции TV. Поэтому надо написать свой сниппет. В принципе можете потом переменной присвоить результат сниппета и работать так, как хотели. Условно:
    {set $res_five = '!getResourceTVs' | snippet : ['id' => 5]}
      Вячеслав Варов
      24 июля 2024, 17:44
      0
      Не нашли решение?
        Александр Туниеков
        24 июля 2024, 21:35
        +2
        Я тут решил немного помочь и сделал сниппет
        res
        <?php
        $id = $input;
        if (empty($id)) {
            $resource = $modx->resource;
        } else {
            $resource = $modx->getObject('modResource', ['id' => intval($id)]);
        }
        if(!$resource) return [];
        
        $out = $resource->toArray();
        $id = $resource->id;
        $sql = "
            SELECT IF(tvr.value != \"\", tvr.value, tv.default_text) AS tv_value,tv.name
            FROM {$modx->getTableName('modTemplateVarResource')} tvr
            LEFT JOIN {$modx->getTableName('modTemplateVar')} tv
            ON tv.id = tvr.tmplvarid
            LEFT JOIN {$modx->getTableName('modTemplateVarTemplate')} tvt
            ON tvt.tmplvarid = tvr.tmplvarid 
            WHERE tvr.contentid = {$id} AND tvt.templateid = {$resource->template}
        ";
        // $modx->log(1,$sql);
        $q = $modx->prepare($sql);
        $q->execute();
        $tvs = $q->fetchAll(PDO::FETCH_ASSOC);
        
        foreach($tvs as $tv){
            $out[$tv['name']] = $tv['tv_value'];
        }
        return $out;
        Использовать
        {set $res = 1 | res}
        <pre>{$res | print_r}</pre>
        Расчитанно, что все tv текстовые. Если надо чтоб tv обрабатывались перед помещением в массив, то надо вызывать getTVValue.
        foreach($tvs as $tv){
            $out[$tv['name']] = $resource->getTVValue($tv['name']);
        }
          Александр Туниеков
          24 июля 2024, 21:56
          0
          Поправил немного
          <?php
          $id = $input;
          if (empty($id)) {
              $resource = $modx->resource;
          } else {
              $resource = $modx->getObject('modResource', ['id' => intval($id)]);
          }
          if(!$resource) return [];
          
          $out = $resource->toArray();
          // чтоб страница не упала в рекурсию
          unset($out['content']);
          
          $id = $resource->id;
          $sql = "
              SELECT IF(tvr.value != \"\", tvr.value, tv.default_text) AS tv_value, tv.name, tv.type
              FROM {$modx->getTableName('modTemplateVarResource')} tvr
              LEFT JOIN {$modx->getTableName('modTemplateVar')} tv
              ON tv.id = tvr.tmplvarid
              LEFT JOIN {$modx->getTableName('modTemplateVarTemplate')} tvt
              ON tvt.tmplvarid = tvr.tmplvarid 
              WHERE tvr.contentid = {$id} AND tvt.templateid = {$resource->template}
          ";
          // $modx->log(1,$sql);
          $q = $modx->prepare($sql);
          $q->execute();
          $tvs = $q->fetchAll(PDO::FETCH_ASSOC);
          
          foreach($tvs as $tv){
              switch($tv['type']){
                  case 'text': case 'textarea':
                      $out[$tv['name']] = $tv['tv_value'];
                  break;
                  default:
                      $out[$tv['name']] = $resource->getTVValue($tv['name']);
              }
          }
          return $out;
            Вячеслав Варов
            26 июля 2024, 08:44
            0
            Спасибо!) А как с происходит обработка {resource_id | resource: 'tv_param_name'}

            каждый такой вызов делает свой отдельный запрос в бд? Я ведь правильно понимаю — использование выше сниппета выше более рационально если надо дергать 5 — 6 полей другого ресурса?
              Александр Туниеков
              26 июля 2024, 19:29
              0
              В pdoTools вот код модификатора
              $this->_modifiers['resource'] = function ($id, $field = null) use ($pdo, $modx, $fenom) {
                          $pdo->debugParserModifier($id, 'resource');
                          /** @var modResource $resource */
                          if (empty($id)) {
                              $resource = $modx->resource;
                          } elseif (!is_numeric($id)) {
                              $field = $id;
                              $resource = $modx->resource;
                          } elseif (!$resource = $pdo->getStore($id, 'resource')) {
                              $resource = $modx->getObject('modResource', ['id' => intval($id)]);
                              $pdo->setStore($id, $resource, 'resource');
                          }
              
                          $output = '';
                          if (!empty($resource)) {
                              if (!empty($field)) {
                                  if (strtolower($field) == 'content') {
                                      $output = $resource->getContent();
                                  } else {
                                      $output = $resource->get($field);
                                      if (is_null($output)) {
                                          $output = $resource->getTVValue(preg_replace('#^tv\.#i', '', $field));
                                      }
                                  }
                              } else {
                                  $output = $resource->toArray();
                              }
                          }
                          $pdo->debugParserModifier($id, 'resource');
              
                          return $output;
                      };
              Судя по $pdo->getStore ресурс где-то кешируется. Но как-то пробовал ускорить сайт 10 вызовов {resource_id | resource: 'tv_param_name'} сильно замедляют сайт.
              Я ведь правильно понимаю — использование выше сниппета выше более рационально если надо дергать 5 — 6 полей другого ресурса?
              Более рационально, если тип поля text. $resource->getTVValue($tv['name']); делает запросы в базу.
                Александр Туниеков
                26 июля 2024, 19:44
                0
                можно наверно и другие типы полей прописать без getTVValue, но я tv почти не использую. Вдаваться в подробности их обработки не буду.
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          9