Тест вложенности ресурса в контейнер [с блекджеком и плюхами]
        Проверить, есть ли контейнер в списке родителей ресурса, можно разными способами:
P.S.: За то, что так скрупулёзно отношусь к нагрузке на сервер и скорости работы скрипта, спасибо Михаилу Воеводскому, что ткнул носом однажды. =)
    
    
                                                        - Можно сделать это используя карту ресурсов, которую MODX создаёт для каждого контекста после обновления кеша. Для этого необходимо воспользоваться методом $modx->getParentIds. Таким образом нагрузка и время затрачиваемое на проверку будет минимальным.
 - Не заморачиваться и сделать всё исключительно на Fenom, без модификаторов. Тут мы тоже можем воспользоваться методом $_modx->getParentIds, который Василий услужливо вынес в список доступных в Fenom.
 - Можно даже извратиться до того, что на каждую такую проверку получать объект через getObject('modResource') + получать объекты его родителей через getOne('Parent'). К слову, что будет в случае, если нам, к примеру, надо проверить 50 товаров на странице на вложенность в определённую категорию?
Ради интереса, я воспроизвёл подобную ситуацию на тестовом сайте Modhost:
- Без каких-либо проверок 50 товаров в списке категории выводятся за 0,0282 сек.
 - С подобной проверкой, за 0.1304 сек.
 - С проверкой, которую мы рассматриваем в этом посте, за 0.0307 сек.
 
А потом заказчики сходят с ума, почему их сайт так долго открывается... 
Поймите меня правильно
Дело даже не столько в единичном сниппете, сколько в самом подходе к разработке. Если для исполнителя нет ничего страшного в подобном сниппете, который прибавляет 0.1 секунду ко времени загрузки страницы при определённых условиях, то заказчику потом приходится тратить в двое больше на оптимизацию сайта или жить с тем, что есть.Преимущества данного решения
В чём же преимущества данного решения в отличие, к примеру, от этого:- Скорость работы и низкая нагрузка на сервер,
 - Возможность передавать опции, вроде ключа контекста,
 - Возможность указать уровень вложенности проверки,
 - Основной параметр проверки (id контейнера) не вшит в сниппет, а указывается извне.
 
Сниппет-модификатор проверки вложенности ресурса в контейнер
Каким же должен быть правильный сниппет-модификатор проверки вложенности ресурса в контейнер:// Parent
$parent = ($options['parent'] ?: null);
unset($options['parent']);
if (empty($input) || empty($parent)) {
    return null;
}
// Height
$height = ($options['height'] ?: 10);
unset($options['height']);
// Alt keys
foreach (array(
    'context_key' => 'context',
    'ctx' => 'context',
) as $k => $v) {
    if (isset($options[$k])) {
        $options[$v] = $options[$k];
    }
}
if (!$parents = $modx->getParentIds($input, $height, $options)) {
    return null;
}
return in_array($parent, $parents) ?: null;Создаём сниппет inParent с этим кодом.Пример использования
Использовать его до безобразия просто:{if ($_modx->resource['id'] | inParent : [
    'parent' => 2,
    'height' => 3,
    'ctx' => 'web',
])?}
    Родитель с id 2 найден на 3 уровня вверх в контексте web.
{else}
    Не найден.
{/if}P.S.: За то, что так скрупулёзно отношусь к нагрузке на сервер и скорости работы скрипта, спасибо Михаилу Воеводскому, что ткнул носом однажды. =)
            
                Поблагодарить автора            
            
                 Отправить деньги            
        
        
            Комментарии: 8
                Спасибо за труд, очень правильно, что написали. 
Сам внимательно отношусь к нагрузке на сервер и скорости загрузки, т.к. как покупатель не люблю тормозные сайты.
Сильно не хватает таких постов с разбором внутренних механизмов кеширования модх.
Хотя про getParentids и getchildIds все должны знать.
Есть еще полезный findResource
В вот так нужный getResourceURI так и не появился(( forums.modx.com/index.php/topic,58207.msg332426.html
                    Сам внимательно отношусь к нагрузке на сервер и скорости загрузки, т.к. как покупатель не люблю тормозные сайты.
Сильно не хватает таких постов с разбором внутренних механизмов кеширования модх.
Хотя про getParentids и getchildIds все должны знать.
Есть еще полезный findResource
В вот так нужный getResourceURI так и не появился(( forums.modx.com/index.php/topic,58207.msg332426.html
                Не стал создавать отдельный топик.
Вот пример как делают настоящие хардкорные программисты для получения тайтла родителя верхнего уровня:
                    Вот пример как делают настоящие хардкорные программисты для получения тайтла родителя верхнего уровня:
if(!$level_1){
                	$parentID = @$modx->resource->get('parent');
    				$document = @$modx->getObject('modResource',array(
        				'id' => $parentID,
    				));
                	$parentID = @$document->get('parent');
        			$document = @$modx->getObject('modResource',array(
            			'id' => $parentID,
        			));
        			$parentID = @$document->get('parent');
        			$document_parent = @$modx->getObject('modResource',array(
            			'id' => $parentID,
        			));
        			$level_1="";
        			if($document_parent) {
            			$level_1 = $document_parent->get('pagetitle');
            			$level_1= mb_strtolower($level_1, 'UTF-8');
        			};
                };Сегодня получил этот код от своих тру сеошников            
                Ничего себе у вас SEOшники код пишут ))            
                    
                Но это опять же долгий способ с получением нескольких объектов, да ещё и не универсальный. 
Хотя даже с получением объектов можно было сделать цикл, где выискивался бы самый верхний родитель.
Подходить лишь для такой структуры:
Родитель 1
— Родитель 2
— Родитель 3
— Ресурс
P.S. Как я думаю, супер скорость будет при getParentIds и запроса newQuery с лимитом 1 и выборкой pagetitle.
                    Хотя даже с получением объектов можно было сделать цикл, где выискивался бы самый верхний родитель.
Подходить лишь для такой структуры:
Родитель 1
— Родитель 2
— Родитель 3
— Ресурс
P.S. Как я думаю, супер скорость будет при getParentIds и запроса newQuery с лимитом 1 и выборкой pagetitle.
                Я как антипример и дал. 
Вот кусочек кода, который сам использую для вытаскивания всех тайтлов родителей просто для примера:
                    Вот кусочек кода, который сам использую для вытаскивания всех тайтлов родителей просто для примера:
$parent_ids=$this->modx->getParentIds($id, $level, array('context' => $context));
      $where = array(
        'id' => $parentIds
        );
        array_push($parent_ids,$id); 
        if(is_array($parent_ids)&&count($parent_ids)>0) {
            $p_query = $this->modx->newQuery('modResource');
            $p_query->select(array('id','pagetitle'));
            $p_query->distinct();
            $p_query->sortby('id', 'asc');
            $p_query->where(array('id:IN' => $parent_ids));            
            if ($p_query->prepare() && $p_query->stmt->execute()){     
                $p_out= array();        
               // $this->modx->log(modX::LOG_LEVEL_ERROR, $p_query->toSql());        
                $p_out=$p_query->stmt->fetchAll(PDO::FETCH_ASSOC);                
                //$this->modx->log(modX::LOG_LEVEL_ERROR, $p_out); 
                $titles_array=array();
               
                foreach ($p_out as $val){                
                 $titles_array[]=$val['pagetitle'];         
                }
            }
        }Сейчас хочу в функцию его завернуть, чтобы можно было конкретный тайтл конкретного родителя с нужного уровня тащить, например.            
                Внесу свои 5 копеек в оптимизацию кода.
1. Самая первая переменная называется $parent, а проверяется $parent_id. Явная опечатка.
2. Блок с Alt key непонятно зачем нужен. Достаточно просто указать ключ context вместо ctx и context_key. Думаю, программисту это будет не сложно.
3. В коде
П.С. Ещё желательно, чтобы переменная height была необязательная. Она явно ограничивает применение фильтра.
                    1. Самая первая переменная называется $parent, а проверяется $parent_id. Явная опечатка.
2. Блок с Alt key непонятно зачем нужен. Достаточно просто указать ключ context вместо ctx и context_key. Думаю, программисту это будет не сложно.
3. В коде
if (!$parents = $modx->getParentIds($input, $height, $options)) {
    $parents = array();
}можно сразу возвращать null. Зачем тратить время на дальнейшие операции.П.С. Ещё желательно, чтобы переменная height была необязательная. Она явно ограничивает применение фильтра.
                1, 3 — полностью согласен!
2 — это для личного удобства. Постоянно путаю, где указать context_key, а где context.
                    2 — это для личного удобства. Постоянно путаю, где указать context_key, а где context.
                Скорректировал код, спасибо! Приятно, когда твой код кто-то читает. ;)
                    П.С. Ещё желательно, чтобы переменная height была необязательная. Она явно ограничивает применение фильтра.Тут не понял. Разве сейчас она обязательна?
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.