• Блог
  • Фильтрация, контейнер, планшет...

Новость для разработчиков. В библиотеку добавлено несколько новых функций:

  • is_tablet()
  • is_desktop()
  • app()
  • filter_data()
  • null_if()

И ещё немного доработана функция pls() для работы с плейсхолдерами, logout() и parse().

С первыми двумя функциями, думаю, всё понятно. Это функции-детекторы текущего устройства. Раньше можно было только проверить является ли устройство мобильным или нет, используя функцию is_mobile(). Теперь проверка полноценнее. Особенно это хорошо впишется при использовании шаблонизатора.

{if $.php.is_tablet()}
    // Планшет
{elseif $.php.is_mobile()}
    // Телефон
{else}
    // Десктоп
{/if}

Функция is_mobile() определяет и телефоны и планшеты как мобильные. Поэтому сначала нужно проверять планшеты.

Детектор устройства использует библиотеку MobileDetect. Поэтому можно использовать все её возможности. А у неё очень много полезных методов. Эта библиотека подключается как сервис через функцию app() (о ней ниже). Поэтому обратиться к ней можно в любом месте так

$detector = app('detector');

// И дальше уже вызывать методы
$detector->version('Firefox');
if ($detector->isiOS()) {}
if ($detector->is('Chrome')) {}

Теперь о функции app(). Она возвращает объект контейнера, который используется для разрешения зависимостей. В контейнере можно хранить объект, который будет один и тот же на протяжении загрузки приложения. Это так называемый синглтон (singleton). Например, в начале загрузки определяется репозиторий (репозиторий пользователей, ресурсов и т.п.), а затем в любом месте приложения к нему можно обращаться. Синглтоны часто используются как сервисы.

Основные методы:

  • bind() — регистрация зависимости.
  • singleton() — регистрация синглтона через имя класса или замыкание.
  • instance() — регистрация уже существующего объекта в качестве синглтона.
  • bound() — проверяет, определена ли указанная зависимость.
  • resolved() — проверяет, создан ли объект указанной зависимости.

Работает это так:

// В плагине при инициализации MODX определяем зависимость
app()->singleton('userRepo', function() use ($modx) {
	return users()->where(['active'=>true])->toArray();
});

И теперь в любом месте приложения можно вызвать:

$users = app('userRepo');

И получаем всегда один и тот же репозиторий. И никаких повторных запросов к базе.

Проверяем, определена ли уже зависимость:

if (!app()->bound('alias')) {
    app()->bind('alias', function(){...});
}

Удобно когда нужно проводить какие-нибудь однотипные манипуляции

// Инициализируем зависимость
app()->bind('user', function($app, $params = array()) {
    if (isset($params['id'])) $user = user($params['id']);
    // Делаем нужные манипуляции и инициализации
    ...
    // Возвращаем объект
    return $user;
});
...
// В любом месте приложения вызываем
$user = app('user', array('id' => 5));  // получаем подготовленный объект пользователя

Про filter_data() я уже писал. Добавлю только, что можно вызывать несколько фильтров для поля (через |), а также указывать параметры у фильтров (после :).

На сегодняшний момент фильтры следующие:

  • int, integer — Приводит к integer.
  • string — Удаляет теги и пробелы из начала и конца строки.
  • float — Приводит к float типу.
  • array — Конвертирует значение в массив.
  • bool, boolean — Возвращает TRUE для «1», «true», «on» и «yes». И FALSE в остальных случаях.
  • alpha — Возвращает только буквенные символы из указанного значения.
  • alpha_num — Возвращает только буквы и цифры.
  • num — Возвращает только цифры.
  • email — Удаляет все символы кроме букв, цифр и !#$%&'*+-=?^_`{|}~@.[].
  • url — Удаляет все символы кроме букв, цифр и $-_.+!*'(),{}|\\^~[]`<>#%";/?:@&=.
  • limit — Обрезает строку до указанного значения и добавляет в конец указанную строку. После двоеточия через запятую можно определить 2 параметра — длина строки и окончание ('limit:20,...'). Многоточие указывается по-умолчанию.
  • fromJSON — Декодирует строку из JSON формата.
  • toJSON — Возвращает значение в JSON формате.
  • default — Возвращает значение по-умолчанию, если указанное значение не существует ('default: Значение по-умолчанию').

Кроме того можно использовать не только замыкания (анонимные функции), но и функции php (к ним же относятся и функции самой библиотеки modHelpers). Например, из важных htmlspecialchars().

// $_POST['list' => 'cat1, cat2, cat5']
$post = filter_data($_POST, ['list' => 'explode|trim'; // Вызываем 2 фильтра - функции php
// $post['list'] = array('cat1', 'cat2', 'cat5')

Загружает объект пользователя

// $_POST = ['user' => '5']
$rules = [
	'user' => 'user', // функция modHelpers
];
$post = filter_data($_POST, $rules);
// $post['user']  - объект класса modUser с id 5.

Можно использовать контейнер для хранения правил фильтрации.

// При загрузке MODX определяем зависимость
app()->bind('user_rules', function() {
    return array(
        'username' => 'string',
        'fullname' => 'string',
        'email' => 'email',
        'user' => 'user',
    );
});

// Затем при фильтрации данных формы вызывать.
$rules = app('user_rules');
$post = filter_data($_POST, $rules);
if (is_object($user = $post['user'])) {
    $user->fromArray($post); 
    $user->Profile->fromArray($post); 
    $user->save();
}

Ну и осталась функция null_if(). Она возвращает NULL, если переданное значение равно второму параметру. По-умолчанию, второй параметр равен пустой строке. Эта функция — задел на будущий функционал валидации данных.

Ещё пару слов про функцию logout(). У неё появился третий параметр, определяющий нужно ли перелогиниться. Если указать TRUE, то если пользователь залогинен в админке, он будет аутентифицирован как этот пользователь. Если указать FALSE, то он так и останется гостем. Это может пригодится при тестировании — когда нужен гость, в вы залогинены в админке, и MODX автоматом аутентифицирует пользователя сайта как админа. Вот чтобы не выходить из админки можно разлогиниться с параметром FALSE.

Что касается функции parse(). Теперь у неё 2 режима: быстрый парсинг и полный. Быстрый — для простой замены тегов.

$tpl = '<li>[[+id]]. [[+username]]</li>';
$output = '';
foreach($users as $user) {
    $output .= parse($tpl, $user);
}
$output = '<ul>' . $output . '</ul>';

А полный парсинг работает как getChunk() для инлайн чанка. Т.е. можно указать полноценную строку с тегами чанков, сниппетов.

$tpl = 'Строка с вызовом чанка [[$chunk]].';
$output = parse($tpl, $data, true, 5);

Для полного парсинга нужно передать в третьем параметре TRUE. В четвертом можно указать количество итераций парсера. По-умолчанию, 10.

На этом всё.

0   3026

Комментарии ()

  1. Семён 21 октября 2017 # 0
    Добрый вечер, Сергей.
    Изучаю документацию modHelpers и столкнулся с таким моментом:
    yadi.sk/i/s6jTzs573NxNUc

    Согласно доков метод parent возвращает объект, с которым ожидается возможным использовать другие методы объекта, но вот поменять ему pagetitle не получается. Может я как то не правильно код написал?
    1. Сергей Шлоков 23 октября 2017 # 0
      Ну так там же написано в чем ошибка. Метод set первым параметром принимает название поля, а вторым — значение.

      Метод parent() возвращает объект xPDOObject и это его метод set().
    2. Семён 06 декабря 2017 # 0
      Возникла такая мысль, а можно ли как-то получить в чанке все доступные плейсхолдеры, но именно выставленные сниппетом, который использует этот чанк для оформления?
      Сейчас если заглянуть в массив плейсхолдеров там огромная куча всего, а хотелось бы видеть только то, что даёт сниппет.
      Было бы не плохо такую функцию всегда под рукой держать, а так приходится либо в документацию лезть искать либо в код сниппета заглядывать и там выискивать выставление плейсхолдеров.
      1. Сергей Шлоков 06 декабря 2017 # 0
        Выделить данные, переданные в чанк, не реально. По крайней мере, я не знаю такого способа. Не представляю зачем это нужно.
        1. Семён 06 декабря 2017 # 0
          Это нужно для понимания какими плейсхолдерами можно распоряжаться в чанке оформления, ведь далеко не все авторы дополнений пишут документацию о своих сниппетах, что они передают в чанк, поэтому было бы удобно вызываешь любой сниппет, а в чанке оформления запускаешь какую-нибудь конструкцию, которая тебе распечатает все плейсхолдеры сниппета и вперёд! — вставлять их в вёрстку!
          Примерно по такому принципу у Василия сделана обработка параметра &tpl в сниппетах pdoTools — если указан пустой параметр, то распечатывается весь массив плейсхолдеров, вот тоже самое хотелось бы иметь в чанках, что бы это было универсальное решение независимое от сниппета.
      2. Vladimir 16 января 2018 # 0
        Вот интересно, и modHelpers и MobileDetect используют библиотеку MobileDetect. И, вроде, на реальных устройствах работают одинаково.
        Но вот есть такой браузер, Blisk — эмулятор устройств (как мобильных так и широкоформатных), пользуюсь им примерно год. Так вот он иногда наотрез (или через раз) отказывается определять
        ​{if 'standard' | mobiledetect}
                             текст для десктопов и т.п.
                             {/if}
                             {if 'mobile' | mobiledetect}
                             тут текст со ссылкой для мобильных
                             {/if}
        
        тогда как
         {if $.php.is_tablet() or $.php.is_mobile()}
        ссылка для мобильых и планшетов
                             {else}
                       текст для десктопа     
                            {/if}
        
        — нет проблем и в эмуляторе и на реальных мобильных.
        1. Сергей Шлоков 16 января 2018 # 0
          Ну у тебя некорректное сравнение. В первом случае ты проверяешь стандарт, а во втором — мобайл. Сделай первое условие как у modHelpers. Думаю всё сработает.

          Кстати, автор пишет, что планшеты являются подмножеством мобильных. Т.е. is_mobile() будет истинно и для тех и для других. Если есть возможность, проверь этот момент.
          1. Vladimir 16 января 2018 # 0
            Во втором примере я объединяю планшеты и мобильники, просто не было смысла разделать. Но пытался по разному. Blisk вроде корректно передает юзерагент, но с modHelpers нет проблем (я только о работе в Blisk), а с пакетом MobileDetect эмулятор все время ошибается (уточню, все в случае использования fenom).
            1. Сергей Шлоков 16 января 2018 # 0
              Рад за modHelpers.:)

              Вот примеры из документации
              // Any mobile device (phones or tablets).
              if ( $detect->isMobile() ) {
               
              }
              // Any tablet device.
              if( $detect->isTablet() ){
               
              }
               // Exclude tablets.
              if( $detect->isMobile() && !$detect->isTablet() ){
               
              }
              
              Для твоего случая достаточно только is_mobile().
              1. Vladimir 16 января 2018 # +1
                Попытаюсь наплодить примеров, покажу, хочется понять почему в одном случае работает, а в другом нет.
                Было еще с MobileDetect (пакетом), что он на немецких серверах (на модхосте) и на СПБ вел себя по-разному. Т.е. буквально, меняю сервер на немецкий- работает, возвращаю на СПБ — нет.
                (это я опять про тот же браузер-эмулятор Blisk, на «железных» девайсах все нормально во всех случаях, но в Blisk уж очень удобно тестить варианты отображения.)

                Да, за modHelpers огромное спасибо!
        2. Алексей 23 мая 2019 # +1
          Добрый вечер, Сергей.
          Прежде всего, большое человеческое спасибо вам за modHelpers.

          Вопрос по filter_data() и фильтру string.
          $rules = [
          	'name' => 'string', // Удаляет теги и пробелы (trim) из $_POST['name']
          ];
          $arr = array(
              'name' => ' 
          Тест'
          );
          $filteredData = filter_data($arr, $rules);
          
          Судя по документации и https://github.com/sergant210/modHelpers/blob/70822a0d86a24507b19535a3c072a28bdda4b863/core/components/modhelpers/functions/functions.php#L1785 должен выдавать нам
          Array
          (
              [name] => Тест
          )
          
          но выводит, видимо, из-за https://github.com/sergant210/modHelpers/blob/70822a0d86a24507b19535a3c072a28bdda4b863/core/components/modhelpers/functions/functions.php#L2127
          Array
          (
              [name] => modHelpers\Str Object
                  (
                      [original:protected] =>  
          Тест
                      [string:protected] =>  
          Тест
                  )
          
          )
          Так и задумано, или это ошибка?
          p.s. версия modhelpers 3.7.0-pl
          1. Сергей Шлоков 23 мая 2019 # +1
            Это баг. Поправил. Спасибо.

            Чтобы не ждать новой версии, можете сами исправить. Добавьте «string» после «url» в массиве.

          Вы должны авторизоваться, чтобы оставлять комментарии.

          Выделите опечатку и нажмите Ctrl + Enter, чтобы отправить сообщение об ошибке.