Поругайте код, мне будет полезно
        Господа, буду рад любым предложениям по улучшению этого написанного мною кода.
Поскольку я дилетант, то наверняка делаю это топорно и не изящно.
Поставил себе цель написать сниппет, который будет выводить на экран значения MIGX TV для всех ресурсов, которые будут дочерними к ресурсу родителю, чей id будет задаваться как параметр сниппета.
    
    
                                                                                
            Поскольку я дилетант, то наверняка делаю это топорно и не изящно.
Поставил себе цель написать сниппет, который будет выводить на экран значения MIGX TV для всех ресурсов, которые будут дочерними к ресурсу родителю, чей id будет задаваться как параметр сниппета.
<?php
// получаем id родительского каталога как параметр
$p=$parent;
// выборка всех ресурсов, у кого родитель имеет переданный id 
// и формируем массив с id ресурсов-детей.
$g=$modx->getCollection('modResource',array('parent'=>$p));
foreach ($g as $g1){
    $where[]=$g1->get('id');
}
// проходим по всем элементам нашего массива, делая выборку одного объекта
// значение contentid которого совпадает с id из массива
// поскольку я задался целью получить только MIGX то прописываю id этого объекта
foreach ($where as $nowhere){
    $result=$modx->getObject('modTemplateVarResource',array('contentid'=>$nowhere,'tmplvarid'=>1));
// добавил сюда проверку на существование $result поскольку не все ресурсы могут иметь заполненные
// MIGX поля
    if ($result){
// $res становится строкой, в которой лежит JSON
    $res=$result->get('value');
//$r становится массивом
    $r=$modx->fromJSON($res);
// перебираем все елементы массива, чтобы добраться до содержимого. 
// У меня поле имеет название text
// в результате получаем вывод на экран перечня значений всех MIGX для всех ресурсов
// дочерних к тому, чей id мы передали в сниппет
    foreach ($r as $r1){ echo $r1['text']."
";}
 } //end if
} // end foreachСпасибо.    Комментарии: 8
                1. Код должен быть читаемым и понятным, пусть и длиннее.
И вообще, если у вас есть переменная $result, то должно быть return $result, что очень логично)
2. В сниппетах не нужно делать echo, только return.
                    $p=$parent;
$g as $g1
$where as $nowhere
$result => $res => $rНе надо так делать.И вообще, если у вас есть переменная $result, то должно быть return $result, что очень логично)
2. В сниппетах не нужно делать echo, только return.
                Спасибо.
Насчет названий переменных, Вы правы.
Насчет echo — тоже, хотя я ставил целью именно вывести на экран.
Кстати, раз уж мы коснулись echo и return — Вы замечали, что сниппет modx печатает на экран то, что вызывается как return?
В нем return ведет себя не как в PHP. Поэтому применение return в моем конкретном случае привело бы к показу первого результата.
Если задаваться целью сделать вывод в чанк, то наверное, правильно было бы в цикле формировать строковую переменную с вызовом getChunk() а уже в конце делать return этой переменной.
                    Насчет названий переменных, Вы правы.
Насчет echo — тоже, хотя я ставил целью именно вывести на экран.
Кстати, раз уж мы коснулись echo и return — Вы замечали, что сниппет modx печатает на экран то, что вызывается как return?
В нем return ведет себя не как в PHP. Поэтому применение return в моем конкретном случае привело бы к показу первого результата.
Если задаваться целью сделать вывод в чанк, то наверное, правильно было бы в цикле формировать строковую переменную с вызовом getChunk() а уже в конце делать return этой переменной.
                Вместо 
лучше создать переменную $output и выводить потом ее
                    echo $r1['text']лучше создать переменную $output и выводить потом ее
foreach ($r as $r1) {
    $output .= $r1['text'];
}
//и в конце сниппета
return $output            
                Спасибо, согласен.            
                    
                Про названия переменных уже сказали, это ужасно. Никогда так не делайте, называйте переменные правильно и не придется писать тонны комментариев к коду.
Второ момент, зачем тут такие странные манипуляции?
Простой пример, у вас сниппет в зависимости от параметра должен выдавать или строку на экран или json в случае ajax-запроса. В таком случае можно сделать так:
                    Второ момент, зачем тут такие странные манипуляции?
$g=$modx->getCollection('modResource',array('parent'=>$p));
foreach ($g as $g1){
    $where[]=$g1->get('id');
}Лучше использовать getIterator, на большом количестве ресурсов памянть не закончится, это раз. Два раза вы делаете проход по массиву, абсолютно бесполезно. Вы же и так перебираете ресурсы, почему не сделать вот так?foreach ($modx->getIterator('modResource', array('parent' => $parent)) as $resource) {
    $result = $modx->getObject('modTemplateVarResource', array('contentid' => $resource->get('id'), 'tmplvarid' => 1));
    ...
}Большая вложенность кода в {} ухудшает читабельность кода, поэтому идеальный код — это прямой без ветвлений или стараться их избегать где возможно. Например, вместо проверки, есть ли значение в переменной и выполнения кода внутри if, можно проверить, что если значение пустое, то пропустить остальной код и перейти на следующую итерацию.if (!$result) {
    continue;
}
$res = $result->get('value');Про return из сниппета вам уже сказали, лучше собирать весь вывод в буфер в виде массива или строки и потом уже выводить одним return. Это даст возможность в дальнейшем, когда условия задачи изменятся, еще раз пройтись по массиву или строку и применить дополнительные действия над результатом.Простой пример, у вас сниппет в зависимости от параметра должен выдавать или строку на экран или json в случае ajax-запроса. В таком случае можно сделать так:
$output = [];
foreach ($r as $r1) { 
    $output[] = $r1['text'];
}
return $ajax ? 
    json_encode($output)
    join("", $output);И последнее, несмотря на то, что параметры в снипете уже присутствуют в виде переменных, лучше получать их значения через API MODX. Это в дальнейшем даст возможность использовать Property Sets (предустановленные параметры) и значения по умолчанию.$parent = $modx->getOption('parent', $scriptProperties, null);            
                Спасибо, вот именно по этому я и говорю, что явно решаю вопрос топорно в силу своих слабых знаний.            
                    
                Для получения значений ТВ-параметров у ресурсов MODX есть метод getTVValue. Он делает то же самое, но код становится чище, опрятнее и гораздо более читабельным:
Ну и в дальнейшем нужно углублять знания SQL и xPDO.
В этом коде делается много запросов к базе данных: сначала получаем все нужные ресурсы (1 запрос), и потом на каждый ресурс делаем дополнительный запрос в базу, чтобы получить значение TV-параметра. При большом количестве ресурсов сниппет будет создавать нехилую нагрузку.
Чтобы такого избежать, используем LEFT JOIN:
                    $res = $g1->getTVValue('tv_name');Ну и в дальнейшем нужно углублять знания SQL и xPDO.
В этом коде делается много запросов к базе данных: сначала получаем все нужные ресурсы (1 запрос), и потом на каждый ресурс делаем дополнительный запрос в базу, чтобы получить значение TV-параметра. При большом количестве ресурсов сниппет будет создавать нехилую нагрузку.
Чтобы такого избежать, используем LEFT JOIN:
// Выборка ресурсов сразу с ТВ-шками
$q = $modx->newQuery('modResource', array('parent' => $parent));
$q->leftJoin('modTemplateVarResource', 'MIGX', 'modResource.id = MIGX.contentid AND MIGX.tmplvarid = 1');
$q->select('`MIGX`.`value` AS `text`');
$g = $modx->getIterator('modResource', $q);
// Получение нужных полей из JSON
foreach ($g as $g1){
    $res = $g1->get('text');
    if (!$res) {
        continue;
    }
    $r = $modx->fromJSON($res);
    foreach ($r as $r1){
        $output[] = $r1['text'];
    }
}            
                Ой, ну и ограничить выборку, конечно, надо
                    $q->where(array(
    'MIGX.value:!=' => '',
    'MIGX.value:!=' => '[]',
    'MIGX.value:IS NOT' => NULL
));            
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.