Вот! Сила… макросов!

Как я уже писал ранее, возможности макросов в Laravel довольно велики, поскольку они позволяют расширять класс во время выполнения с помощью ваших собственных методов. Вы можете добавить полезные методы, которые могут преобразовывать подробный код в выразительные однострочники, которые имеют смысл. Один из них выходит из коробки - это проверка запроса:

public function (Request $request)
{
    $request->validate([
        'email' => 'required|unique:users',
    ]);
    // ...
}

В список классов, реализующих свойство Macroable, которое включает макросы в классе, входят Query Builder и Eloquent Builder. Оба они используются для выполнения запросов непосредственно к базе данных.

Одна из вещей, которые я постоянно делаю, когда мне нужны дорогие вычисления SQL, - это сохранять результат в кэше, что сильно раздувает код:

$votes = 100;
$users = Cache::remember('users', 60, function () use ($votes) {
        return Users::has('comments')
            ->where('votes', '>', $votes)
            ->get();
    });

Было бы неплохо сделать что-то одной строчкой вместо того, чтобы угадывать, что, черт возьми, я написал?

Конечно!

План, класс и макрос

Я хочу запомнить результаты, используя этот простой синтаксис; вот что я хочу написать в своем приложении:

$results = User::where('something')->remember(60)->get();

Чтобы это сработало, недостаточно добавить метод remember() в качестве макроса в построитель запросов. Если мы сделаем только это, используя другой другой метод, например get() (или любой другой метод получения), он вернет результат запроса, минуя любую логику запоминания.

Другими словами: кеш и результат запроса не связаны.

Итак, я закончил создание очень простого пакета, следуя диаграмме ниже. Существует крошечный класс, который после вызова remember() становится промежуточным звеном между Builder и Cache.

Чтобы лучше объяснить это, когда вы используете метод remember(), экземпляр Eloquent или Query Builder будет инкапсулирован внутри класса, который будет передавать все ваши методы в Builder ... кроме случаев, когда Builder возвращает результат базы данных - в основном все, кроме самого экземпляра Builder .

Это очень хороший способ делать дорогостоящие вызовы базы данных без использования подробной логики для использования замыканий. Вернемся к нашему первому примеру:

$votes = 100;
$users = Cache::remember('users', 60, function () use ($votes) {
        return Users::has('comments')
            ->where('votes', '>', $votes)
            ->get();
    });

Хорошо, мы знаем, что используем кеш. Замыкание находится внутри логики кеширования, которая фактически вызывает базу данных при импорте переменной извне. Теперь сравните это с этой выразительной строкой:

$users = Users::has('comments')->where('votes', '>', $votes)
    ->remember()
    ->get();

Хорошая часть? Ключ кеша обрабатывается автоматически. По сути, он хеширует SQL-запрос запроса вместе с привязками, делая каждый оператор уникальным. Другими словами, логика может быть такой же, но если вы измените такую ​​переменную, как количество голосов, со 100 на 99, хеш будет другим, и результат будет выполнен и сохранен в кеш-памяти.

Вот и все. Попробуй и скажи мне, что ты думаешь.