Макросы в Laravel | OTUS
🔥 Начинаем BLACK FRIDAY!
Максимальная скидка -25% на всё. Успейте начать обучение по самой выгодной цене.
Выбрать курс

Курсы

Программирование
iOS Developer. Basic
-25%
Python Developer. Professional
-25%
Разработчик на Spring Framework
-25%
Golang Developer. Professional
-25%
Python Developer. Basic
-25%
iOS Developer. Professional
-25%
Node.js Developer
-25%
Unity Game Developer. Professional
-25%
React.js Developer
-25%
Android Developer. Professional
-25%
Software Architect
-25%
C++ Developer. Professional
-25%
Backend-разработчик на PHP Web-разработчик на Python Алгоритмы и структуры данных Framework Laravel PostgreSQL Team Lead Разработчик голосовых ассистентов и чат-ботов Архитектура и шаблоны проектирования Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT IoT-разработчик Подготовка к сертификации Oracle Java Programmer (OCAJP) Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Azure для разработчиков"
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-25%
DevOps практики и инструменты
-25%
Архитектор сетей
-25%
Инфраструктурная платформа на основе Kubernetes
-25%
Супер-интенсив «ELK»
-16%
Супер-интенсив «IaC Ansible»
-16%
Administrator Linux. Professional MS SQL Server Developer Безопасность Linux PostgreSQL Reverse-Engineering. Professional CI/CD VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Administrator Linux.Basic Супер-интенсив "Tarantool"
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Макросы в Laravel

PHP_deep_25.3-5020-657699.png

О макросах в Laravel сказано явно недостаточно, и мы постараемся исправить эту досадную оплошность. Если говорить о макросах вкратце, то речь идёт о способе расширения метода класса, однако не через наследование, а через замыкание. При этом макросы можно применять в любом классе фреймворка Laravel, который использует трейт Macroable.

Использование макросов позволит вам улучшить свою работу, снизить дублирование кода, сделать код более читабельным, да и просто решить ряд проблем, которые иногда возникают при тестировании.

Как сделать и куда положить макросы в Laravel?

Итак, есть несколько мест, куда можно положить макросы: 1.Использование простого PHP-файла и его загрузка через Composer. Нужно создать новый файл macros.php в папке app. После этого следует отредактировать autoload в composer.json, добавив в свойство files относительный путь к файлу app/macros.php. Далее останется запустить composer dump-autoloader, чтобы файл загружался и выполнялся, настраивая макросы для всего нашего приложения.

"autoload": {
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories"
],
"files": [
"app/macros.php"
]
}

2.Второе место — это метод boot в сервис-провайдере. По правде говоря, это не самый оптимальный способ, т. к. при росте приложения придётся добавлять всё больше макросов. Но тем не менее.

Коллекции

Большинство людей познакомились с макросами именно с помощью коллекций в Laravel, поэтому не будем об этом много рассказывать. Приведём лишь простой, но хороший пример небольшого макроса — это преобразование ключей для массива. Если вы захотите написать преобразование как функцию, это будет довольно утомительно. Лучше использовать макрос. Сначала его необходимо создать, чтобы всё отмаппить и управлять рекурсивно:

<?php

\Illuminate\Support\Collection::macro(
'mapKeysWith',
function ($callable) {
/* @var $this \Illuminate\Support\Collection */
return $this->mapWithKeys(function ($item, $key) use ($callable) {
if (is_array($item)) {
$item = collect($item)
->mapKeysWith($callable)
->toArray();
}
return [$callable($key) => $item];
});
}
);

А потом создать ещё один, чтобы красиво всё обернуть:

<?php

\Illuminate\Support\Collection::macro(
'mapKeysToCamelCase',
function () {
/* @var $this \Illuminate\Support\Collection */
return $this->mapKeysWith('camel_case');
}
);

Вуаля, теперь можно использовать наш макрос, к примеру, так:

<?php

collect(['test_key' => ['second_layer' => true]])->mapKeysToCamelCase();
// Создает массив ['TestKey' => ['SecondLayer' => true]]

Запросы Eloquent

Здесь применение макросов имеет действительно важное значение. К примеру, вы хотите напрямую использовать БД. Скорее всего, вы будете делать это, используя «сырые» запросы (raw queries):

<?php

$query->whereRaw(
"ST_Distance_Sphere(`table`.`column`, POINT(?, ?)) < ?",
[$long, $lat, $distance],
$boolean
);

Если в вашем приложении вы будете делать это слишком часто, код станет повторяемым, не говоря уже о попытках соединить несколько where в одном выражении. Да, можно обойти это с помощью скоупов (scopes), но их тогда придётся добавлять в каждую модель. Проще всего — создать макрос. В нашем примере мы создаём макрос для фильтрации результатов в MySQL, применяя встроенные геопространственные функции сервера:

<?php

\Illuminate\Database\Query\Builder::macro(
'whereSpatialDistance',
function ($column, $operator, $point, $distance, $boolean = 'and') {
$this->whereRaw(
"ST_Distance_Sphere(`{$this->from}`.`$column`, POINT(?, ?)) $operator ?",
[$point[0], $point[1], $distance],
$boolean
);
});

А чтобы мы могли использовать условие orWhere, добавим ещё один макрос:

<?php

\Illuminate\Database\Query\Builder::macro(
'orWhereSpatialDistance',
function ($column, $operator, $point, $distance) {
$this->whereSpatialDistance($column, $operator, $point, $distance, 'or');
}
);

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

<?php

$query->whereSpatialDistance('coordinates', [1, 1], 10)
->orWhereSpatialDistance('coordinates', [0, 0], 1);

Написано по материалам статьи «Laravel Tip: 5 examples of why you should be using Macros».

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться
🎁 Максимальная скидка!
Черная пятница уже в OTUS! Скидка -25% на всё!