HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>О<strong>макросах в Laravel</strong>сказано явно недостаточно, и мы постараемся исправить эту досадную оплошность. Если говорить о макросах вкратце, то речь идёт о способе расширения метода класса, однако не через наследование, а через замыкание. При этом макросы можно применять в любом классе фреймворка Laravel, который использует трейт Macroable.</p>
1 <p>О<strong>макросах в Laravel</strong>сказано явно недостаточно, и мы постараемся исправить эту досадную оплошность. Если говорить о макросах вкратце, то речь идёт о способе расширения метода класса, однако не через наследование, а через замыкание. При этом макросы можно применять в любом классе фреймворка Laravel, который использует трейт Macroable.</p>
2 <p>Использование макросов позволит вам улучшить свою работу, снизить дублирование кода, сделать код более читабельным, да и просто решить ряд проблем, которые иногда возникают при тестировании.</p>
2 <p>Использование макросов позволит вам улучшить свою работу, снизить дублирование кода, сделать код более читабельным, да и просто решить ряд проблем, которые иногда возникают при тестировании.</p>
3 <h2>Как сделать и куда положить макросы в Laravel?</h2>
3 <h2>Как сделать и куда положить макросы в Laravel?</h2>
4 <p>Итак, есть несколько мест, куда можно положить макросы: 1.Использование простого PHP-файла и его загрузка через<strong>Composer</strong>. Нужно создать новый файл<strong>macros.php</strong>в папке<strong>app</strong>. После этого следует отредактировать<strong>autoload</strong>в<strong>composer.json</strong>, добавив в свойство<strong>files</strong>относительный путь к файлу<strong>app/macros.php</strong>. Далее останется запустить<strong>composer dump-autoloader</strong>, чтобы файл загружался и выполнялся, настраивая макросы для всего нашего приложения.</p>
4 <p>Итак, есть несколько мест, куда можно положить макросы: 1.Использование простого PHP-файла и его загрузка через<strong>Composer</strong>. Нужно создать новый файл<strong>macros.php</strong>в папке<strong>app</strong>. После этого следует отредактировать<strong>autoload</strong>в<strong>composer.json</strong>, добавив в свойство<strong>files</strong>относительный путь к файлу<strong>app/macros.php</strong>. Далее останется запустить<strong>composer dump-autoloader</strong>, чтобы файл загружался и выполнялся, настраивая макросы для всего нашего приложения.</p>
5 "autoload": { "psr-4": { "App\\": "app/" }, "classmap": [ "database/seeds", "database/factories" ], "files": [ "app/macros.php" ] }<p>2.Второе место - это метод<strong>boot</strong>в сервис-провайдере. По правде говоря, это не самый оптимальный способ, т. к. при росте приложения придётся добавлять всё больше макросов. Но тем не менее.</p>
5 "autoload": { "psr-4": { "App\\": "app/" }, "classmap": [ "database/seeds", "database/factories" ], "files": [ "app/macros.php" ] }<p>2.Второе место - это метод<strong>boot</strong>в сервис-провайдере. По правде говоря, это не самый оптимальный способ, т. к. при росте приложения придётся добавлять всё больше макросов. Но тем не менее.</p>
6 <h2>Коллекции</h2>
6 <h2>Коллекции</h2>
7 <p>Большинство людей познакомились с макросами именно с помощью коллекций в<strong>Laravel</strong>, поэтому не будем об этом много рассказывать. Приведём лишь простой, но хороший пример небольшого макроса - это<strong>преобразование ключей для массива</strong>. Если вы захотите написать преобразование как функцию, это будет довольно утомительно.<strong>Лучше использовать макрос</strong>. Сначала его необходимо создать, чтобы всё отмаппить и управлять рекурсивно:</p>
7 <p>Большинство людей познакомились с макросами именно с помощью коллекций в<strong>Laravel</strong>, поэтому не будем об этом много рассказывать. Приведём лишь простой, но хороший пример небольшого макроса - это<strong>преобразование ключей для массива</strong>. Если вы захотите написать преобразование как функцию, это будет довольно утомительно.<strong>Лучше использовать макрос</strong>. Сначала его необходимо создать, чтобы всё отмаппить и управлять рекурсивно:</p>
8 &lt;?php \Illuminate\Support\Collection::macro( 'mapKeysWith', function ($callable) { /* @var $this \Illuminate\Support\Collection */ return $this-&gt;mapWithKeys(function ($item, $key) use ($callable) { if (is_array($item)) { $item = collect($item) -&gt;mapKeysWith($callable) -&gt;toArray(); } return [$callable($key) =&gt; $item]; }); } );<p>А потом создать ещё один, чтобы красиво всё обернуть:</p>
8 &lt;?php \Illuminate\Support\Collection::macro( 'mapKeysWith', function ($callable) { /* @var $this \Illuminate\Support\Collection */ return $this-&gt;mapWithKeys(function ($item, $key) use ($callable) { if (is_array($item)) { $item = collect($item) -&gt;mapKeysWith($callable) -&gt;toArray(); } return [$callable($key) =&gt; $item]; }); } );<p>А потом создать ещё один, чтобы красиво всё обернуть:</p>
9 &lt;?php \Illuminate\Support\Collection::macro( 'mapKeysToCamelCase', function () { /* @var $this \Illuminate\Support\Collection */ return $this-&gt;mapKeysWith('camel_case'); } );<p>Вуаля, теперь можно использовать наш макрос, к примеру, так:</p>
9 &lt;?php \Illuminate\Support\Collection::macro( 'mapKeysToCamelCase', function () { /* @var $this \Illuminate\Support\Collection */ return $this-&gt;mapKeysWith('camel_case'); } );<p>Вуаля, теперь можно использовать наш макрос, к примеру, так:</p>
10 &lt;?php collect(['test_key' =&gt; ['second_layer' =&gt; true]])-&gt;mapKeysToCamelCase(); // Создает массив ['TestKey' =&gt; ['SecondLayer' =&gt; true]]<h2>Запросы Eloquent</h2>
10 &lt;?php collect(['test_key' =&gt; ['second_layer' =&gt; true]])-&gt;mapKeysToCamelCase(); // Создает массив ['TestKey' =&gt; ['SecondLayer' =&gt; true]]<h2>Запросы Eloquent</h2>
11 <p>Здесь применение макросов имеет действительно важное значение. К примеру, вы хотите напрямую использовать БД. Скорее всего, вы будете делать это, используя "сырые" запросы (raw queries):</p>
11 <p>Здесь применение макросов имеет действительно важное значение. К примеру, вы хотите напрямую использовать БД. Скорее всего, вы будете делать это, используя "сырые" запросы (raw queries):</p>
12 &lt;?php $query-&gt;whereRaw( "ST_Distance_Sphere(`table`.`column`, POINT(?, ?)) &lt; ?", [$long, $lat, $distance], $boolean );<p>Если в вашем приложении вы будете делать это слишком часто, код станет повторяемым, не говоря уже о попытках соединить несколько where в одном выражении. Да, можно обойти это с помощью скоупов (scopes), но их тогда придётся добавлять в каждую модель. Проще всего - создать макрос. В нашем примере мы создаём макрос для фильтрации результатов в MySQL, применяя встроенные геопространственные функции сервера:</p>
12 &lt;?php $query-&gt;whereRaw( "ST_Distance_Sphere(`table`.`column`, POINT(?, ?)) &lt; ?", [$long, $lat, $distance], $boolean );<p>Если в вашем приложении вы будете делать это слишком часто, код станет повторяемым, не говоря уже о попытках соединить несколько where в одном выражении. Да, можно обойти это с помощью скоупов (scopes), но их тогда придётся добавлять в каждую модель. Проще всего - создать макрос. В нашем примере мы создаём макрос для фильтрации результатов в MySQL, применяя встроенные геопространственные функции сервера:</p>
13 &lt;?php \Illuminate\Database\Query\Builder::macro( 'whereSpatialDistance', function ($column, $operator, $point, $distance, $boolean = 'and') { $this-&gt;whereRaw( "ST_Distance_Sphere(`{$this-&gt;from}`.`$column`, POINT(?, ?)) $operator ?", [$point[0], $point[1], $distance], $boolean ); });<p>А чтобы мы могли использовать условие<strong>orWhere</strong>, добавим ещё один макрос:</p>
13 &lt;?php \Illuminate\Database\Query\Builder::macro( 'whereSpatialDistance', function ($column, $operator, $point, $distance, $boolean = 'and') { $this-&gt;whereRaw( "ST_Distance_Sphere(`{$this-&gt;from}`.`$column`, POINT(?, ?)) $operator ?", [$point[0], $point[1], $distance], $boolean ); });<p>А чтобы мы могли использовать условие<strong>orWhere</strong>, добавим ещё один макрос:</p>
14 &lt;?php \Illuminate\Database\Query\Builder::macro( 'orWhereSpatialDistance', function ($column, $operator, $point, $distance) { $this-&gt;whereSpatialDistance($column, $operator, $point, $distance, 'or'); } );<p>Теперь, если нужно отфильтровать запрос, можно вызвать макрос напрямую точно так же, как и любой другой оператор where.</p>
14 &lt;?php \Illuminate\Database\Query\Builder::macro( 'orWhereSpatialDistance', function ($column, $operator, $point, $distance) { $this-&gt;whereSpatialDistance($column, $operator, $point, $distance, 'or'); } );<p>Теперь, если нужно отфильтровать запрос, можно вызвать макрос напрямую точно так же, как и любой другой оператор where.</p>
15 &lt;?php $query-&gt;whereSpatialDistance('coordinates', [1, 1], 10) -&gt;orWhereSpatialDistance('coordinates', [0, 0], 1);<p><em>Написано по материалам статьи "<a>Laravel Tip: 5 examples of why you should be using Macros</a>".</em></p>
15 &lt;?php $query-&gt;whereSpatialDistance('coordinates', [1, 1], 10) -&gt;orWhereSpatialDistance('coordinates', [0, 0], 1);<p><em>Написано по материалам статьи "<a>Laravel Tip: 5 examples of why you should be using Macros</a>".</em></p>
16  
16