Судя по вашему комментарию у вас стоит Revo 2.1.5 А ничего, что уже 2.2.8 актуальная версия? Не пробовали откатываться еще на более раннюю версию, к примеру 2.0.8 (тогда еще даже поддержка многих Эво-функций была). Все современные пакеты работают с версии, начиная 2.2.0, для вашего движка просто нет доступных пакетов.

В тексте поставщик modxSite указан в домене com, а на картинке ru. У меня после добавления ни с одного из них перечня доступных пакетов не видно. По прежнему только modx.com. Еще бы не помешало указать разделы на modx.com в которых нужные пакеты лежат (хотя бы в скобках за названием пакета), а то поиск в менеджере пакетов толком не работает.

Правильно ли я понимаю что плагин phpThumbOfCacheManager, который устанавливается вместе с самим компонентом phpThumbOf, очищает полностью папку кэша phpThumbOf? Поэтому его лучше выключать? Да. Вот еще на этот компонент посмотри: modx.com/extras/package/phpthumbsup Райн говорит, что он гораздо быстрее работает, чем phpthumbof

Жесть, слил на 0 настройки, производительность моментально улучшилась. Правильно ли я понимаю что плагин phpThumbOfCacheManager, который устанавливается вместе с самим компонентом phpThumbOf, очищает полностью папку кэша phpThumbOf? Поэтому его лучше выключать?

Давным-давно, когда я еще тоже пользовался чанками и сниппетами, я, как и многие другие, тоже использовал конструкции типа [[[[+id]] ]] (часто используется в чанках, формирующих данные на списки документов) или [[[[*id]] ]]. При чем этот синтаксис пришел к нам еще со времен самых первых MODx. Если кто не знает, объясню, что здесь происходит: Это двойная конструкция. По плейсхолдеру [[+id]] или [[*id]] MODX-парсер получает id документа. Далее этот id уже замещает указанный плейсхолдер, и получается тег-ссылка, к примеру [[1]]. И вот уже эту ссылку MODX-парсер окончательно парсит, определяя указанный id документа и получает ссылку, выполняя $modx->makeUrl(id документа). Операция это довольно-таки затратная, а вызовов на странице может быть довольно много. Но ведь уже прошло очень много времени, и MODX серьезно развился, и давно уже все документы имеют атрибут uri (адрес страницы). Так вот, если у вас есть возможность (если в получаемых данных есть параметр uri), используйте его. Я давно уже его использую, и пока еще не было случая, чтобы возвращаемый адрес был не правильным. К примеру, вместо [[[[*id]] ]] вы можете использовать [[*uri]] (то есть ссылка на текущий документ. В текущем документе эта конструкция всегда будет работать). А [[[[+id]] ]] заменить на [[+uri]]. Это снизит нагрузку на парсинг этих тегов более чем в два раза (во-первых, на один тег меньше, а во-вторых не используется $modx->makeUrl()). В Smarty я же вообще все данные в списках документов получаю через list-процессоры из shopModx-а. Так вот там я в цикле когда набиваю данные документов, я давно уже не использую конструкции {link id=$object.id} (и уж тем более не использую [[{$object.object_id}]]). Я просто пишу {$object.uri} и все. И MODX-парсер отдыхает.

В этом топике опубликую все modxSmarty-теги с примерами, а так же парочку родных Smarty-тегов. Но все, что касается самого Smarty, смотрите в официальной документации Smarty. Snippet ===================== {snippet name=«SnippetName» params=«var=value&var2=value» parse=«true»} parse — not necessary. If set 'true', output will be parsed by MODX-parser. Default — false params — not necessary. Can use String or Array. Example 1 PHP: $modx->smarty->assign('params', array(«param1» => «value», «param2» => «value»,)) Template: {snippet name=«test» params=$params} Example 2 {snippet name=«test» assign=params}{snippet name=«test2» params=$params nocache} Chunk =================== {chunk name=«ChunkName» params=«var=value&var2=value» noparse=«true»} noparse — not necessary. If set 'true', output will not be parsed by MODX-parser. Default — false params — not necessary. Can use String or Array. System variable {config name=«configName»} Example {config name=«site_name»} return $modx->getOption('site_name') Placeholder =================== {px name=«configName»} Field {field name=«modResourceFieldName»} Link {link id=«modResourceID»} TV {tv name=«TvName» contentid=«modResourceID» parse=«true»} contentid — not necessary. If not specified, will be used current modResource. parse — not necessary. If set 'true', output will be parsed by MODX-parser. Default — false Parser =================== {parser content=«some content with MODX-tags»} Processor =================== {processor action=«web/menu/getcatalogmenu» location=path ns=«npghardwarestore» params=«foo=foo»} return $modx->runProcessor(); action — required. ns (namespace) — optionaly. If set, path for namespace_core_path/processors/ will be created automaticly location — optionaly. See MODx::runProcessor manual. params — optionaly. $scriptPproperties. Addition params =================================================== You can set this params for all this tags assign =================== {chunk name=chunk_name assign=param} Assign chunk result to var $param. nocache =================== {chunk name=chunk_name nocache} If Smarty caching enabled, this tag will be no-cached.

Вчера оптимизировал один сайт заказчика, и хочу рассказать о проблеме, с которой столкнулся. На сайте используется компонент Gallery, само собой картинки обрезаются phpThumb-ом. При этом картинки из кеша явно слишком долго отдавались (350ms 120 на 100 px), а статистика хостинга показывала неоправданно высокую нагрузку. Стал копать все это дело, и оказалось, что нагрузку создает сам phpThumb из-за чтения директории кеша, в которой лежит 16000 кеш-картинок… Детали. В классе phpthumb есть метод: Вот если config_cache_maxage или config_cache_maxsize или config_cache_maxfiles больше нуля, но он считает всю кеш-папку, чтобы посчитать пределы и убедиться, что они не превышены. Сами понимаете, что это дает с 16000 картинками в папке… Проблема в том, что в MODX эти конфиги никак нельзя задать, то есть phpThumb всегда выставляет дефолтовые настройки, отличные от нуля, и всегда читает папку кеша. Я Сплиттингреду написал тикет, но видимо пока я или кто-то не запостит исправления, это не будет исправлено. В процессоре Gallery processors/web/phpthumb.php я временно пофиксил так: Переписал на Нагрузка существенно упала.

Задача довольно тривиальная, а вот решение лично для меня на поверхности вообще не лежало… Задача: у нас документы в разных контекстах лежат (не спрашивайте зачем). Так вот, нам надо организовать подмену УРЛов (то есть у нас своя маска УРЛов, и мы при обращении к сайту разбирая УРЛ точно знаем ID документа, который надо вывести), и нам надо вывести этот документ. Вопрос на засыпку: с какими трудностями мы можем столкнуться? Ответ: ни с какими! В MODx есть функция — sendForward(); Но она очень замученная и далеко не для всего годится. В нашем же случае самый простой код выглядит вот так: Все. При чем пофиг на текущий контексты и т.п. Вешаете свой плагин на OnPageNotFound и рулите какие документы выводить. Никакого редиректа, просто вывод документа абсолютно в штатном режиме. UPD: на одном проекте делали хитрый роутинг под клиента, и выяснилось, что данный метод не укладывается в заложенный механизм MODX-кеширования, а именно: в момент выполнения modRequest::handleRequest MODX берет найденный документ из кеша, включая обработанный контент, ТВ-параметры и т.п., и только потом отправляет на обработку modRequest::prepareResponse(). А если мы напрямую его вызываем с полученным документом, то у нас нет его кеша и каждый раз страница отрабатывается с нуля. Чтобы все корректно работало, надо делать типа такого: Конечно же у вас могут быть свои отличные методы поиска айдишника запрошенного документа, но самое главное это сброс $_REQUEST['q'], установка id нужного документа $_REQUEST['id'] и повторная обработка запроса $modx->handleRequest(); Вот так будет все работать с кешем.

Интересный вопрос прозвучал на Хабре: «Может ли один спиппет быть продолжением другого по php коду?». Вообще это фишка интересная. К примеру вы хотите вызвать некий сниппет, к примеру [[mySnippet?param1=var1&ms2=var2]], а внутри этого снипета есть вызовы других сниппетов и/или чанков, в которые надо передать изначальные параметры. И вот полезная информация: Как и в любом элементе (чанк, сниппет и т.п.), внутри сниппета есть параметр $scriptProperties. Он как раз и содержит переданные параметры. Вы его можете передать как аргумент в последующий сниппет, к примеру внутри своего сниппета вызвать $modx->runSnippet($name, $scriptProperties); (и так сколько угодно вложенностей.). При этом по ходу можно переопределять и/или дополнять $scriptProperties. Много ясностей внесет кеш-функция тестового сниппета:

Такой странный тайтл, но кто предложит лучше, перепишу… Итак, это новые знания, полученные в процессе написания modSociety. Хочу рассказать про один интересный момент: как различные классы «уживаются» в одной таблице. Простой пример: у нас есть несколько классов: modDocument, modWebLink и т.п., то есть Документ, Ссылка и т.п. (всего 4 из коробки). При этом все эти 4 класса не просто флажочки типа «тип ресурса», а реально разные объекты. Их объединят только две вещи:

  1. Общая таблица modx_site_content
  2. Общий предок modResource Как же так получается, что все эти объекты мы получаем через метод $modx->getObject('modResource', $id);? И в ответ мы еще и получает реально разные объекты. Тут есть тонкость. В нашем случае каждая запись в таблице имеет class_key с указанием класса. Суть в том, что таблица одна, но xPDO хитро построен: если в таблице имеется колонка class_key, то при получении объекта, он инициализирует именно этот класс, и в этот объект набивает данные. То есть делаем запрос $d = $modx->getObject('modResource', 1); xPDO формирует запрос на основе класса, получает данные из БД, но прежде чем вернуть конечный объект с этими данными, он сначала проверяем ключ class_key в этих данных, и если есть такая колонка, то инициализирует именно указанный класс. То есть если там class_key=SocietyBlog, то в итоге он вернет объект SocietyBlog с данными из этой таблицы. Все это происходит в методе xPDOObject::loadInstance() public static function loadInstance(& $xpdo, $className, $criteria, $row) { $rowPrefix= ''; if (is_object($criteria) && $criteria instanceof xPDOQuery) { $alias = $criteria->getAlias(); $actualClass = $criteria->getClass(); } elseif (is_string($criteria) && !empty($criteria)) { $alias = $criteria; $actualClass = $className; } else { $alias = $className; $actualClass= $className; } if (isset ($row["{$alias}class_key"])) { $actualClass= $row["{$alias}class_key"]; $rowPrefix= $alias . ''; } elseif (isset($row["{$className}class_key"])) { $actualClass= $row["{$className}class_key"]; $rowPrefix= $className . ''; } elseif (isset ($row['class_key'])) { $actualClass= $row['class_key']; } $instance= $xpdo->newObject($actualClass); if (is_object($instance) && $instance instanceof xPDOObject) { $pk = $xpdo->getPK($actualClass); if ($pk) { if (is_array($pk)) $pk = reset($pk); if (isset($row["{$alias}{$pk}"])) { $rowPrefix= $alias . ''; } elseif ($actualClass !== $className && $actualClass !== $alias && isset($row["{$actualClass}{$pk}"])) { $rowPrefix= $actualClass . ''; } elseif ($className !== $alias && isset($row["{$className}{$pk}"])) { $rowPrefix= $className . ''; } } elseif (strpos(strtolower(key($row)), strtolower($alias . '')) === 0) { $rowPrefix= $alias . ''; } elseif (strpos(strtolower(key($row)), strtolower($className . '')) === 0) { $rowPrefix= $className . ''; } $parentClass = $className; $isSubPackage = strpos($className,'.'); if ($isSubPackage !== false) { $parentClass = substr($className,$isSubPackage+1); } if (!$instance instanceof $parentClass) { $xpdo->log(xPDO::LOG_LEVEL_ERROR, "Instantiated a derived class {$actualClass} that is not a subclass of the requested class {$className}"); } $instance->_lazy= $actualClass !== $className ? array_keys($xpdo->getFieldMeta($actualClass)) : array_keys($instance->_fieldMeta); $instance->fromArray($row, $rowPrefix, true, true); $instance->_dirty= array (); $instance->_new= false; } return $instance; } При этом ты можешь в запросе указывать любой класс, хоть $modx->getObject('SocietyBlog');, хоть $modx->getObject('modDocument');, он все равно вернет конечный объект тот, ключ которого указан. Колонка class_key есть и в таблицах modx_users и modx_media_sources. Но самое интересно то, что вы и в своих таблицах можете использовать эту колонку, чтобы хранить данные разных объектов, все будет работать нативно. Хотя нет, это еще не самое интересное… Вот такая идея возникла: посмотрите на запрос $q = $modx->newQuery('modResource'); $q->where(array( 'modResource.id' => '1' )); $q->select(array( 'modResource.*', "'SocietyBlog' as class_key", "'SocietyBlog' as modresourceclass_key" )); $obj = $modx->getObject('modResource', $q);

print_r($obj->toArray()); Как вы думаете, какой объект вернет функция $modx->getObject('modResource', $q);? Правильно — SocietyBlog. То есть получается, что на уровне селекта можно определить в какой объект в итоге все это выльется, при чем мало того, что мы можем переопределить значение колонки class_key, получается, мы этот фокус можем выполнить там, где этой колонки вообще нет. То есть на уровне простого запроса переопределить любой MODX-объект, который в принципе не предполагался расширяться. Правда надо еще более внимательно все это изучать, так как здесь идет проверка на наследственность объектов, но это потом. Основная мысль — можно использовать системные таблицы для хранения каких-то своих данных, и наоборот, данные из системных таблиц забивать в свои объекты. Я понимаю, что все это можно сделать и другими методами, но все-таки что-то в этом есть. Как минимум построение SQL-запросов, основываясь на связях MODX-объектов.