Unetway

Laravel - Eloquent

Вступление

Eloquent ORM, включенный в Laravel, обеспечивает красивую и простую реализацию ActiveRecord для работы с вашей базой данных. Каждая таблица базы данных имеет соответствующую «Модель», которая используется для взаимодействия с этой таблицей. Модели позволяют запрашивать данные в ваших таблицах, а также вставлять новые записи в таблицу.

Перед началом работы обязательно настройте соединение с базой данных в . Для получения дополнительной информации о настройке базы данных ознакомьтесь с документацией.config/database.php

 

Определение моделей

Для начала давайте создадим модель Eloquent. Модели обычно appнаходятся в каталоге, но вы можете разместить их в любом месте, которое может быть автоматически загружено в соответствии с вашим файлом. Все модели Eloquent расширяют класс.composer.jsonIlluminate\Database\Eloquent\Model

Самый простой способ создать экземпляр модели - использовать команду Artisan :make:model

php artisan make:model Flight

Если вы хотите создать миграцию базы данных при создании модели, вы можете использовать опцию --migrationили -m:

php artisan make:model Flight --migration

php artisan make:model Flight -m

 

Красноречивые модельные соглашения

Теперь давайте рассмотрим пример Flightмодели, которую мы будем использовать для извлечения и хранения информации из нашей flightsтаблицы базы данных:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    //
}

Имена таблиц

Обратите внимание, что мы не указали Eloquent, какую таблицу использовать для нашей Flightмодели. По соглашению, "случай змеи", имя класса во множественном числе будет использоваться в качестве имени таблицы, если явно не указано другое имя. Таким образом, в этом случае Eloquent предполагает, что Flightмодель хранит записи в flightsтаблице. Вы можете указать пользовательскую таблицу, определив tableсвойство в вашей модели:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'my_flights';
}

Основные ключи

Eloquent также предполагает, что каждая таблица имеет столбец первичного ключа с именем id. Вы можете определить защищенное $primaryKeyсвойство, чтобы переопределить это соглашение:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The primary key associated with the table.
     *
     * @var string
     */
    protected $primaryKey = 'flight_id';
}

Кроме того, Eloquent предполагает, что первичный ключ является возрастающим целочисленным значением, что означает, что по умолчанию первичный ключ будет автоматически приведен к int. Если вы хотите использовать неинкрементный или нечисловой первичный ключ, вы должны установить открытое $incrementingсвойство вашей модели false:

<?php

class Flight extends Model
{
    /**
     * Indicates if the IDs are auto-incrementing.
     *
     * @var bool
     */
    public $incrementing = false;
}

Если ваш первичный ключ не является целым числом, вы должны установить для защищенного $keyTypeсвойства вашей модели string:

<?php

class Flight extends Model
{
    /**
     * The "type" of the auto-incrementing ID.
     *
     * @var string
     */
    protected $keyType = 'string';
}

Timestamps

По умолчанию, Красноречивым ожидает created_atи updated_atстолбцов существовать на ваших столах. Если вы не хотите, чтобы Eloquent автоматически управлял этими столбцами, установите для $timestampsсвойства вашей модели false:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;
}

Если вам нужно настроить формат ваших временных меток, установите $dateFormatсвойство для вашей модели. Это свойство определяет, как атрибуты даты хранятся в базе данных, а также их формат при сериализации модели в массив или JSON:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

Если вам необходимо настроить имена столбцов , используемых для хранения временных меток, вы можете установить CREATED_ATи UPDATED_ATконстанты в модели:

<?php

class Flight extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'last_update';
}

Подключение к базе данных

По умолчанию все модели Eloquent будут использовать соединение с базой данных по умолчанию, настроенное для вашего приложения. Если вы хотите указать другое соединение для модели, используйте $connectionсвойство:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The connection name for the model.
     *
     * @var string
     */
    protected $connection = 'connection-name';
}

 

Значения атрибутов по умолчанию

Если вы хотите определить значения по умолчанию для некоторых атрибутов вашей модели, вы можете определить $attributesсвойство вашей модели:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The model's default values for attributes.
     *
     * @var array
     */
    protected $attributes = [
        'delayed' => false,
    ];
}

 

Получение моделей

Создав модель и связанную с ней таблицу базы данных , вы готовы начать извлечение данных из вашей базы данных. Думайте о каждой модели Eloquent как о мощном конструкторе запросов,позволяющем свободно выполнять запросы к таблице базы данных, связанной с моделью. Например:

<?php

$flights = App\Flight::all();

foreach ($flights as $flight) {
    echo $flight->name;
}

Добавление дополнительных ограничений

Метод Eloquent allвозвращает все результаты в таблице модели. Поскольку каждая модель Eloquent служит построителем запросов , вы также можете добавить ограничения к запросам, а затем использовать getметод для получения результатов:

$flights = App\Flight::where('active', 1)
               ->orderBy('name', 'desc')
               ->take(10)
               ->get();

Поскольку модели Eloquent являются построителями запросов, вам следует просмотреть все методы, доступные в построителе запросов . Вы можете использовать любой из этих методов в своих Eloquent запросах.

Обновление моделей

Вы можете обновить модели , используя freshи refreshметоды. freshМетод будет повторно извлечь модель из базы данных. Существующий экземпляр модели не будет затронут:

$flight = App\Flight::where('number', 'FR 900')->first();

$freshFlight = $flight->fresh();

refreshМетод будет повторно гидратировать существующую модель с использованием свежих данных из базы данных. Кроме того, будут обновлены все загруженные отношения:

$flight = App\Flight::where('number', 'FR 900')->first();

$flight->number = 'FR 456';

$flight->refresh();

$flight->number; // "FR 900"

 

Коллекции

Для методов Eloquent, таких как allи getкоторые получают несколько результатов, будет возвращен экземпляр . Класс предоставляет множество полезных методов для работы с вашими красноречивыми результатами:Illuminate\Database\Eloquent\CollectionCollection

$flights = $flights->reject(function ($flight) {
    return $flight->cancelled;
});

Вы также можете перебрать коллекцию как массив:

foreach ($flights as $flight) {
    echo $flight->name;
}

 

Результаты Chunking

Если вам нужно обработать тысячи записей Eloquent, используйте chunkкоманду. chunkМетод извлечения «кусок» красноречивых моделей, кормя их данность Closureдля обработки. Использование chunkметода сэкономит память при работе с большими наборами результатов:

Flight::chunk(200, function ($flights) {
    foreach ($flights as $flight) {
        //
    }
});

Первым аргументом, передаваемым методу, является количество записей, которые вы хотите получить за «порцию». Закрытие, переданное в качестве второго аргумента, будет вызываться для каждого чанка, полученного из базы данных. Будет выполнен запрос к базе данных для извлечения каждого куска записей, переданных в Closure.

Использование курсоров

Этот cursorметод позволяет перебирать записи базы данных с помощью курсора, который будет выполнять только один запрос. При обработке больших объемов данных этот cursorметод может быть использован для значительного сокращения использования памяти:

foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
    //
}

 

Получение одиночных моделей / агрегатов

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

// Retrieve a model by its primary key...
$flight = App\Flight::find(1);

// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();

Вы также можете вызвать findметод с массивом первичных ключей, который вернет коллекцию соответствующих записей:

$flights = App\Flight::find([1, 2, 3]);

Исключения не найдены

Иногда вы можете выбросить исключение, если модель не найдена. Это особенно полезно в маршрутах или контроллерах. Эти findOrFailи firstOrFailметоды будут извлекать первый результат запроса; однако, если результат не будет найден, будет выдано:Illuminate\Database\Eloquent\ModelNotFoundException

$model = App\Flight::findOrFail(1);

$model = App\Flight::where('legs', '>', 100)->firstOrFail();

Если исключение не перехвачено, 404ответ HTTP автоматически отправляется обратно пользователю. Нет необходимости писать явные проверки для возврата 404ответов при использовании этих методов:

Route::get('/api/flights/{id}', function ($id) {
    return App\Flight::findOrFail($id);
});

 

Получение агрегатов

Вы также можете использовать countsummax, и другие агрегатные методы , предоставляемые построитель запросов . Эти методы возвращают соответствующее скалярное значение вместо полного экземпляра модели:

$count = App\Flight::where('active', 1)->count();

$max = App\Flight::where('active', 1)->max('price');

 

Вставка и обновление моделей

Вставки

Чтобы создать новую запись в базе данных, создайте новый экземпляр модели, установите атрибуты для модели, затем вызовите saveметод:

<?php

namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class FlightController extends Controller
{
    /**
     * Create a new flight instance.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate the request...

        $flight = new Flight;

        $flight->name = $request->name;

        $flight->save();
    }
}

В этом примере мы присваиваем nameпараметр из входящего HTTP-запроса nameатрибуту экземпляра модели. Когда мы вызываем метод, запись будет вставлена ​​в базу данных. И временные метки автоматически устанавливается , когда вызывается метод, поэтому нет необходимости устанавливать их вручную.App\Flightsavecreated_atupdated_atsave

 

Обновления

Этот saveметод также можно использовать для обновления моделей, которые уже существуют в базе данных. Чтобы обновить модель, вы должны извлечь ее, установить любые атрибуты, которые вы хотите обновить, а затем вызвать saveметод. Опять же, updated_atотметка времени будет автоматически обновлена, поэтому нет необходимости вручную устанавливать ее значение:

$flight = App\Flight::find(1);

$flight->name = 'New Flight Name';

$flight->save();

Массовые обновления

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

App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]);

updateМетод ожидает массив столбцов и пар значений , представляющих столбцы , которые должны быть обновлены.

При выпуске массового обновления через красноречивый, в savingsavedupdatingи updatedмодель событий , не будет срабатывать для обновленных моделей. Это связано с тем, что модели никогда не извлекаются при массовом обновлении.

 

Массовое задание

Вы также можете использовать createметод для сохранения новой модели в одну строку. Вставленный экземпляр модели будет возвращен вам из метода. Однако, прежде чем сделать это, вам нужно будет указать в модели fillableлибо guardedатрибут a, либо атрибут, так как все модели Eloquent по умолчанию защищают от массового назначения.

Уязвимость массового назначения возникает, когда пользователь передает неожиданный параметр HTTP через запрос, и этот параметр изменяет столбец в вашей базе данных, которого вы не ожидали. Например, злонамеренный пользователь может отправить is_adminпараметр через HTTP-запрос, который затем передается в createметод вашей модели , позволяя пользователю повысить себя до администратора.

Итак, для начала вы должны определить, какие атрибуты модели вы хотите сделать массовыми назначаемыми. Вы можете сделать это, используя $fillableсвойство модели. Например, давайте сделаем nameатрибут массы нашей Flightмодели назначаемым:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

После того, как мы сделали атрибуты массово назначаемыми, мы можем использовать createметод для вставки новой записи в базу данных. createМетод возвращает сохраненный экземпляр модели:

$flight = App\Flight::create(['name' => 'Flight 10']);

Если у вас уже есть экземпляр модели, вы можете использовать fillметод, чтобы заполнить его массивом атрибутов:

$flight->fill(['name' => 'Flight 22']);

Атрибуты охраны

Хотя он $fillableслужит «белым списком» атрибутов, которые должны быть массово назначаемыми, вы также можете использовать их $guarded$guardedСвойство должно содержать массив атрибутов , которые не хотят быть массой переуступки. Все остальные атрибуты, отсутствующие в массиве, будут массово назначаться. Итак, $guardedфункционирует как «черный список». Важно отметить, что вы должны использовать либо $fillableили $guarded- не оба. В приведенном ниже примере все атрибуты, кроме,price будут массово назначаться:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = ['price'];
}

Если вы хотите сделать все атрибуты массово назначаемыми, вы можете определить $guardedсвойство как пустой массив:

/**
 * The attributes that aren't mass assignable.
 *
 * @var array
 */
protected $guarded = [];

 

Другие методы создания

firstOrCreatefirstOrNew

Есть два других метода, которые вы можете использовать для создания моделей путем массового присвоения атрибутов: firstOrCreateи firstOrNewfirstOrCreateМетод попытается найти запись в базе данных , используя данные пары столбец / значение. Если модель не может быть найдена в базе данных, будет вставлена ​​запись с атрибутами из первого параметра, а также с атрибутами во втором необязательном параметре.

firstOrNewМетод, как firstOrCreateбудет пытаться найти запись в базе данных , соответствующую заданные атрибуты. Однако, если модель не найдена, будет возвращен новый экземпляр модели. Обратите внимание, что возвращенная модель firstOrNewеще не была сохранена в базе данных. Вам нужно будет позвонить saveвручную, чтобы сохранить это:

// Retrieve flight by name, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// Retrieve flight by name, or create it with the name, delayed, and arrival_time attributes...
$flight = App\Flight::firstOrCreate(
    ['name' => 'Flight 10'],
    ['delayed' => 1, 'arrival_time' => '11:30']
);

// Retrieve by name, or instantiate...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

// Retrieve by name, or instantiate with the name, delayed, and arrival_time attributes...
$flight = App\Flight::firstOrNew(
    ['name' => 'Flight 10'],
    ['delayed' => 1, 'arrival_time' => '11:30']
);

updateOrCreate

Вы также можете столкнуться с ситуациями, когда вы хотите обновить существующую модель или создать новую модель, если она не существует. Laravel предлагает updateOrCreateметод, позволяющий сделать это за один шаг. Как и firstOrCreateметод, updateOrCreateсохраняется модель, поэтому нет необходимости вызывать :save()

// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99, 'discounted' => 1]
);

 

Удаление моделей

Чтобы удалить модель, вызовите deleteметод для экземпляра модели:

$flight = App\Flight::find(1);

$flight->delete();

Удаление существующей модели по ключу

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

App\Flight::destroy(1);

App\Flight::destroy(1, 2, 3);

App\Flight::destroy([1, 2, 3]);

App\Flight::destroy(collect([1, 2, 3]));

Удаление моделей по запросу

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

$deletedRows = App\Flight::where('active', 0)->delete();

При выполнении оператора массового удаления через Eloquent события deletingи deletedмодели не будут запускаться для удаленных моделей. Это связано с тем, что модели никогда не извлекаются при выполнении оператора delete.

 

Мягкое удаление

В дополнение к фактическому удалению записей из вашей базы данных, Eloquent также может «мягко удалять» модели. Когда модели мягко удаляются, они фактически не удаляются из вашей базы данных. Вместо этого deleted_atатрибут устанавливается на модель и вставляется в базу данных. Если модель имеет ненулевое deleted_atзначение, она была удалена. Чтобы включить мягкое удаление для модели, используйте черту на модели:Illuminate\Database\Eloquent\SoftDeletes

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;
}

SoftDeletesЧерта будет автоматически бросить deleted_atатрибут к DateTimeCarbonнапример , для вас.

Вы также должны добавить deleted_atстолбец в таблицу базы данных. Конструктор схемыLaravel содержит вспомогательный метод для создания этого столбца:

Schema::table('flights', function (Blueprint $table) {
    $table->softDeletes();
});

Теперь, когда вы вызываете deleteметод для модели, в deleted_atстолбце будут установлены текущие дата и время. И, при запросе модели, которая использует мягкое удаление, мягко удаленные модели будут автоматически исключены из всех результатов запроса.

Чтобы определить, был ли данный экземпляр модели удален, используйте trashedметод:

if ($flight->trashed()) {
    //
}

 

Запрос мягких удаленных моделей

Включая мягко удаленные модели

Как отмечалось выше, мягко удаленные модели будут автоматически исключены из результатов запроса. Однако вы можете принудительно отобразить удаленные модели в наборе результатов, используя withTrashedметод запроса:

$flights = App\Flight::withTrashed()
                ->where('account_id', 1)
                ->get();

withTrashedСпособ также может быть использован на отношения запроса:

$flight->history()->withTrashed()->get();

Получение только мягко удаленных моделей

onlyTrashedМетод будет получать только мягкие удаленные модели:

$flights = App\Flight::onlyTrashed()
                ->where('airline_id', 1)
                ->get();

Восстановление мягко удаленных моделей

Иногда вы можете захотеть «удалить» мягко удаленную модель. Чтобы восстановить мягко удаленную модель в активное состояние, используйте restoreметод для экземпляра модели:

$flight->restore();

Вы также можете использовать restoreметод в запросе для быстрого восстановления нескольких моделей. Опять же, как и другие «массовые» операции, это не вызовет никаких событий модели для восстанавливаемых моделей:

App\Flight::withTrashed()
        ->where('airline_id', 1)
        ->restore();

Как и withTrashedметод, restoreметод также может быть использован для отношений :

$flight->history()->restore();

Удаление моделей без возможности восстановления

Иногда вам может понадобиться действительно удалить модель из вашей базы данных. Чтобы окончательно удалить мягко удаленную модель из базы данных, используйте forceDeleteметод:

// Force deleting a single model instance...
$flight->forceDelete();

// Force deleting all related models...
$flight->history()->forceDelete();

 

Области запросов

Global Scopes

Глобальные области позволяют вам добавлять ограничения ко всем запросам для данной модели. Собственная функциональность мягкого удаления Laravel использует глобальные области для извлечения только «не удаленных» моделей из базы данных. Написание собственных глобальных областей может обеспечить удобный и простой способ убедиться, что каждый запрос для данной модели получает определенные ограничения.

Написание глобальных областей

Написание глобальной области просто. Определите класс, который реализует интерфейс. Этот интерфейс требует, чтобы реализовать один метод: . Метод может добавить ограничения на запрос в случае необходимости:Illuminate\Database\Eloquent\Scopeapplyapplywhere

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('age', '>', 200);
    }
}

Если ваша глобальная область добавляет столбцы к предложению select запроса, вы должны использовать addSelectметод вместо select. Это предотвратит непреднамеренную замену существующего предложения select в запросе.

Применение глобальных областей

Чтобы назначить глобальную область видимости модели, вы должны переопределить bootметод данной модели и использовать addGlobalScopeметод:

<?php

namespace App;

use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(new AgeScope);
    }
}

После добавления области, запрос к будет производить следующий SQL:User::all()

select * from `users` where `age` > 200

Анонимные Глобальные Области

Eloquent также позволяет вам определять глобальные области, используя Closures, что особенно полезно для простых областей, которые не требуют отдельного класса:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class User extends Model
{
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('age', function (Builder $builder) {
            $builder->where('age', '>', 200);
        });
    }
}

Удаление глобальных областей

Если вы хотите удалить глобальную область для данного запроса, вы можете использовать withoutGlobalScopeметод. Метод принимает имя класса глобальной области видимости в качестве единственного аргумента:

User::withoutGlobalScope(AgeScope::class)->get();

Или, если вы определили глобальную область с помощью Closure:

User::withoutGlobalScope('age')->get();

Если вы хотите удалить несколько или даже все глобальные области, вы можете использовать withoutGlobalScopesметод:

// Remove all of the global scopes...
User::withoutGlobalScopes()->get();

// Remove some of the global scopes...
User::withoutGlobalScopes([
    FirstScope::class, SecondScope::class
])->get();

 

Местные возможности

Локальные области позволяют вам определять общие наборы ограничений, которые вы можете легко повторно использовать в своем приложении. Например, вам может понадобиться часто получать всех пользователей, которые считаются «популярными». Чтобы определить область, добавьте префикс метода модели Eloquent с помощью scope.

Области должны всегда возвращать экземпляр построителя запросов:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include popular users.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

    /**
     * Scope a query to only include active users.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

Использование локальной области

После определения области вы можете вызывать методы области при запросе модели. Однако вы не должны включать scopeпрефикс при вызове метода. Вы можете даже соединять вызовы в различные области, например:

$users = App\User::popular()->active()->orderBy('created_at')->get();

Объединение нескольких областей Eloquent модели с помощью orоператора запроса может потребовать использования обратных вызовов Closure:

$users = App\User::popular()->orWhere(function (Builder $query) {
    $query->active();
})->get();

Тем не менее, поскольку это может быть громоздким, Laravel предоставляет orWhereметод «более высокого порядка», который позволяет свободно объединять эти области вместе без использования Closures:

$users = App\User::popular()->orWhere->active()->get();

Динамические Области

Иногда вы можете захотеть определить область, которая принимает параметры. Чтобы начать, просто добавьте ваши дополнительные параметры в вашу область. Параметры области должны быть определены после $queryпараметра:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include users of a given type.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @param  mixed  $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

Теперь вы можете передать параметры при вызове области:

$users = App\User::ofType('admin')->get();

 

Сравнение моделей

Иногда вам может понадобиться определить, являются ли две модели «одинаковыми». Этот isметод можно использовать для быстрой проверки того, что две модели имеют одинаковый первичный ключ, таблицу и соединение с базой данных:

if ($post->is($anotherPost)) {
    //
}

 

События

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

retrievedСобытие срабатывает , когда существующая модель извлекается из базы данных. Когда новая модель сохраняется в первый раз, creatingи createdсобытия будут стрелять. Если модель уже существует в базе данных и saveметод вызывается, события updatingupdatedбудут срабатывать. Однако в обоих случаях события savingsavedбудут срабатывать.

При выпуске массового обновления через Eloquent события savedи updatedмодели не будут запускаться для обновленных моделей. Это связано с тем, что модели никогда не извлекаются при массовом обновлении.

Чтобы начать, определите $dispatchesEventsсвойство в своей модели Eloquent, которое отображает различные точки жизненного цикла модели Eloquent на ваши собственные классы событий :

<?php

namespace App;

use App\Events\UserSaved;
use App\Events\UserDeleted;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The event map for the model.
     *
     * @var array
     */
    protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}

После определения и сопоставления событий Eloquent вы можете использовать обработчики событий для обработки событий.

 

Наблюдатели

Определение наблюдателей

Если вы слушаете много событий в данной модели, вы можете использовать наблюдателей, чтобы сгруппировать всех ваших слушателей в один класс. Классы наблюдателей имеют имена методов, которые отражают события Eloquent, которые вы хотите прослушивать. Каждый из этих методов получает модель в качестве единственного аргумента. Команда Artisan - это самый простой способ создать новый класс наблюдателей:make:observer

php artisan make:observer UserObserver --model=User

Эта команда поместит нового наблюдателя в ваш каталог. Если этот каталог не существует, Artisan создаст его для вас. Ваш новый наблюдатель будет выглядеть следующим образом:App/Observers

<?php

namespace App\Observers;

use App\User;

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function created(User $user)
    {
        //
    }

    /**
     * Handle the User "updated" event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function updated(User $user)
    {
        //
    }

    /**
     * Handle the User "deleted" event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function deleted(User $user)
    {
        //
    }
}

Чтобы зарегистрировать наблюдателя, используйте observeметод на модели, которую вы хотите наблюдать. Вы можете зарегистрировать наблюдателей по bootметоду одного из ваших поставщиков услуг. В этом примере мы зарегистрируем наблюдателя в AppServiceProvider:

<?php

namespace App\Providers;

use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        User::observe(UserObserver::class);
    }
}