7 трюков - как сделать модели laravel лучше

Переведено из источника с некоторыми изменениями: https://itnext.io/7-things-you-need-to-know-to-get-the-most-out-of-your-laravel-model-4f915acbb47c

Когда я начал разрабатывать на laravel у меня возникли мысли, что можно улучшить многие вещи касательно моделей. Изучая Eloquent Model класс, я нашёл интересные фичи (приёмы, трюки), которые можно сделать с моделями. 

В этой статье я расскажу о 7 улучшениях, которые каждый может применить в своём проекте в классах моделей.

Давайте создадим модели

Когда вы создаёте модель посредством командной строки вы моежет указать директорию, куда следует записать новый файл. Для этого необходимо всего лишь указать директорию перед названием модели. Лучше хранить все необходимые модели в отдельной папке, нежели в корне директории app.

php artisan make:model Models/Post

Этак команда создат модель Post в папке app\Models и запишет классу соответствующее пространство имён в соответствии со стандартом psr-4.

Приведение атрибутов

$casts свойство модели - удобный способ кастовать (или приводить) атрибуты к конкретным типам.

Например, когда вы обращаетесь к свойству, где у вас хранится bit(1) из mysql вы получаете единицу.  Если написать 

protected $casts = [
'is_published' => 'boolean'
];

То при обращении к этому свойству вы будете точно знать, что тип этого свойства boolean.

Также с помощью casts удобно работать с датами. Вместо того, чтобы писать

{{ $blog->created_at->format('Y-m-d') }} в темплейте, вы можете сделать код более удобным с помощью такой конструкции. Такая конструкция отобразит дату в формате Y-m-d, то есть "2020-02-25".

protected $casts = [
'published_at' => 'datetime:Y-m-d',
];

Когда вы обратитесь к этому свойству - получите строку с форматированной датой. В темплейте можно написать {{ $model->published_at }}

Видимость

Иногда когда мы преобразуем объект в массив(toArray) или json мы не хотим, чтобы эти атрибуты отображались в в результате. К примеру поле пароль. Мы может добавить к модели свойство $hidden

protected $hidden = [

'password'
];

Это свойство работает как список запрещённых к показу атрибутов. Также вы моежет наоброт использовать $visible для белого списка атрибутов. 

protected $visible = [
'first_name',
'last_name'
];

Когда это свойство указано, преобразуются только те свойства, которые указаны. Остальные ведут себя так, как будто они $hidden.

Аксессоры

Иногда вам нужно исполльзовать несколько атрибутов в одном, возможно, каким то образом комбинировать их. Для этого используются аксессоры - методы доступа к атрибутам.

примером может служить такая конструкция

$this->first_name. ' ' . $this->last_name;

Допустим мы хотим получать это выражение через свойство объекта $user->full_name.

Для этого необходимо назвать метод get<attrName>Attribute(). То есть в нашем случае

public function getFullNameAttribute() {
return "{$this->first_name} {$this->last_name}";
}

Обратите внимание на то, что доступ к свойству - с маленькой буквой и с подчёркиванием. А название метода - camelCase.


Мутаторы

Мутаторы это как аксессоры, только действуют наоборот. Через него можно не получить свойство, а задать, причём как-то по своему. Например мы хотим, чтобы у нас в имени всегда была строка, которая начинается с большой буквы.

public function setLastNameAttribute($value) {
$this->attributes['last_name'] = ucfirst($value);
}

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

Принцип именования тот же. get<attrName>Attribute(). Название атрибута в camelCase.

Добавление значений к выводу.

Вспомним метод toArray или toJson

По умолчанию метод не возвращает аксессоры и связи с другими моделями. Чтобы добавить в вывод аксессоры или связи (relations) мы можем воспользоваться свойством $appends модели.

$appends = [
'full_name'
];

Обратите внимание, что аттрибуты добавляются в змейка-регистре (snake case).

Давайте предположим, что модель User имеет связь с Blog через свойство user_id у модели Blog.

Тогда у пользователя будет следующая связь (модель User)

public function blogs() {
return $this->hasMany(App\Blog::class, 'user_id');
}

Чтобы вывести также это значение в массиве или json напишем в модели User

$appends = [
'full_name',
'blogs'
];

Связанная модель также имеет внутренние свойства. Мы можем при желании указать какие из свойств связанной модели добавить к выводу $user->toArray() таким образом

$appends = [
'full_name',
'blogs:id,title'
];


Трогательные моменты (Touches)

По умолчанию у моделей есть атрибуты created_at и updated_at, которые сигнализируют нам, когда модель была создана и когда изменена. Если мы изменяем модель, updated_at обновляется.

Допустим у на сесть комментарий к записи блога. Когда мы пишем новый комментарий, нам необходимо также обновлять updated_at у блога, чтобы, к примеру, сказать поисковой системе - наша страница с записью в блоге обновилась. 

Мы в комментарии можем указать, что нам нужно обновить поле updated_at через свойство $touches таким образом

class Comment extends Model
{
protected $touches = ['blog'];
public function blog()
{
return $this->belongsTo(App\Blog::class);
}
}

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


Все эти приёмы очень удобно использовать в повседневной разработке. Они облегчают восприятие и качество кода. Надеюсь Вам было