MODX сниппеты (snippet)

MODX сниппеты (snippet) MODX Revo

В предыдущей статье мы разбили шаблон на чанки (мы к ним еще вернемся по мере разработки). Теперь разберемся, что такое сниппеты и создадим первый сниппет «year», который будет автоматически выводить текущий год. Год нам пригодится, например, в подвале, где указан Copyright. Чтобы каждый год его не менять вручную, MODX будет подставлять год автоматически.

Что такое

MODX сниппет — это контейнер (как чанк), но содержащий в себе не HTML, а PHP код, и их можно подключать в любые места: страниц, шаблоны, ресурсы, чанки.

Как создать

Что бы создать сниппет в MODX в дереве документов на вкладке «Элементы» нажмите на копку «Новый сниппет». Затем на открывшейся странице укажите имя (year), описание, категорию и вставьте код.

Код сниппета «year» следующий (см. синтаксис языка PHP):

<?php 
echo date('Y');

Создание сниппета year

 

“?>” прописывать не нужно. Если пропишите, то парсер MODX всё равно её проигнорирует. В принципе, и объявление PHP скрипта в виде “<?php” можно не прописывать, код будет исполняться корректно и без этого. Но для наглядности я привык прописывать это указание на то, что перед нами скрипт на языке PHP.

Если вы используете парсер fenom и у вас включена настройка pdotools_fenom_php, то вы можете вывести текущий год так.

{'' | date : 'Y'}

Получается так мы избавились от сниппета, как и до этого от чанков)

Вызов сниппета

Вывод сниппетов аналогичен чанкам, для вызова не кэшируемого сниппета используем [[name_snippet]]:

&copy; Copyright 2022 - [[year]] [[++site_name]]. Все права защищены.

В код выведется: Copyright 2022 — 2023 Название сайта. Все права защищены.

Где название сайта берется из системных настроек: site_name (скоро до них дойдем).

Если нужен не кэшируемый вывод, то вызывается всегда по аналогии — с восклицательным знаком вначале [[!name_snippet]].

Вышеприведенный код на fenom.

&copy; Copyright 2022 - {'year' | snippet} {$_modx->config.site_name}. Все права защищены.
или 
&copy; Copyright 2022 - {'' | date : 'Y'} {$_modx->config.site_name}. Все права защищены.

В общем открываете чанк в котором хранятся сквозные блоки, или шаблон base и в подвале в блоке copyright прописываем одну из конструкций указанных выше.

Выводим копирайтинг

Параметры

Сниппеты могут иметь параметры — php-переменные, которые можно инициализировать во время вызова.
Например усложним код нашего сниппета, до

<?php
$year = date("Y");
if($year == $start) {
	return $year;
} else {
return ''.$start.' – '.$year.'';
}

Здесь мы добавили параметр start, следовательно, можем указать:

Copyright [[year? &start=`2022`]] [[++site_name]]. Все права защищены.

В код выведется то же самое, что и в предыдущем случае.

Указываются параметры в вызове сниппета после знака вопроса (?).

В случае с феном вызов будет следующим.

{'year' | snippet : [
    'start' => '2022'
]}

Если вы не особо знаете PHP (или вообще не знаете) — не переживайте, его знание для создания среднестатистического сайта не требуется. Тем более есть куча готовых решений, часть из них ниже. На худой конец если вообще не шарите в php и не нашли готового сниппета, то код снипетов (по крайней мере простеньких), может сгенерить chat gpt.

Подборка полезных мини сниппетов для разработчиков

Красивый вывод цифр (цен) с пробелами, используя php number_format

Вариант 1. (numformat)

<?php
if(strlen($input)==0) return '';
$input = floatval(str_replace(array(' ',','), array('','.'), $input));
return number_format($input,(floor($input) == $input ? 0 : 2),'.',' ');

Использование:

[[*price:numformat]]

Было: 33354567
Стало: 33 354 567

Вариант 2. (nPrice)

<?php 
if ($price == "")
$price_output =  $modx->resource->getTVValue('Price');
else
$price_output = $price; 
return number_format($price_output, 0, '', ' ' );

Использование:

В месте, где у Вас выводится цифровое поле (цена), вставляем (пусть будет TV с именем price):

[[nPrice?price=`[[*price]]`]]

Ну или если у вас магазин на minishop2 то, вместо вывода [[+prise]] пишем:

[[nPrice?price=`[[+price]]`]]

Удаляем последний символ в строке

last

<?php
return mb_substr($input, 0, -1);

Примечание: Полезно при формировании каких-либо последовательностей (например, ID ресурсов через запятую), у которой последний символ вызывает ошибку.

Использование:

[[*resources:last]]

Было: 33,35,45,67,
Стало: 33,35,45,67

Формирование корректной ссылки с атрибутом tel при выводе телефона на сайте

phone

<?php
$p1 = array(" ", "-", "(", ")");
$p2 = array("", "", "", "");
return str_replace($p1, $p2, $input);

Примечание: Удаляются скобки, дефисы и т. д.

Использование:

<a href="tel:[[++phone:phone]]">[[++phone]]</a>

на fenom можно без создания сниппета вывести, так.

<a href="tel:{$_modx->config.phone  | preg_replace : '/[^0-9+]/' : ''}"> {$_modx->config.phone}</a>

Было: 8 (927) 778-45-45
Стало: 89277784545

Склоняем числовые определения

plural

<?php
if($n!=''){
$plural = $n%10==1&&$n%100!=11?$w1:($n%10>=2&&$n%10<=4&&($n%100<10||$n%100>=20)?$w2:$w3);
return $plural;
}

Примечание: Данное решение позволяет склонять числовые определения. То есть, не «1 штук», а «1 штука», «3 штуки» и т. д. 

Использование:

[[plural? &n=`число` &w1=`штука` &w2=`штуки` &w3=`штуки`]]

Убирает лишние символы в строке

title

<?php
$str = preg_replace ("#([^=])\"([^\"]+)\"#", "\\1«\\2»", $input);
return str_replace('&', '', $str);

Данный снииппет полезен тем, что зачастую заказчики в pagetitle вводят название ресурса типа О компании «Рога и копыта» и в код выводятся двойные кавычки, если такие кавычки вывести в meta или в img, например так:

<img src="[[*image]]" alt="[[*pagetitle]]"/>

выведется:

<img src="путь к изображению" alt="О компании "Рога и копыта""/>

Получаются двойные кавычки, что приводит к ошибкам.

Данный модификатор заменяет кавычки на «» и дополнительно убивает символ &.

Использование:

<img src="[[*image]]" alt="[[*pagetitle:title]]" />

Запись в сессию и вывода значения какой-либо переменной

getGet

<?php
$get = htmlentities(trim(strip_tags((string) $_GET[$var])), ENT_QUOTES, 'UTF-8', false);
session_start();
if ($get == '' ) {
return $_SESSION[$var];
} 
else {
$_SESSION[$var] = $get;
return $_SESSION[$var];
}

Для чего он: Например нужно передать на страницу формы заказа название товара, на котором нажата ссылка «Купить».

Примечание: Можно в первой строке вместо $GET[$var] прописать $_REQUEST[$var] — тогда будет работать и с GET и с POST.

Использование:
Ссылка:

<a href="[[~id? &item=`[[*pagetitle]]`]]">Заказать</a>

В форме:

<input type="hidden" name="item" value="[[!getGet? &var=`item`]]" />

Поскольку всё пишется в сессию, значение подставляется и при перезагрузке страницы после, к примеру, не прошедшей валидацию, формы.

Время чтения

простенький сниппет, который оценивает время, которое читатель будет читать контент.

readtime

<?php
$options = (int) $modx->getOption('options', $scriptProperties, 220, true); // 220 слов в минуту
$wordCount = (int) str_word_count(strip_tags($input)); // Чтобы отобразить количество слов, установите для параметров значение 0
if ($options === 0) return $wordCount;
return ceil($wordCount / abs($options));

Использование:

<p>Время чтения [[*content:readtime]] мин.</p>

Если ваш сайт с jQuery то можете воспользоваться продвинутым, настраиваемым миниатюрным скриптом выводящим время чтения.

Данный сниппет нужно вызвать в секции head.

<?php
$res = $modx->resource;
$site_url = $modx->getOption('site_url');
$site_start = $modx->getOption('site_start') ?: 1;
$ids = $modx->getParentIds($res->id, 10, array('context' => $modx->context->key));
$pids = ($res->id != $site_start) ? [$res->id] : [];
foreach($ids as $id) {
    if($res->id != $id) {
        $pids[] = $id;    
    }
}
$pids = array_reverse($pids);
$output = [];
$index = 0;
foreach($pids as $id) {
    if ($id == 0) {
        $id = $site_start;
    }
    if($res->id != $id) {
        $res = $modx->getObject('modResource', $id);
    }
    
    $uri = $site_url . $res->get('uri');
    if($res->get('id') == $site_start) {
        $uri = $site_url;
    }
    $output[] = '{
        "@type": "ListItem",
        "position": '.++$index.',
        "name": "'.$res->get('pagetitle').'",
        "item": "'.$uri.'"
    }';
}
$wrapper = implode(',', $output);
return '<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": ['.$wrapper.']
}
</script>';

alternate hreflang

Для мультиязычных сайтов (выводить в секции head), подробнее зачем и почему можно почитать здесь: https://netpeak.net/ru/blog/tegi-alternate-hreflang-media-type-zachem-i-kak-ikh-ispol-zovat/

<?php
$ctxDefault = $modx->getOption('x-default', $scriptProperties, 'web', true);
$tplDefault = '<link rel="alternate" href="{$page}" hreflang="x-default"/>';
$tpl = '<link rel="alternate" href="{$page}" hreflang="{$lang}"/>';
$output = '';
$contexts = $modx->getCollection('modContext', array('key:!=' => 'mgr'));
if(!count($contexts)) return;
foreach($contexts as $context) {
    $ctx = $modx->getContext($context->key);
    $site_url = $ctx->getOption('site_url');
    $site_start = $ctx->getOption('site_start');
    if($modx->resource->uri != 'index') {
        $site_url .= $modx->resource->uri; 
    }
    $cultureKey = $ctx->getOption('cultureKey');
    if($context->key == $ctxDefault) {
        $parseTpl = str_replace('{$page}', $site_url, $tplDefault);
        $output .= $parseTpl;
    }
    $parseTpl = str_replace('{$page}', $site_url, $tpl);
    $parseTpl = str_replace('{$lang}', $cultureKey, $parseTpl);
    $output .= $parseTpl;
}
return $output;

FileSize — вывод размера файла и расширения файла

Использование:

  • [[!FileSize? &input=`assets/files/myfile.pdf`]] — Будет автоматически выбрана единица измерения.
  • [[*file_catalog:FileSize]] — Вывод размера файла из TV-параметра.
  • [[!FileSize? &input=`assets/files/myfile.pdf` &unit=`b`]] — Явно указываем единицу измерения.
  • [[!FileSize? &input=`assets/files/myfile.pdf` &get_ext=`1`]] — Получить расширение файла, а не размер.
  • [[*file_catalog:FileSize?&get_ext=`1`]] — расширение файла из TV-параметра.
  • {'!FileSize' | snippet : ['input' => 'assets/files/myfile.pdf']} — Fenom.
<?php
if(!empty($get_ext)){
  //Получить расширение файла в нижнем регистре
  $ext = mb_strtolower(pathinfo($input, PATHINFO_EXTENSION));
  return $ext;
}else{
  //Получить размер файла
  $units = array(
    'gb' => array('size' => 1073741824, 'label' => 'ГБ'),
    'mb' => array('size' => 1048576,    'label' => 'МБ'),
    'kb' => array('size' => 1024,       'label' => 'КБ'),
    'b'  => array('size' => 0,          'label' => 'байт')
  );
  $input = MODX_BASE_PATH . $input;
  $size = is_file($input) ? filesize($input) : 0;
  $unit = (isset($unit) && isset($units[$unit])) ? $unit : false;
  
  if ($size > 0) {
    if ($unit === false) {
      foreach ($units as $key => $properties) {
        if ($size >= $properties['size']) {
          $unit = $key;
          break;
        }
      }
    }
    if ($unit != 'b'){
      $size = $size / $units[$unit]['size'];
    }
  }
  else {
    if ($unit === false) $unit = 'b';
  }
  return round($size, 2) . ' ' . $units[$unit]['label'];
}

FaviconGenerator — aвтоматическая генерация favicon

Размеры генерит дополнение phpthumbof, если оно не установлено, то нужно установить с основного репозитория, также можно использовать pthumb или phpthumbon.

Допустим, название FaviconGenerator, код:

<?php
if (version_compare(PHP_VERSION, '5.4.0') < 0) {
    return '<!-- Your version of PHP is very ancient -->';
}
$output = '';
// Цвет фона. Если не указан, то не применяется.
$backgroundColor = (string)$modx->getOption('backgroundColor', $scriptProperties, '');
// Путь до изображения
$image = (string)$modx->getOption('image', $scriptProperties, '');
// Нужно ли генерировать favicon.ico
$ico = (int)$modx->getOption('ico', $scriptProperties, 0);
// Сниппет, создающий миниатюры (phpthumbof, pthumb, phpthumbon)
$snippet = (string)$modx->getOption('snippet', $scriptProperties, 'phpthumbof');
// Цвет вкладки для мобильных браузеров
$tabColor = (string)$modx->getOption('tabColor', $scriptProperties, '');

// Apple
$sizes = ['57x57', '72x72', '144x144', '60x60', '120x120', '76x76', '152x152'];
foreach ($sizes as $size) {
	$as = explode('x', $size);
	$options = 'w='.$as[0].'&h='.$as[1].'&zc=1&f=png&bg='.$backgroundColor;
	$output .= '<link rel="apple-touch-icon-precomposed" sizes="'.$size.'" href="'.$modx->runSnippet($snippet, ['input' => $image, 'options' => $options]).'" />'.PHP_EOL;
}

// Classic
$sizes = ['32x32', '16x16', '96x96', '128x128', '196x196'];
foreach ($sizes as $size) {
	$as = explode('x', $size);
	$options = 'w='.$as[0].'&h='.$as[1].'&zc=1&f=png';
	if (!empty($backgroundColor)) {
		$options .= '&bg='.$backgroundColor;
	}
	$output .= '<link rel="icon" type="image/png" sizes="'.$size.'" href="'.$modx->runSnippet($snippet, ['input' => $image, 'options' => $options]).'" />'.PHP_EOL;
}

// Microsoft
$output .= '<meta name="msapplication-TileColor" content="#FFFFFF" />'.PHP_EOL;
$output .= '<meta name="msapplication-TileImage" content="'.$modx->runSnippet($snippet, ['input' => $image, 'options'=>'w=144&h=144&zc=1&f=png&bg='.$backgroundColor]).'" />'.PHP_EOL;
$sizes = ['70x70', '150x150', '310x310'];
foreach ($sizes as $size) {
	$as = explode('x',$size);
	$options = 'w='.$as[0].'&h='.$as[1].'&zc=1&f=png';
	if (!empty($backgroundColor)) {
		$options .= '&bg='.$backgroundColor;
	}
	$output.='<meta name="msapplication-square'.$size.'logo" content="'.$modx->runSnippet($snippet, ['input' => $image, 'options' => $options]).'" />'.PHP_EOL;
}

// favicon.ico
if ($ico == 1) {
	$options = 'w=16&h=16&zc=1&f=ico';
	if (!empty($backgroundColor)) {
		$options .= '&bg='.$backgroundColor;
	}
	$output .= '<link rel="shortcut icon" href="'.$modx->runSnippet($snippet, ['input' => $image, 'options' => $options]).'" type="image/x-icon" />'.PHP_EOL;
	$output .= '<link rel="icon" href="'.$modx->runSnippet($snippet, ['input' => $image, 'options'=>$options]).'" type="image/x-icon" />'.PHP_EOL;
}

if (!empty($tabColor)) {
	$output .= '<meta name="theme-color" content="#'.$tabColor.'" />'.PHP_EOL;
	$output .= '<meta name="msapplication-navbutton-color" content="#'.$tabColor.'" />'.PHP_EOL;
	$output .= '<meta name="apple-mobile-web-app-status-bar-style" content="#'.$tabColor.'" />'.PHP_EOL;
}

return $output;

Пример использования

[[FaviconGenerator? 
    &image=`favicon.png`
    &backgroundColor=`f00`
    &tabColor=`f00`
    &ico=`1`
    &snippet=`phpthumbof`
 ]]

Параметры

Параметр Значение по умолчанию Пример значения
image assets/images/favicon.png
backgroundColor bada55
tabColor bada55
ico 0 1
snippet phpthumbof pthumb

Большинство сниппетов взято на просторах интернета.

В следующем уроке разберем поля ресурсов MODX и как их выводить.

Поделиться с друзьями
Алексей

Веб-дизайнер и SEO оптимизатор. Занимаюсь созданием сайтов с 2010 года и их продвижение с 2012 года!

Оцените автора
( 5 оценок, среднее 4.2 из 5 )
Web-Revenue.ru
Добавить комментарий

  1. Seva

    Продолжение будет?

    Ответить
    1. Алексей автор

      Будет как время появится, сейчас немного не до ведения блога

      Ответить
  2. Сергей

    А есть в modx возможность вставки карты от яндекс например как в wordpress, плагином?

    Ответить
    1. Алексей автор

      А зачем вам плагин, создайте чанк поместите в него код карты и вызовите в любом месте сайта

      Ответить