Рефакторинг eloquent запросов через Сообщения Высшего Порядка

Higher Order Messages

Самый кайф при работе с Laravel — это найти альтернативный способ делать старые и уже наскучившие тебе вещи. Недавно, при работе с Eloquent, я столкнулся с тем, что называют Higher Order Messages (Сообщения высшего порядка). Этот функционал появился в Laravel 5.4.

Higher Order Messages — это причудливый термин, обозначающий механику, когда компьютерная программа разрешает сообщения, содержащие другие сообщения в качестве аргументов/методов. Звучит запутанно? Поверь мне, все не так сложно. Давайте разберемся с этим на примере.

Допустим, у нас есть модель User связанная с таблицей users, которая выглядит примерно так:

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model 
{
    // пока здесь ничего нет
}

Давайте сделаем для неё контроллер. Назовем его UserController.

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\User;

class UserController extends Controller
{
    public function index()
    {
        return User::where('active', 1);
    }
}

Пока ничего необычного. Метод index возвращает всех активных пользователей в виде массива json. Но проблема в том, что он вернет все поля таблицы users. А если нам нужны только определенные поля с кастомными ключами, то мы можем сделать это так.

class UserController extends Controller
{
    public function index()
    {
        return User::where('active', 1)
            ->map(function($user) {
                return [
                    'user_id' => $user->id,
                    'name' => $user->name
                    'title' => $user->title
                ]
            });
    }
}

Ожидаемо — вышеприведенный код вернет ответ с указанными полями для каждого пользователя. Именно здесь вступают в игру Higher Order Messages, при условии, что вы хотите сделать код более аккуратным.

Используя их, мы можем определить метод (с логикой замыкания map) прямо в модели…

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model 
{
    public function transform()
    {
        return [
            'user_id' => $this->id,
            'name' => $this->name,
            'title' => $this->title
        ];
    }
}

…и «передать» его методу map в запросе Eloquent, как показано ниже.

class UserController extends Controller
{
    public function index()
    {
        return User::where('active', 1)
            ->map->transform();
    }
}

Это тоже самое, что и при использовании анонимной функции в map. Теперь вы можете напрямую передавать метод transform модели User в map. Как вы можете видеть, это пригодится, если вы хотите сделать рефакторинг ваших запросов и поддерживать чистоту ваших контроллеров (или фабрик).

Вот все методы коллекций, которые поддерживают сообщения высокого порядка: average, avg, contains, each, every, filter, first, flatMap, map, partition, reject, sortBy, sortByDesc и sum.

Автор: Amit Merchant
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.