modHelpers 3.0. Обработка запросов, контексты


Всем привет! Сегодня выпустил новую версию библиотеки modHelpers. Вот основные изменения:
  • Добавлено пространство имен для всех классов.
  • Добавлена функция request().
  • Добавлена функция switch_context().
  • В класс Object добавлен метод «object».
  • В класс Object добавлен метод «parent».
  • В класс Query добавлен метод «first».
  • В класс Query добавлен метод «toString».
Звучит суховато. Давайте разберёмся поподробнее.
Как вы могли заметить, изменилась мажорная версия. Это сигнал для разработчиков задуматься перед обновлением. Главная причина — версия PHP >= 5.5 и неймспейс. Все классы теперь упакованы в пространство имён modHelpers. Те, кто не работал напрямую с классами, а пользовался функциями, могут спокойно обновляться. При условии, что версия PHP сервера не ниже 5.5. А вот тем, кто пользовался классами, придётся править код. Класс modHelpersMailer теперь называется modHelpers\Mailer. И так с остальными классами.

Обработка запросов

Это самая большая доработка. Для этой задачи используется библиотека symfony/http-foundation. С помощью неё можно работать со всеми данными HTTP запроса — GET, POST, QUERY, SERVER, COOKIE, FILES, HEADER. И всё это в одном месте.
if (request()->isAjax()) // ajax запрос
if (request()->isJson()) // json запрос
// К json данным можно обращаться
request()->json('key');
# Получить данные запроса 
request()->all(); // Все данные вместе с файлами
request()->input(); // Данные POST
request()->query(); // Данные GET
request()->allFiles(); // Загруженные файлы
# Выборочно
request()->only([...]); // Только указанные данные из запроса
request()->except([...]); // За исключением указанных данных из запроса
# URI
request()->getHost(); // HOST_NAME
request()->path(); // Путь
request()->url(); // Url без данных после знака ?
request()->fullUrl(); // Url c данными после знака ?
# Фильтрация 
request()->filter($rules); 
request()->input(); // Отфильтрованные данные

// и много ещё другого
Обратиться к данными можно несколькими способами:
$request = request();
$key = $request->input('key');
// или
$key = $request->key;
// или
$key = $request['key'];

Особенно удобно работать с загруженными файлами:
// Загружает все файлы по указанному пути для указанного источника файлов.
$request->uploadFiles($path, $mediaSource);
// Можно загрузить каждый файл отдельно
if ($request->hasFile('file')) {
    $request->file('file')->store('assets', $mediaSource);  // Имя файла будет захешировано
}
if ($request->hasFile('avatar')) {
    $request->file('avatar')->storeAs('assets', 'avatar.jpg', $mediaSource); // Указываем имя
}
Теоретически можно заливать файлы и на облачные хранилища, но этот момент я не тестировал.
Класс файла наследуется от SplFileInfo. Так что у него куча методов для работы с файлами.

Переключение контекстов

Для этого предназначена функция switch_context(). У неё 2 режима:
  • Простой — в параметре передать ключ контекста.
  • По условию — нужно указать критерий.
# Простой вариант
switch_context($context_key); // аналогично $modx->switchContext()

# Переключение контекстов на субдоменах
switch_context(['http_host' => $_SERVER['HTTP_HOST']]); // или  request()->getHost()

# Переключение контекстов на директориях
switch_context(['base_url' => request()->segment(1)]);
Вторым параметром можно передать массив контекстов, которые нужно игнорировать.
Напомню, что данную функцию нужно вызывать на событие OnHandleRequest.

Прочие доработки

Дальше по классу Object. Этот класс используется в функциях object(), resource() и user(). У них есть одно отличие — последние 2 функции возвращают объект класса modResource или modUser, если передать критерии отбора. Если вызывать эти функции без параметров, то вернётся объект класса modHelpers\Object, который используется для построения запросов. Функция object() всегда возвращает объект класса modHelpers\Object. Т.е. возможна такая конструкция:
// Функция object()
$queryBuilder = object('modUser')->where(['active' => 1])->limit(1);
$user = $queryBuilder->get();

// Аналогично для функции user()
$queryBuilder = user()->where(['active' => 1])->limit(1);
$user = $queryBuilder->get();

$user = user(1); // Вернёт сразу объект класса modUser

Так вот, при использовании построителя запросов, чтобы получить сам объект, нужно завершить цепочку методами get(), first() или last(). Метод object() также получает объект. Добавил для семантики.
Метод parent() возвращает объект родителя, если он есть. Можно указать уровень — «папа», «дедушка», «прадедушка».
$parent = object('modResource')->parent();
$grandpa = object('modResource')->parent(2);
Для объекта должна быть определена связь Parent.

Теперь по классу Query. Метод first(), в отличие от метода execute(), возвращает не массив строк, а массив с данными одной строки.
Метод toString() выводит результат запроса через print_r(). Удобно для тестирования.

Вроде ничего не забыл. Все подробности будут в документации. Планирую сделать серию видео.
Кому нравится — плюсуйте, кому нет — ругайте.

П.С. Забыл написать про возможность расширения — все классы библиотеки можно расширять. Для этого нужно указать класс в соответствующей системной настройке:
  • modhelpers_cacheManagerClass — новый класс менеджера кэша;
  • modhelpers_collectionClass — новый класс коллекции;
  • modhelpers_containerClass — новый класс контейнера;
  • modhelpers_loggerClass — новый класс логера;
  • modhelpers_mailerClass — новый класс мейлера;
  • modhelpers_modelBuilderClass — новый класс билдера модели;
  • modhelpers_modelColumnClass — класс колонок модели;
  • modhelpers_objectClass — класс менеджера объектов;
  • modhelpers_queryClass — класс менеджера SQL запросов;
  • modhelpers_requestClass — класс HTTP запросов;
27 сентября 2017, 20:33    Сергей Шлоков   G+  
4    392 +18

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

  1. Алексей Соин 28 сентября 2017, 10:34 # +4
    Отличное дополнение! Спасибо вам огромное, что улучшаете его =)
    1. Сергей Шлоков 28 сентября 2017, 15:03 # +3
      Спасибо за добрые слова! :)
    2. Сергей Шлоков 02 октября 2017, 08:53 # +3
      Ещё забыл написать про новый метод кэшменеджера — remember. Он пригодится в тех случаях, когда нужно получить значение из кэша, и если кэш пусто, то сохранить данные в кэш.
      Например, получаем общее количество активных пользователей.
      cache()->remember('count_users', 300, function() use ($modx) {
          return $modx->getCount('modUser', array('active' => 1));
      });
      
      Если в кэше пусто, то выполняется замыкание, в котором возвращается вычисленное значение. Затем это значение сохраняется в кэше на 5 минут. И пока не истечет это время при последующих запросах количество пользователей будет запрашиваться из кэша.

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