Тест вложенности ресурса в контейнер [с блекджеком и плюхами]
Проверить, есть ли контейнер в списке родителей ресурса, можно разными способами:
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 была необязательная. Она явно ограничивает применение фильтра.Тут не понял. Разве сейчас она обязательна?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.