Вывод данных из БД

Накидал сниппет для вывода нужных данных из БД. Верстку в РНР не хочется делать — долго. Добавил блок для вывода прямо в сниппете. Все работает, но появляется информация о возврате какой-то функции.
Код сниппета(укороченный)
<?php
$sth = $modx->query("SELECT * FROM reg_users");
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $data) {
    $regNum = $data['regNum'];
}
?>
<div><?php echo $regNum;?></div>
выводит
3173
return; 1
значение переменной $regNum верное. А вот откуда берется return; 1 понять не могу.
Если выводить таким образом
<?php
$sth = $modx->query("SELECT * FROM reg_users");
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $data) {
    $regNum = $data['regNum'];
}
echo '<div>' .$regNum. '</div>';
?>
то все нормально.
Просто данных гораздо больше и при их выводе используется довольно сложная верстка и верстать вывод html тегов на php очень не хочется.
Дмитрий
30 августа 2021, 19:15
modx.pro
1
1 718
0

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

Andrey
30 августа 2021, 20:16
0
Есть прямая рекомендация так не делать, потому что работать не будет. Да и закрывать php в сниппете не надо. Полагаю, что это вывод сообщения обработчика, типа return — отдано; 1 — успешно.
    Павел Романов
    30 августа 2021, 20:18
    1
    0
    Используйте getChunk.
    Например:
    <?php
    $sth = $modx->query("SELECT * FROM reg_users");
    $result = $sth->fetchAll(PDO::FETCH_ASSOC);
    foreach ($result as $data) {
        $regNums .= $modx->getChunk($tpl, array('regNum' => $data['regNum']);
    }
    return $modx->getChunk($tplWrapper, array('output' => $regNums));

    В вызове указывайте параметры:
    [[SnippetName?  
        &tplWrapper=`chunk1` 
        &tpl=`chunk2`
    ]]

    Ну а там уже оформляйте как угодно.
    В chunk2, к примеру:
    <ul>[[+output]]</ul>

    В chunk2:
    <li>[[+regNum]]</li>
      Ilya
      31 июля 2022, 14:30
      0
      Здравствуйте, Павел.
      Вы можете помочь разделить нижеследующий код на сниппет и чанк/и?:

      foreach($content_currency->Record as $currency) {
      
      	$content_currency_result[0][] = '"'.(string)$currency->attributes()->Date.'"';
      	$content_currency_result[1][] = str_replace(',', '.', $currency->Value);
      
      }
      	return $content_currency_result;
      }
      На сайте я вывожу их так:
      <?php echo implode(', ', $currencyArr[1]); ?>
        <?php echo implode(', ', $currencyArr[0]); ?>
        Ilya
        31 июля 2022, 16:29
        0
        У меня тоже под результатом выходит текст return; 1 если в сниппете смешиваются html и php коды.
        Пытался разделить смешанный код на сниппет и чанк, но не получается.

        Павел, надеюсь, что вы и мне тоже поможете. Заранее спасибо!
          Павел Романов
          31 июля 2022, 16:49
          +1
          У Вас нет HTML и выводить в чанк нет смысла.
          Сделайте вывод прямо в сниппете:
          <?php
          $dates= array();
          $values = array();
          
          foreach($content_currency->Record as $currency) {
              $dates[] = '"'.(string)$currency->attributes()->Date.'"';
              $values[] = str_replace(',', '.', $currency->Value);
          }
          echo implode(', ', $dates);
          echo implode(', ', $values);
          return;

          Этого, естественно, не нужно:
          <?php echo implode(', ', $currencyArr[1]); ?>
          <?php echo implode(', ', $currencyArr[0]); ?>
            Ilya
            31 июля 2022, 17:03
            0
            Добрый день, Павел. Большое спасибо за ответ!
            Дело в том, что эти данные я вывожу в графиках с помощью Apexcharts.
            Код был большим. Поэтому я сокращенно написал их.
            Вот как оно выглядит:
            <div id="chart" style="max-width: 760px; margin: 35px auto; opacity: 0.9;">
              <div id="responsive-chart"></div>
            </div>
            
            <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
            <script>
                var options = {
              chart: {
                width: "100%",
                height: 380,
                type: "area"
              },
              plotOptions: {
                bar: {
                  horizontal: true
                }
              },
              dataLabels: {
                enabled: false
              },
              fill: {
                      type: 'gradient',
                      gradient: {
                        shadeIntensity: 1,
                        inverseColors: false,
                        opacityFrom: 0.5,
                        opacityTo: 0,
                        stops: [0, 90, 100]
                      },
              series: [
                {
                  name: "Курс",    
                  data: [<?php echo implode(', ', $currencyArr[1]); ?>]
                }
              ],
              xaxis: {
                categories: [<?php echo implode(', ', $currencyArr[0]); ?>]
              },
              title: {
                      text: 'Динамика курса доллара США',
                      align: 'left'
                    },
                    stroke: {
                      curve: 'straight'
                    },
              legend: {
                position: "right",
                verticalAlign: "top",
                containerMargin: {
                  left: 35,
                  right: 60
                }
              },
              responsive: [
                {
                  breakpoint: 1000,
                  options: {
                    plotOptions: {
                      bar: {
                        horizontal: false
                      }
                    },
                    legend: {
                      position: "bottom"
                    }
                  }
                }
              ]
            };
            
            var chart = new ApexCharts(
              document.querySelector("#responsive-chart"),
              options
            );
            
            chart.render();
            
            </script>
            Данный html код я выводил вместе с php кодом внутри сниппета. Поэтому под графикой выводилась ошибка return; 1.
              Павел Романов
              31 июля 2022, 17:16
              1
              +1
              Тут тоже чанк не нужен. Используйте setPlaceholders:
              <?php
              $dates= array();
              $values = array();
              
              foreach($content_currency->Record as $currency) {
                  $dates[] = '"'.(string)$currency->attributes()->Date.'"';
                  $values[] = str_replace(',', '.', $currency->Value);
              }
              
              $modx->setPlaceholders(array(
                  'dates' => implode(', ', $dates),
                  'values' => implode(', ', $values),
              ));
              
              return;

              Вызывайте сниппет где-нибудь в начале страницы, а в скрипте вставьте плейсхолдеры:
              //..........
              series: [
                  {
                    name: "Курс",    
                    data: [ [[+values]] ]
                  }
                ],
                xaxis: {
                  categories: [ [[+dates]]  ]
                },
              //..........
                Ilya
                31 июля 2022, 18:47
                0
                Что-то
                [[+value]] и [[+dates]]
                пустыми отображаются.
                  Ilya
                  31 июля 2022, 20:26
                  0
                  Не знаю, что сделал, но теперь уже работает.
                  Ilya
                  31 июля 2022, 20:27
                  0
                  Павел, большое вам спасибо за помощь! Все отлично работает.
            Ilya
            31 июля 2022, 23:11
            0
            Павел, а как быть с выводом данных в таблицу? В обычном php файле, следующий код работает, но используя в сниппете выходит ошибка return;1.
            <?php
            function get_currency_td($currency_code = 'R01235') {
            
            $date_start = date('d/m/Y', strtotime('-30 days')); // Дата начала выборки
            	$date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
            
            $cache_time_out = 86400; // Время жизни кэша в секундах
            
            $file_currency_cache = './currency.xml'; // Файл кэша
            
            if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
            
            $ch = curl_init();
            
            curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ='.$currency_code);
            
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            
            curl_setopt($ch, CURLOPT_HEADER, 0);
            
            $out = curl_exec($ch);
            
            curl_close($ch);
            
            file_put_contents($file_currency_cache, $out);
            
            }
            
            $content_currency = simplexml_load_file($file_currency_cache);
            
            $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
            
            foreach($content_currency->Record as $currency) {
            
            $content_currency_result .= '<tr><td>'.$currency->attributes()->Date.' </td><td> '.$currency->Value.'</td><td></td></tr>';
            
            }
            
            return $content_currency_result;
            
            }
            
            ?>
            <div class="currency-exchange">
            
            <div class="ce-title">Таблица изменений курса доллара США за 30 дней</div>
            
            <table class="table table-condensed ce-table">
            
            <thead>
            
            <tr>
            
            <td>Дата</td>
            
            <td>Курс рублей за 1 usd</td>
            
            <td>Изменение</td>
            
            </tr>
            
            </thead>
            
            <tbody>
            
            <?php echo get_currency_td('R01235'); ?>
            
            </tbody>
            
            </table>
            </div>
            Оставив только php код в сниппете и переносив html код в шаблон, пробовал использовать setPlaceholders, но с таблицей не получается. Данные отображаются внутри одного
            <tr>
            <td></td>
            <td></td>
            <td></td>
            </tr>
            Вот скриншот: https://skr.sh/sFCZaUMux90?a
            А необходимо чтобы данные распределились в отдельные tr td.

            Предполагаю, что тут уже без чанка/ов не обойтись, верно?
            Если да, то как это реализовать? Заранее спасибо!
              Павел Романов
              01 августа 2022, 10:27
              1
              +1
              Поскольку тут уже HTML, то через getChunk.
              Сниппет:
              <?php
              $out = '';
              $date_start = date('d/m/Y', strtotime('-30 days')); // Дата начала выборки
              $date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
              $cache_time_out = 86400; // Время жизни кэша в секундах
              $file_currency_cache = './currency.xml'; // Файл кэша
              if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
                  $ch = curl_init();
                  curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ='.$currency_code);
                  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                  curl_setopt($ch, CURLOPT_HEADER, 0);
                  $out = curl_exec($ch);
                  curl_close($ch);
                  file_put_contents($file_currency_cache, $out);
              }
              $content_currency = simplexml_load_file($file_currency_cache);
              $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
              
              foreach($content_currency->Record as $currency) {
                  $items .= $modx->getChunk($tpl, array(
                      'date' => $currency->attributes()->Date,
                      'value' => $currency->Value,
                  ))
              }	
              if($items != '') $out = $modx->getChunk($tplWrapper, array('items' => $items));
              return $out;

              Вызов:
              [[snippetName?
                  &tplWrapper=`chunk_wrapper`
                  &tpl=`chunk_item`
              ]]

              Чанк chunk_wrapper:
              <div class="currency-exchange">
                  <div class="ce-title">Таблица изменений курса доллара США за 30 дней</div>
                  <table class="table table-condensed ce-table">
                      <thead>
                          <tr>
                              <td>Дата</td>
                              <td>Курс рублей за 1 usd</td>
                              <td>Изменение</td>
                          </tr>
                      </thead>
              
                      <tbody>
                          [[+items]]
                      </tbody>
                  </table>
              </div>

              Чанк chunk_item:
              <tr>
                  <td>[[+date]]</td>
                  <td>[[+value]]</td>
                  <td></td>
              </tr>
                Ilya
                01 августа 2022, 11:30
                0
                Павел, добрый день! Спасибо большое за подробный ответ.
                Без ; после:
                foreach($content_currency->Record as $currency) {
                    $items .= $modx->getChunk($tpl, array(
                        'date' => $currency->attributes()->Date,
                        'value' => $currency->Value,
                    ))
                на сайте выдает ошибку 500.
                Вставляю ; после двух скобок ));, ошибка пропадает.
                Но таблица отображается. Но уже с пустыми [[+date]] и [[+value]]. Скриншот: https://skr.sh/sFDGc49PTvC?a.

                P.S В сниппет я также добавил строку:
                $currency_code = 'R01235';
                Думал, что может из-за этого таблица пустая. Но, оказывается не из-за этого.
                  Павел Романов
                  01 августа 2022, 12:00
                  1
                  +1
                  Да, добавьте точку с запятой, я опечатался.

                  Если Вы используете функцию, то нужно в ней объявить глобальную переменную $modx:
                  function get_currency_td($currency_code = 'R01235') {
                      global $modx;
                      $out = '';
                      $date_start = date('d/m/Y', strtotime('-30 days')); // Дата начала выборки
                      $date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
                      $cache_time_out = 86400; // Время жизни кэша в секундах
                      $file_currency_cache = './currency.xml'; // Файл кэша
                      if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
                          $ch = curl_init();
                          curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ='.$currency_code);
                          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                          curl_setopt($ch, CURLOPT_HEADER, 0);
                          $out = curl_exec($ch);
                          curl_close($ch);
                          file_put_contents($file_currency_cache, $out);
                      }
                      $content_currency = simplexml_load_file($file_currency_cache);
                      $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
                      
                      foreach($content_currency->Record as $currency) {
                          $items .= $modx->getChunk($tpl, array(
                              'date' => $currency->attributes()->Date,
                              'value' => $currency->Value,
                          ));
                      }	
                      if($items != '') $out = $modx->getChunk($tplWrapper, array('items' => $items));
                      return $out;
                  }
                  Но потом, естественно, в сниппете где-то нужно эту функцию вызывать.

                  Но если у Вас задача вывести этим сниппетом только курсы доллара, функция не нужна, но надо непосредственно указать код валюты (в 9 строке):
                  <?php
                  $out = '';
                  $date_start = date('d/m/Y', strtotime('-30 days')); // Дата начала выборки
                  $date = date('d/m/Y'); // Текущая дата (используется для кэша и для конца выборки)
                  $cache_time_out = 86400; // Время жизни кэша в секундах
                  $file_currency_cache = './currency.xml'; // Файл кэша
                  if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
                      $ch = curl_init();
                      curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='.$date_start.'&date_req2='.$date.'&VAL_NM_RQ=R01235');
                      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                      curl_setopt($ch, CURLOPT_HEADER, 0);
                      $out = curl_exec($ch);
                      curl_close($ch);
                      file_put_contents($file_currency_cache, $out);
                  }
                  $content_currency = simplexml_load_file($file_currency_cache);
                  $content_currency_result = ''; // Переменная для объединения всех дней в одну группу
                  
                  foreach($content_currency->Record as $currency) {
                      $items .= $modx->getChunk($tpl, array(
                          'date' => $currency->attributes()->Date,
                          'value' => $currency->Value,
                      ));
                  }	
                  if($items != '') $out = $modx->getChunk($tplWrapper, array('items' => $items));
                  return $out;
                    Ilya
                    01 августа 2022, 12:11
                    0
                    Да, задача вывести этим сниппетом только курсы доллара по дням.
                    Поэтому использовал второй вариант без функции.
                    Но не могу понять, почему-то [[+date]] и [[+value]] возвращаются пустыми.
                      Павел Романов
                      01 августа 2022, 12:25
                      1
                      +1
                      К строке приведите:
                      // .............
                      foreach($content_currency->Record as $currency) {
                          $items .= $modx->getChunk($tpl, array(
                              'date' => (string)$currency->attributes()->Date,
                              'value' => (string)$currency->Value,
                          ));
                      }
                      // .............
                        Ilya
                        01 августа 2022, 12:30
                        0
                        Павел, огромное вам спасибо! Задача решена.
            Andrey
            30 августа 2021, 20:39
            0
            Ну или можно попробовать поиграть в прятки с обработчиком и открыть в конце сниппета пустой php, например:
            <?php
            $sth = $modx->query("SELECT * FROM reg_users");
            $result = $sth->fetchAll(PDO::FETCH_ASSOC);
            foreach ($result as $data) {
                $regNum = $data['regNum'];
            }
            ?>
            <div><?php echo $regNum;?></div>
            <?php
            если хочется костылей :D
              Дмитрий
              30 августа 2021, 22:07
              0
              Не, костылей не надо. И так хромаю на обе ноги))) Рецепт от Павла Романова помог. Спасибо всем!
              vectorserver
              07 сентября 2021, 21:53
              0
              <?php
              $sth = $modx->query("SELECT * FROM reg_users");
              $result = $sth->fetchAll(PDO::FETCH_ASSOC);
              foreach ($result as $data) {
                  $regNum = $data['regNum'];
              }
              ?>
              <div><?php echo $regNum;?></div>
              <?php return ''; ?>
                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                20