воскресенье, 28 июля 2013 г.

Modx – phpthumbof создает слишком много копий одного изображения

Используя phpThumbOf для пережатия изображений в MODx, можно столкнуться с такой проблемой, что сайт стал медленно работать, приходится долго ждать начала загрузки страницы. Чтобы разобраться с этой проблемой, надо понять, как работает кэширование в плагине, каким образом происходит именование файлов.

На момент написания статьи версия плагина phpThumbOf, доступная для установки в MODx Revo, phpthumbof-1.4.0-pl.

    Существует два варианта именования пережимаемых изображений (устанавливаются через параметр phpthumbof.hash_thumbnail_names (Hash Thumbnail Names) в Настройках системы):
  1. если параметр равен true: md5 из полного имени файла, включая путь, и параметров для сжатия (ширина, высота и пр.), к примеру, 9388805c65e0d85ce90ac26cd67b186e.c82348b2ac2f4fdfc6b913a99e31a6fd.jpg
  2. если параметр равен false (значение по умолчанию): имя файла + md5 из опций для сжатия (ширина, высота и пр.) и id ресурса $this->modx->resource->get('id'), к примеру, 3189_photo.c82348b2ac2f4fdfc6b913a99e31a6fd1.jpg
if ($this->modx->context->getOption('phpthumbof.hash_thumbnail_names',false,$this->config)) {
 $inputSanitized = str_replace(array(':','/'),'_',$this->input);
 $this->cacheFilename = md5($inputSanitized);
 $this->cacheFilename .= '.'.md5(serialize($this->options));
 $this->cacheFilename .= '.' . (!empty($this->options['f']) ? $this->options['f'] : 'png');
} else { /* or attempt to preserve the filename */
 $inputSanitized = str_replace(array('http://','https://','ftp://','sftp://'),'',$this->input);
 $inputSanitized = str_replace(array(':'),'_',$inputSanitized);
 $this->cacheFilename = basename($inputSanitized);
 if ($this->modx->context->getOption('phpthumbof.postfix_property_hash',true,$this->config)) {
  if (!empty($this->options['f'])) { /* get rid of the middle extension and put it at the end */
   $length = strlen($this->cacheFilename);
   $extLength = strlen($this->options['f']);
   $cut = $length-$extLength-1;
   if (strlen($this->cacheFilename) > $cut) {
    $this->cacheFilename = substr($this->cacheFilename,0,$cut);
   }
  }
  $this->cacheFilename .= '.'.md5(serialize($this->options)).$this->modx->resource->get('id');
  $this->cacheFilename .= '.' . (!empty($this->options['f']) ? $this->options['f'] : 'png');
 }
}

По умолчанию параметр Hash Thumbnail Names отключен, т.е. срабатывает второй сценарий. В этом случае может возникнуть проблема, когда создается слишком много копий одного и того же изображения с одинаковыми опциями для сжатия у phpThumbOf. К примеру: есть каталог товаров, и на странице каждого товара есть список всех товаров с превью. Из-за добавления к имени файла id ресурса превьюшки товаров всего каталога будут создаваться столько раз, сколько товаров (т.е. страниц-ресурсов, на которых они должны отобразиться). Чтобы этого избежать, приходится устанавливать в настройках значение параметра Hash Thumbnail Names в "Нет". Но тогда имена файлов становятся совершенно не СЕО-френдли.

Запросов на правку плагина phpThumbOf MODx за год набежало довольно много, но новой версии всё нет и нет. Поэтому раз уж не нравится ни одни из сценариев генерации имени файла, остается сделать правку и сделать так, как удобно для проекта.

В моем случае существует, как минимум 4 варианта размера одного и того же изображения (уф, богат дизайн оказался на формы..). Можно было конечно генерировать все эти варианты превью при загрузке на сайт исходного изображения, но я предпочла создавать все нужные (сейчас и возможно в будущем) размеры при помощи phpThumbOf при обращении к странице, на которой они используются. На каждой странице товара у меня есть список всех товаров с превью, поэтому второй сценарий мне не подходит. Первый мне не нравится из-за полностью нечитабельного имени. Поэтому я делаю комбинацию двух методов.

    Для создания имен вида:
  1. 3189_photo.9388805c65e0d85ce90ac26cd67b186e.c82348b2ac2f4fdfc6b913a99e31a6fd.jpg с именем файла 3189_photo.jpg
  2. yellow.e76118f558936bb6c1d57413783584e4.ef294f795d171be1bbf5494b60fa7502.jpeg с именем файла yellow
  3. где первая часть - имя файла без расширения, вторая - хэш пути (начиная с assets/), третья - хэш параметров сжатия.

Заменяю 290 строку файла core/components/phpthumbof/model/phpthumbof/phpthumbof.class.php на (для вырезания имени файла без расширения можно было скопировать код из второго метода именования, или вообще изменять второй способ именования удалением конкатенации id ресурса, я изменяла первый ):

$name = (strrpos($this->input, $this->options['f']) == strlen($this->input)-strlen($this->options['f'])) ? substr(basename($this->input), 0, -strlen($this->options['f'])) : basename($this->input).'.';
$this->cacheFilename = $name.md5($inputSanitized);

Комментариев нет:

Отправить комментарий