• Блог
  • Обработка запросов, контексты

Эта версия 3.0.0 вышла ещё в сентебре. Но я вдруг обнаружил, что забыл опубликовать новость об этом тут. Или её кто-то украл. Поэтому исправляю данное недоразумение. Теперь про новую версию. Вот список доработок:

  • Добавлено пространство имен для всех классов.
  • Добавлена функция 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]);
$user = $queryBuilder->get();

// Аналогично для функции user()
$queryBuilder = user()->where(['active' => 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 запросов;

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

1   2223

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

  1. Семён 28 декабря 2017 # 0
    Приветствую, Сергей! С наступающим!!!
    Разбирался тут с посредниками и modHelpers и возник вопрос — вот есть у нас менеджер запросов, он всё умеет получать, есть целая коллекция функций что бы разобрать запрос по косточкам, а как на счёт менять какие то параметры запроса? Есть ли для этого какие-то методы или тут уже своими силами нужно обработку писать?
    Идея какая — почти на всех сайтах требуется единая система url адресов, ну это сеошная тема, и обычно хотят чтобы либо всё через слеш работало либо наоборот, всё без слеша, тоже самое с гет-параметрами, чтобы избежать потенциальных дублей, нужно оставить обработку только тех параметров, которые есть в белом списке, всё остальное из запроса удалять. Раньше я всё это через плагины делал, а теперь хочу через посредников сделать, всё равно абсолютно все запросы нужно обрабатывать — так вот я хочу, что бы всё по-шагам срабатывало, первый посредник разбирается со слешами и если нужно то меняет запрос и дальше передаёт второму посреднику, который уже разбирается с гет-параметрами. Вопрос тут как можно передать измененный запрос между посредниками? На совсем простом примере покажу:
    Есть адрес: mysite.ru/search/ — все url должны быть со слешами (даже когда передаются гет-параметры), то есть вот так mysite.ru/search/?query=abc
    Пользователь, допустим вводит mysite.ru/search?query=abc&blabla=nothing
    1)Первый посредник смотрит — ага, на конце нет слеша и меняет запрос, передавая его дальше второму посреднику
    2)Второй посредник получает уже mysite.ru/search/?query=abc&blabla=nothing
    сверяется с белым списком параметров, а остальные удаляет (допустим, что в белом только — query)
    Получаем финальный запрос — mysite.ru/search/?query=abc
    1. Сергей Шлоков 28 декабря 2017 # 0
      Добрый вечер!
      Не вижу необходимости в разных посредниках. Для этого достаточно и одного.
      1. Проверяются параметры согласно белого списка и формируется соответствующий массив $whiteParams. Например, с помощью функции filter_data().
      2. Получить финальный запрос
      request()->url() . '/?' . http_build_query($whiteParams);
      П.С. С наступающим Новым годом!

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

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