В силу того, что модели Eloquent являются конструкторами запросов, вам следует пересмотреть
все методы доступны для конструктора запросов.
Вы можете использовать любой из этих методов в ваших запросах Eloquent.
Elequent ORM. Введение.
Содержание:
- Введение
- Определение моделей
- Получение моделей
- Получение отдельных моделей / агрегатов
- Вставка и обновление моделей
- Удаление моделей
- Условия запросов
- Сравнение моделей
- События
Введение
Включённая в базовую сборку фреймворка Eloquent ORM предоставляет простую, красивую реализацию ActiveRecord для работы с вашей базой данных. Каждая таблица имеет соотвествующую "Model", которая используется для взаимодействия с таблицей. Модели позволяют вам как делать запросы для получения данных в таблицы, также как и для внесения новых записей в таблицу.
Убедитесь, что настроили соединение базы данных в config/database.php
.
Для большей информации для вашей базы данных, обратитесь к соответсвующему разделу
документации.
Определение моделей
Для начала, давайте создадим модель Eloquent. Модели располагаются в папке app
, но вы можете
легко поместить их в любом месте, и подхватить их автозагрузчиком, согласно вашего файла composer.json
.
Все модели Eloquent расшираяют класс Illuminate\Database\Eloquent\Model
.
Самый просто способ создать экземпляр модели — это используя команду Артезан make:model
:
php artisan make:model Flight
Если вы хотите сгенерировать также миграцию базы данных при создании модели, то вы можете
использовать опцию --migration
или сокращённую версию -m
:
php artisan make:model Flight --migration
php artisan make:model Flight -m
Конвенции модели Eloquent
Теперь давайте взглянем на пример модели Flight
, которая будет использованы для
получения и хранения информации из вашей таблицы базы данных flights
:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
//
}
Имена таблицы
Надо заметить, что мы не указали Eloquent какую таблицу необходимо использовать для модели Flight
.
По умолчанию используется имя класса в качестве имени таблицы путём преобразования в множественное число и соединения
через нижнее подчёркивание, но только до того момента, пока не будет явно указано другое имя таблицы.
Поэтому, в этом случае для модели 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
. Если вы хотите использовать
неинкрементный или нечисловой первичный ключ, вы должны установить значение как false
для публичного свойства модели $incrementing
:
<?php
class Flight extends Model
{
/**
* Indicates if the IDs are auto-incrementing.
*
* @var bool
*/
public $incrementing = false;
}
Если ваш первичный ключ не integer, вам необходимо установить свойство $keyType
для вашей модели как string
:
<?php
class Flight extends Model
{
/**
* The "type" of the auto-incrementing ID.
*
* @var string
*/
protected $keyType = 'string';
}
Временные метки
По умолчанию, Eloquent ожидает, что столбцы 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();
Обновление моделей
Вы можете обновить модели используя методы 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\Collection
. Класс Collection
предоставляет набор полезных методов
для работы с вашими результатами Eloquent:
$flights = $flights->reject(function ($flight) {
return $flight->cancelled;
});
Вы можете также перебирать элементы коллекции как массив:
foreach ($flights as $flight) {
echo $flight->name;
}
Разбиение результатов на части
Если вам необходимо обработать тысячи записей Eloquent, используйте команду chunk
.
Метод chunk
будет получать "часть" моделей Eloquent, отправляя их
в предоставленное замыкание
для обработки. Исопльзуя метод chunk
вы сможете
сэкономить большой объём памяти при работе с большим набором результатов:
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
Первый аргумент передаваемый в метод — это число записей, которые вы хотите получать за каждую "часть". Замыкание, передаваемое в качестве второго аргумента, будет вызываться для каждой части из набора резузльтатов из бд. Запрос бд будет выплняться для получения каждой части записей, передаваемых в Замыкание.
Использование курсоров
Метод cursor
позволяет вам проводить итерации через записи базы данных
используя курсоры, которые будет выполнять только одиночный запросы. При использовании
больших объёмов данных, метод cursor
может быть использован для значительного
снижения использования вашей памяти:
foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
//
}
Метод cursor
возвращает экземпляр
Illuminate\Support\LazyCollection
"ленивой коллекции" позволяя вам использовать
большинство методов доступных для типовой коллекции Laravel, в то время как загружаете одиночную
модель в память за единицу времени:
$users = App\User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}
Сложные подзапросы
Подзапросы Selects
Eloquent также предлагает расширенную поддержку подзапросов, что позволяет вам
получать информацию из связанных таблиц в одиночном запросе. Например, давайте представим,
что у нас есть таблицы рейсов и назначений: destinations
и flights
.
Таблица flights
содержит стобец arrived_at
, который показывает
время прибытия в пункт назначения.
Используя функциональность подзапросов доступных для методов select
и addSelect
,
мы можем выбрать все назначения и имена уже прибывших полётов для данного назначения используя
одиночный запрос:
use App\Destination;
use App\Flight;
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
])->get();
Порядок для подзапросов
Дополнительно, функция констуктора запросов orderBy
поддерживает подзапросы.
Мы можем использовать эту функциональность для сортировку всех пунктов прибытия основываясь на
времени прибытия последнего рейса в пункт назначения. Опять же, это можно сделать путём выполнения
одиночных запросов к базе данных:
return Destination::orderByDesc(
Flight::select('arrived_at')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
)->get();
Получение отдельных моделей / агрегатов
Дополнительно к получению всех записей для данной таблицы, вы можете также получить одиночные
записи используя метод code>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();
Если исключение не обработано, ответ HTTP 404
будет автоматически отсылаться назад
пользователю. Нет необходимости писать явные проверки, чтобы вернуть ответ 404
при использовании этих методов:
Route::get('/api/flights/{id}', function ($id) {
return App\Flight::findOrFail($id);
});
Получение агрегатов
Вы можете также использовать count
, sum
, max
,
и другие методы агрегатов
предоставляемые
конструктором запросов.
Эти методы вернут соответствующее скалярное значение вместо полного экземпляра модели:
$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');
Вставка и обновление моделей
Вставка
Для создания новой записи в базе данных, создайте экземпляр новой модели,
установите желаемые атрибуты, а потом вызовите метод save
:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Flight;
use Illuminate\Http\Request;
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\Flight
. Когда мы вызыаем метод
save
, запись будет вставлена в базу данных. Метки времени created_at
и
updated_at
будут автоматически установлены, при вызове метода save
,
поэтому нет необходимости устанавливать их вручную.
Обновления
Метод 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
ожидает массив столбцов и значений, представляющих столбцы,
которые быть обновлены.
Массовое назначение
Вы можете также использовать метод create
для сохранения новой модели в одну строку.
Вставленный экземпляр модели вернётся вам из метода. Однако, перед тем, как сделать так,
вам необходимо указать fillable
или guarded
атрибут для модели,
так как все модели 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
выступает в качестве "чёрного списка" атрибутов.
Важно, чтобы вы использовали или $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 = [];
Другие методы создания
firstOrCreate
/ firstOrNew
Есть 2 других метода, вы можете использовать для создания моделей через массовае назначение:
firstOrCreate
и firstOrNew
. Метод firstOrCreate
попытается найти запись базы данных используя данную пару столбец / значение. Если модель
не будет найдена в базе данных, запись будет вставлена с атрибутами из первого параметра,
вместе с теми, что указаны в необязательном втором параметре.
Метод 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
Вы также можете столкнуться с ситуацией, когда вам необходимо обновить существующую модель
или создать новую, если такой не существует. Ларавел предоставляет метод 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 также может "мягко удалять" модели.
Когда модели мягко удаляются, их не убирают из базы данных. Вместо этого, для модели устанавливается
атрибут deleted_at
и вставляется в базу данных. Если модель имеет значение не-null для
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;
}
Вам также необходимо добавить столбец 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();
Условия запросов
Глобальные ограничения
Глобальные рамки позволяют вам добавлять условия для всех запросов для данной модели. Функциональность Ларавел для мягкого удаления использует глобальные рамки, чтобы получать неудалённые модели из базы данных. Написание ваших глобальных ограничений может предоставить удобный и простой способ добавить ограничеиня для каждого запроса для данной модели.
Установление глобальных рамок
Написать глобальное ограничение просто. Необходимо определить класс, который расширяет интерфейс
Illuminate\Database\Eloquent\Scope
. Этот интерфейс требует от вас расширать
единственный метод apply
. Метод apply
может добавить условия
where
в запрос как это и необходимо:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
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);
}
}
Применение глобальных ограничений
Чтобы приписать глобальное ограничение к модели, вам необходимо переписать данный метод
модели 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);
}
}
После добавления ограничения, запрос User::all()
сделает следующий SQL:
select * from `users` where `age` > 200
Анонимные глобальные ограничения
Eloquent также позволяет вам определить глобальные ограничения используя Замыкание, что может быть полезно для простых ограничений, которые не требуют отдельного класса:
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
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('age', function (Builder $builder) {
$builder->where('age', '>', 200);
});
}
}
Удаление глобальных ограничеинй
Если вы хоите удалить глобальное ограничение для данного запроса, вы можете использовать
метод withoutGlobalScope
. Этот метод принимает имя класса глобального ограничения
как единственный аргумент:
User::withoutGlobalScope(AgeScope::class)->get();
Или, если вы определили глобальное ограничения используя Замыкание:
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();
Локальные ограничения
Локальные ограничения позволяют вам определить общие наборы ограничений, которые вы можете
повторно использовать для разных разделов вашего приложения. Например, вам может понадобиться
часто получать всех пользователей, которые счиатаются "популярными". Для определения ограничения,
добавьте префикс scope
для метода модели Eloquent.
Ограничения должны всегда возвращать экземпляр конструктора запросов:
<?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
может потребовать использование Замыкания как обратной связи:
$users = App\User::popular()->orWhere(function (Builder $query) {
$query->active();
})->get();
Такое использование может быть слишком громоздко, поэтому Ларавел предоставляет "более высокий порядок"
метод orWhere
, который позволяет вам быстро добавлять цепочкой ограничения вместе
без использования Замыкания:
$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)) {
//
}
Наблюдатели
Модели Eloquent запускают некоторые события, что позволяет вам перенестись на определённую точку
жизненного цикла модели: retrieved
, creating
, created
, updating
,
updated
, saving
, saved
, deleting
,
deleted
, restoring
, restored
. События позволяют вам легко выполнить
код каждый раз, когда указанный класс модели сохраняется или обновляется в базе данных.
Каждое событие получает экземпляр модели через его конструктор.
Событе retrieved
будет запущено, когда существующая модель получена из базы данных.
Когда новая модель сохраняет в первый раз, события creating
и created
будут запущены. Если модель уже существует в базе данных и вызывается метод save
,
события updating
/ updated
будут запущены. Однако, в обоих случаях,
события saving
/ saved
будут запущены.
Для начала, определите свойство $dispatchesEvents
для вашей модели Eloquent,
которое покажет набор различных точек жизненного цикла модели Eloquent к вашим собственныы
классам событий:
<?php
namespace App;
use App\Events\UserDeleted;
use App\Events\UserSaved;
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, вы можете использовать слушателей событий, чтобы обрабатывать события.