Важно понимать, что это не самостоятельный пакет. Он использует имеющийся в MODX класс phpthumb. А тот в свою очередь уже был ранее замечен, как источник проблем с производительностью. Дело в том, что phpthumb перед созданием кеша файла, подсчитывает общий объем кеша, и это процедура совсем не слабая, если файлов довольно много. Чтобы этого избежать, идем в настройки MODX-а и устанавливаем значение 0 для следующих настроек: phpthumb_cache_maxage, phpthumb_cache_maxfiles и phpthumb_cache_maxsize. Тогда phpthumb не будет подсчитывать объем использованного кеша.
Проблема вторая. Низкая производительность.
Сейчас делаю каталог недвижимости, и там на одну страницу выводится 30 карточек. Так вот, на генерацию 30-ти превьюшек уходит 3-4 секунды. Конечно в дальнейшем эти превьюшки уже будут, и повторной генерации не будет, но от этого все равно не легче, так как на сайте более 4000 активных объектов, и будет очень много тормознутых страниц. Да и сниппету каждый раз проверять наличие файла превьюшки — тоже лишняя работа.
В общем, эту проблему я решил исправить радикально — просто заранее сгенерировать превьюшки и сохранить их для документа в отдельное TV-поле. Итак, все по порядку:
1. Создаем TV-шку для превьюхи. С этим все просто и понятно. Единственное — если на сайте будут работать менеджеры, то настройте права доступа на нее, чтобы они даже не видели это поле (это прям в редакторе TV-шки есть вкладка Права доступа).
2. Пишем плагин на сохранение документа. Замысел прост — при сохранении документа, плагин должен проверять значение TV-шки с необрезанной фоткой, и если получает, то выполняет сниппет phpThumbOf и записывает полученный путь до превьюшки в эту специальную TV-шку. Код плагина:
<?phpswitch($modx->event->name){case'OnDocFormSave':// На всякий случай меняем контекст, если MODX сам не поменял на контекст документа$origin_context=null;if($modx->context->key=='mgr'){$origin_context=$modx->context->key;$modx->switchContext('web');}// Создаем самбнейл превьюшки$TV_source=2;// Устанавливаете значения своих TV-шек$TV_target=17;$resource=&$scriptProperties['resource'];if($photo=$resource->getTVValue($TV_source)and$thumb=$modx->runSnippet('phpthumbof',array('input'=>$photo,'options'=>'w=113&h=113&q=100&zc=1',))and$photo!=$thumb){$resource->setTVValue($TV_target,$thumb);}// Если контекст меняли, то меняем его на изначальныйif($origin_context){$modx->switchContext($origin_context);}break;default:;}
Все. Теперь при сохранении документа сразу будет генериться и сохраняться превьюшка. Но что делать, если уже документы есть, и их много? Ведь надо каждый документ пересохранить… Но с этим тоже все довольно просто — не обязательно каждый документ открывать, можно документ пересохранить программно, через API. Лучше всего это делать через Console. Пишем и выполняем вот такой код:
<?phpini_set('max_execution_time',0);ignore_user_abort(1);$TV_source=1;// Устанавливаете значения своих TV-шек$TV_target=2;$q=$modx->newQuery('modResource');$q->leftJoin('modTemplateVarResource','tv',"tv.tmplvarid={$TV_source} AND tv.contentid=modResource.id");$q->leftJoin('modTemplateVarResource','tv2',"tv2.tmplvarid={$TV_target} AND tv2.contentid=modResource.id");$q->where(array('tv.id:!='=>null,'tv.value:!='=>'','tv2.id'=>null,'published'=>1,));print"Total: ".$modx->getCount('modResource',$q);// Общее число оставшихся документов// return;$q->limit(10);if($docs=$modx->getCollection('modResource',$q)){foreach($docsas$doc){$modx->error->reset();$modx->runProcessor('resource/update',$doc->toArray());}}
Здесь мы получаем документы с картинками, у которых есть картинки, но нет еще превьюшек, и обновляем их через процессор. А в процессоре уже вызывается событие OnDocFormSave и само собой и наш процессор, срабатывающий на это событие.
Вот теперь, после того, как у нас уже есть все превьюшки в специальном TV, нам не надо уже в коде страницы вызывать сниппет phpThumbOf, мы просто вставляем значение этой TV-шки. Нагрузка падает, мы радуемся :-)
UPD: Чуть-чуть дописал плагин. Добавил смену контекста, если текущий контекст — mgr. Дело в том, что для разных контекстов могут быть указаны различные источники файлов, а для mgr этот параметр в TV почему-то не задается, и если источник файлов TV-параметра не базовый (корневой), а контекст mgr, то TV-шка просто вернет неверный результат.
UPD: Добавил еще проверку AND $photo != $thumb. Причина — pThumb, если не смог получить картинку или еще что (ошибка в общем) возвращает оригинальное изображение. Если мы запишем оригинальный путь, то у нас и TV-поле будет заполнено (и мы не будем знать, что для этого ресурса не была создана превьюшка), и значение будет не правильным. Будет потом много гемора.
радикально. у меня тут пара сотен страниц с вызовом phpThumbOf завалялась, а на каждой по 16-30 мегабайтных картинок уже есть и переделывать их реально в ломы, проще сервер купить (что и сделано было)=)
А на самом деле клева получается. Во-первых, исключается человеческий фактор (не надо учить менеджеров что делать. Один раз прогнал все документы, а потом при любом сохранении документа обновляется превьюха). Во-вторых, идет как чистая статика, сервер вообще не грузится.
Жесть, слил на 0 настройки, производительность моментально улучшилась.
Правильно ли я понимаю что плагин phpThumbOfCacheManager, который устанавливается вместе с самим компонентом phpThumbOf, очищает полностью папку кэша phpThumbOf? Поэтому его лучше выключать?
Правильно ли я понимаю что плагин phpThumbOfCacheManager, который устанавливается вместе с самим компонентом phpThumbOf, очищает полностью папку кэша phpThumbOf? Поэтому его лучше выключать?
кто уже попробовал phpthumbsup?
а то я довёл уже до максимума (с помощью Философа) скорость работы phpthumbof, так что у меня он как статика уже работает.
кто-то что-то скажет о phpthumbsup?
Пристал. Я не буду писать обзоры. Я лично могу поделиться, но не более.
Вот например: по первым моим тестам обнаружен недостаток в UP и в ON версиях (по крайней мере на этом этапе). Ни одна из них не может брать картинку с внешнего источника. OF может, то попутно обнаружена задержка в нём (проверка наличия кеша), которая составляет 1.5-3ms на одну картинку. Это тоже нехорошо.
Теперь пример, как это развивалось бы, буть это топик: вылезет какой-то умный троль и скажет, что я криворукий, и методом переделки 20 строк кода в плагине и перелопачивании 20 строк ядра всё будет работать, и что я вообще ничего не увидел, поэтому мой обзор — хламищ, мне двойка и я уволен.
Исключительно и только поэтому я никогда ничего не напишу вообще, даже если все будут аплодировать и в руках у меня будет сокровище.
Вообщем, парился я парился и надоело
ON вечно кладёт файл-пустышку в стиле /assets/cache_image/noimage_100x100_31b.jpg, мол
оригинал не найден, хотя оригинал есть и доступен.
UP, напротив, заработал полностью, хотя выхов картинки у него совершенно другой, полностью отличается от OF.
Например так: /cache/w/100/h/100/src/http://modxclub.ru/uploads/images/00/01/66/2013/07/13/avatar_48x48.jpg
это я вытащил свой аватар с твоего сайта, чтобы для примера не было моего сайта в ссылке. но смысл и расшифровка, думаю, понятны. И гибкость, на мой взгляд, приобретается просто невероятная.
// На всякий случай меняем контекст, если MODX сам не поменял на контекст документа
$origin_context = null;
if($modx->context->key == 'mgr'){
$origin_context = $modx->context->key;
$modx->switchContext('web');
}
то причина следующая: дело в том, что TV-параметры привязываются к источникам файлов (индивидуально для каждого контекста). Но нельзя указать связку TV-поля с конкретным источником файлов в контексте mgr. Если вы не используете отдельного источника файлов. используя по умолчанию filesystem (который от корня сайта работает), то вам бояться нечего. А если у вас в web-контексте другой источник (я часто в основном использую Images (/assets/images/)), то без смены контекста будет использован тот же filesystem и пути побьются, файлы просто не будут найдены.
И что делать на мультиязычных сайтах?
Мультиязычных или мультидоменных? Мультиязычность здесь никакой роли не играет, а если мультидоменный (мультиконтекстный), то используйте во всех контекстах один и тот же источник файлов, что и в web, и никаких проблем не будет.
P.S. на самом деле эта смена контекстов больше имеет значение при выполнении кода в консоли, когда по умолчанию используется текущий контекст mgr, но при редактировании документа через родной редактор страниц, проблем не должно никаких встать.
P.P.S -лучше использовать pThumb вместо phpthumbof, так как первый, в случае если картинка не найдена, использует указанный УРЛ картинки без изменения (то есть просто УРЛ будет на оригинал), в то время как второй или ничего не отдает, или записывается ошибка в TV.
Про источники файлов почитаю, спасибо.
Вы может быть не пользуетесь стандартными пакетами, но в наиболее распространённых инструкциях к Babel требуется создание отдельного контекста для языка. По-моему он иначе не работает.
И ещё, я может глупость спрошу, но все-таки: у вас в условии if с бухты-барахты появляется переменная $photo. Я как-то привык сперва объявлять переменную, класть в неё что-то, а потом уже в условии проверять.
ЗЫ вообще я phpThumbOn установил. но что-то он не больно по скорости обгоняет phpThumbof по моим наблюдениям.
Вы может быть не пользуетесь стандартными пакетами, но в наиболее распространённых инструкциях к Babel требуется создание отдельного контекста для языка.
Я мало использую стандартные пакеты, но во-первых, я знаю хорошо сам MODX (а значит и любой пакет для меня — не проблема), а во-вторых, в свое время не мало пакетов использовал.
Вы в данном случае путаете разные вещи. То, что бабел заставляет делать новые контексты, это еще не говорит, что мультиязычность на что-то влияет. Повторюсь: сама мультиязычность ни на что не влияет. А вот по какой причине созданы контексты — это вообще не важно (бабел вас заставил, или сами захотели), здесь есть факт — другие контексты. И вот про эти контексты и их влияние я написал выше — здесь влияние только связка TV-контекст-Источник файлов. Всего написанного выше достаточно.
у вас в условии if с бухты-барахты появляется переменная $photo. Я как-то привык сперва объявлять переменную
У меня написано:
if($photo = $resource->getTVValue($TV_source)
В данном случае не только происходит присвоение, но и ленивое объявление (сам php ее автоматом заводит). Ни логической, ни технической ошибки здесь никакой нет. А ваше желание объявлять переменные в шапке — это ваше право. Я тоже бывает переменные объявляю, но только тогда, когда они в коде расположены далеко друг от друга. Здесь переменная используется в двух строчках кода, близко расположенных друг к другу. Какой смысл их где-то объявлять?
ЗЫ вообще я phpThumbOn установил. но что-то он не больно по скорости обгоняет phpThumbof по моим наблюдениям.
Я не говорил ставить phpThumbOn. Я говорил про pThumb.
Обнаружил такую штуку, что на выходе от сниппета phpthumbof, выходят изображения немного бледные нежели оригинал, в чем может быть проблема? Помогите очень серьезный баг на мог взгляд. Причем если даже размер ставить в настройках один в один с оригиналом, все равно обрабатывает и делает изображение превьюшки более бледной по цвету. Кто сталкивался?
Автору респект!!! В голову не приходило что так можно сделать, нарадоваться не могу.
Но вот не люблю создавать лишний раз тв, пришла идея записывать превью в неиспользуемое поле, например introtext или link_attributes. Сниппету каталога не придется обращаться к тв за картинкой, тем самым еще больше ускорим загрузку.
В php я не силен, сделал как смог, поправьте говнокод, буду очень признателен)
Но вот использовать зарезервированные поля под хранение данных, не для которых они были созданы — это не правильно. Хотите в ресурс сохранять, изучайте эту статью: habrahabr.ru/post/253737/
Благодаря вам получилась работающая штуковина приведенная внизу, почему-то заработала только с phpThumbOn.
У меня вопрос, можно ли теперь это как-то применить к полю Migx, пытался адаптировать различные решения найденные на различных форумах, но не выходит.
PS про php я знаю только, что он есть.
<?phpif($modx->event->name=="OnDocFormSave")// Плагин срабатывает при сохранении ресурса{$tv='image_1';// ТВ загружаемой картинки$tv2='image_1_preview';// ТВ создаваемого превью$options='w=100&h=100&zc=1';$tvv=$resource->getTVValue($tv);// Получаем адрес загруженной картинкиif(!empty($tvv))// Если ТВ загружаемой картинки не пустое{$thumbnail=$modx->runSnippet('phpThumbOn',array('input'=>$tvv,'options'=>'w=113&h=113&q=70&zc=1',// Параметры сохраняемой превью));if(!empty($thumbnail)){$resource->setTVValue($tv2,$thumbnail);// Если phpThumbOn срабтал, то записываем адрес превью в ТВ}}}
Я не очень понял вопрос по MIGX, то есть по сути его вообще не увидел. В чем именно проблема? Предположу, что на сервер MIGX-данные прилетают в JSON и вопрос в том, как выдернуть данные картинок из этой JSON-строки и провернуть операцию.
Но в любом случае, я бы рекомендовал не усложнять это. Лучше все пусть работает в штатном режиме. В производительности выигрыш небольшой, а вот подводных камней многократно прибавится. Потом не будете знать откуда ноги растут.