Laravel: How to extend Request class

webgods article cover image

Понякога искаме да разширим Request обекта, който идва с Laravel, за да си добавим нов метод, който е тясно свързан с бизнес логиката на проекта ни. Понякога ни трябва нещо, което да филтрира данните и да бъде достъпно на глобалното ниво през request()хелпъра, а понякога просто искаме да му добавим допълнителен метод, който да чете някакъв хедър и да ни го връща обработен.

Преди да видим как да разширим Request обекта, трябва да се запитаме точно там ли е мясото на функцията от която имаме нужда, защо не е просто метод в отделен хелпър или сървис клас? Все още мислиш, че най-правилно и логично би било функцията да се достъпва през request() хелпъра? Нека видим как става това.

1. Традиционен начин

Тук говорим за най-традиционният начин, чрез заменяне на Request класа с наш, който да наследява оригиналния Request клас. Ето как би станало това.
Създаваме Нов клас: \App\Http\Requests\CustomRequest , и в AppServiceProvider го заместваме, но лошото е, че това няма автоматично да замени оригиналния Request клас на всякъде, както и request() хелпъра трябва да бъде заменен в контейра отделно.

2. По-лесен, добър и удобен начин

Можем да ползваме macro метода, има го на почти всеки основен клас в Laravel, който ни позволява да си добавим с лекота нашите методи вурху основният Request клас, без да се налага да го заменяме и да се борим с контейнера, а най-хубавото е, че хем си ползваме оригиналният Request и request() хелпъра, които автоматично имат нашият нов метод.

<?php 
namespace App\Providers;
use Illuminate\Http\Request;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Request::macro('filterArrayElements', function () {
            return array_filter($this->all(), function ($value) {
                return ! empty($value);
            });
        }
    }
}

// ustage: 
// $request->filterArrayElements();
// request()->filterArrayElements();

Какво всъщност е "macro" метода и от къде идва?

Macro метода идва от trait пакетиран в базовия код на Laravel на име Illuminate\Support\Traits\MacroableТози трейт се наследява от повечето класове, които Laravel предлага като:

  • Cache

  • File

  • Lang

  • Request

  • Response

  • Route

  • URL

  • Illuminate\Cache\Repository

  • Illuminate\Console\Scheduling\Event

  • Illuminate\Database\Eloquent\Builder

  • Illuminate\Database\Eloquent\Relation

  • Illuminate\Database\Query\Builder

  • Illuminate\Filesystem\Filesystem

  • Illuminate\Foundation\Testing\TestResponse

  • Illuminate\Support\Str

  • Illuminate\Translation\Translator

  • Illuminate\Http\RedirectResponse

  • Illuminate\Http\Request

  • Illuminate\Http\UploadedFile

  • Illuminate\Routing\ResponseFactory

  • Illuminate\Routing\Router

  • Illuminate\Routing\UrlGenerator

  • Illuminate\Support\Arr

  • Illuminate\Support\Collection

С оглед на по-горните класове става ясно, че Macro трейта може да се наследи във всеки клас и той да придобие тази възможност за ултра бързо разширяване.

<?php
use Illuminate\Support\Traits\Macroable;
class MyClass {
    use Macroable;
}

Това означа че автоматично можем да разширим класа си в boot метода в AppServiceProvider:

<?php
// AppServiceProvider.php
public function boot()
{
    MyClass::macro('greet', function (?string $greeting = null) {
        return !is_null($greeting)
            ? sprintf('%s %s%s', $greeting, $this->name, PHP_EOL)
            : 'No hello for you sir!';
    });
}
// and you can use it like this:
// $myClass = (new MyClass)->greet('You') <---


3. Заключение: три пъти мери, един път режи

Нека първо вметнем факта, че общоноста от програмисти и ентусиасти стоящи зад отворения код на Laravel постоянно доприасят към развитието на платформата. За това винаги е важно да проверяваме не само документацията на използваната от нас версия на Laravel, но и документацията на най-актуалната версия към момента, защото е твърде вероятно отговора на задачата ви вече да е бил срещнат от много други и дори вече да включен в новата версия на платформата.

Ето за пример - Беше ни необходимо да извлечем за дадена форма стойностите валидирани по тип по възможно най-интуитивния начин, за да си гарантираме бъдещето използване и прилагане на метода, който искахме да вградим. Минахме през наследяване, декориране, та дори и през презаписване на основния Request клас, само за да можем да извикаме request()->float() на дадени входящи данни и това да ни валидира стойноста и да ни я върне ако отговаря.

След като упорито търсихме начин за глобалното презаписване и наследяване, за да може да е общо достъпно без излишни действия не намерихме нищо подобно в документацията на Laravel, но след детайлно разравяне в кодовата база се намерихме не само на точно такъв метод request()->float(), който правеше точно това, но и на други подобни методи, които ни решиха проблема, за който бяхме готови да презаписваме и наследяваме цял основен клас.

Все пак се надяваме, че тази статия вие е била от полза и ви е спеситла време. Понякога трябва да се разровим и доверим на инструмента, който ползваме и да си спомним или научим как точно работи той, защото може да се окаже че има доста по-лесен и вграден начин за решенеи на проблема ни.


Кои сме ние и защо да изберете нас?

Ние сме Webgods.bg, базирани сме в гр. Стара Загора и създаваме персонализирани проекти, създадени единствено и специално за вас и вашите нужди. Проекти, които да ви представляват пред вашите доверени партньори и да смажат конкуренцията. Ние сме надежден партньор, на който може да разчитате да бъде до вас в изработката на уеб сайт или изработката на онлайн магазин. Готови сме да изградим единствен по рода си уеб сайт или онлайн магазин за твоят бизнес, продукт или услуга. Заедно ще изградим едно дългосрочно партньорство и ще се погрижим за вашият дигитален успех!

Имаш ли нужда от уеб сайт или онлайн магазин?

Ние сме в готовност, а ти?

Изпрати запитване

Реализирани проекти от нас

Искам безплатна консултация

Попълнете заявката и ние ще ви се обадим за безплатна неангажираща 30 минутна консултация. Колкото по-детаийлно опишете вашите нужди, толкова по-конкретно ще можем да отговорим относно срокове, цени и дали ще можем да ви помогнем.
Отбележете сферите, в които имате нужда от консултация

Това ще ни помогне да бъдем подготвени и точно с кой от наишят екип да ви свъжем

Обикновенно отговаряме в рамките на 2 работни дни.