Quick start
Eloquent: Getting Started
- Introduction
- Model Definition
- Model retrieval
- Retrieve a single model/collection
- Insert & Update Model
- Delete model
- Query scope
- ##Model comparison
- Event
Laravel's Eloquent ORM provides a beautiful, concise ActiveRecord implementation to interact with the database. Each database table has a corresponding "model" used to interact with the table. You can query data in the data table through the model and insert new records into the data table.
Before you begin, make sure you configure your database connection in
config/database.php. For more information on database configuration, check out the documentation.
First, create an Eloquent model. Models are usually in the
app directory, but you can place them anywhere where they can be automatically loaded based on the composer.json
file. All Eloquent models inherit from the Illuminate\Database\Eloquent\Model
class. The easiest way to create a model is to use
Artisan command:
If you want to generate database migration when generating the model, you can use php artisan make:model Flight
or -m
Options: php artisan make:model Flight --migration
php artisan make:model Flight -m
Flight
model that we will use to retrieve and store data information from theflights database table:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ // }
Data table name
Please note that we do not tell Eloquent which data table to use for our Flight
model. Unless another name is explicitly specified, the plural form of class, "snakes", will be used as the table name. Therefore, in this case, Eloquent will assume that the Flight
model stores data from the flights
data table. You can specify a custom data table by defining the table
attribute on the model:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 与模型关联的表名 * * @var string */ protected $table = 'my_flights'; }
Primary key
Eloquent will also assume that each data table There is a primary key column named id
. You can define a protected $primaryKey
property to override the convention.
Additionally, Eloquent assumes that the primary key is an auto-incrementing integer value, which means that the primary key is automatically converted to the int
type by default. If you wish to use a non-increasing or non-numeric primary key you need to set the public $incrementing
property to false
. If your primary key is not an integer, you need to set the protected $keyType
property on the model to string
.
Timestamp
By default, Eloquent expects created_at
and updated_at
to exist in your data table. If you do not want Eloquent to automatically manage these two columns, please set the $timestamps
attribute in the model to false
:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 指示模型是否自动维护时间戳 * * @var bool */ public $timestamps = false; }
If you need to customize the timestamps Format, set the $dateFormat
property in your model. This attribute determines how the date attribute is stored in the database, and the format in which the model is serialized into an array or JSON:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 模型日期列的存储格式。 * * @var string */ protected $dateFormat = 'U'; }
If you need to customize the field name for storing timestamps, you can set CREATED_AT in the model
and UPDATED_AT
constant values to implement:
<?php class Flight extends Model{ const CREATED_AT = 'creation_date'; const UPDATED_AT = 'last_update'; }
Database Connection
By default, the Eloquent model will be used by your application Configured default database connection. If you want to specify a different connection for the model, set the $connection
property:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 模型的连接名称 * * @var string */ protected $connection = 'connection-name'; }
Default property value
If you want to define default values for some attributes of the model, you can define $attributes
attributes on the model:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 模型的默认属性值。 * * @var array */ protected $attributes = [ 'delayed' => false, ]; }
Model Retrieval
After creating the model and its associated database table, you can query data from the database. Think of each Eloquent model as a powerful query builder that you can use to query its associated data table more quickly. For example:
<?php $flights = App\Flight::all(); foreach ($flights as $flight) { echo $flight->name; }
Additional constraints
Eloquent’s all
method will return all results in the model. Since each Eloquent model acts as a query builder, you can also add query conditions and then use the get
method to get the query results:
$flights = App\Flight::where('active', 1) ->orderBy('name', 'desc') ->take(10) ->get();
{tip} Because the Eloquent model is also a query builder, so you should also read about all the methods available to the query builder. You can use these methods in Eloquent queries.
Reload the model
You can reload the model using the fresh
and refresh
methods. fresh
The method will retrieve the model from the database again. Existing model instances are not affected: The
$flight = App\Flight::where('number', 'FR 900')->first(); $freshFlight = $flight->fresh();
refresh
method reassigns an existing model with new data from the database. In addition, already loaded relationships will be reloaded:
$flight = App\Flight::where('number', 'FR 900')->first(); $flight->number = 'FR 456';$flight->refresh(); $flight->number; // "FR 900"
Collection
For in Eloquent The all
and get
methods can query multiple results and return an Illuminate\Database\Eloquent\Collection
instance. The Collection
class provides a number of helper functions to handle Eloquent results:
$flights = $flights->reject(function ($flight) { return $flight->cancelled; });
You can iterate over the collection like an array:
foreach ($flights as $flight) { echo $flight->name; }
Chunking results
If you need to process thousands of Eloquent results, use the chunk
command. The chunk
method retrieves the "chunks" in the Eloquent model and provides them to the specified Closure
for processing. When processing large result sets, use the chunk
method to save memory:
Flight::chunk(200, function ($flights) { foreach ($flights as $flight) { // } });
The first parameter passed to the method is the amount of data you want each "chunk" to receive. The closure is passed as the second parameter and is called each time a chunk is retrieved from the database. It will execute the database query and pass the retrieved chunked results to the closure method.
Using Cursors
cursor
method allows you to traverse the database using a cursor, which only executes the query once. When processing large amounts of data, the cursor
method can greatly reduce memory usage:
foreach (Flight::where('foo', 'bar')->cursor() as $flight) { // }
Retrieve a single model / Collection
In addition to retrieving all records from the specified data table, you can use the find
or first
method to retrieve a single record. These methods return a single model instance rather than a collection of models:
// 通过主键检索一个模型... $flight = App\Flight::find(1); // 检索符合查询限制的第一个模型... $flight = App\Flight::where('active', 1)->first();
You can also call the find
method with an array of primary keys as a parameter, which will return a collection of matching records:
$flights = App\Flight::find([1, 2, 3]);
『Not Found』Exception
Sometimes you want to throw an exception when the model is not found. This is very useful in controllers and routing. The findOrFail
and firstOrFail
methods will retrieve the first result of the query, if not found, will throw Illuminate\Database\Eloquent\ModelNotFoundException
Exception:
$model = App\Flight::findOrFail(1); $model = App\Flight::where('legs', '>', 100)->firstOrFail();
If the exception is not caught, a 404
response will be automatically returned to the user. That is, when using these methods, there is no need to write a check to return 404
Response: :
Route::get('/api/flights/{id}', function ($id) { return App\Flight::findOrFail($id); });
Retrieve a collection
You can also use the count
, sum
, max
, and other aggregate functions provided by the query builder. These methods will simply return the appropriate scalar value instead of a model instance:
$count = App\Flight::where('active', 1)->count(); $max = App\Flight::where('active', 1)->max('price');##Insert & Update ModelInsertTo add a new record to the database, first create a new model instance, set properties for the instance, and then call
save Method:
<?php namespace App\Http\Controllers; use App\Flight;use Illuminate\Http\Request; use App\Http\Controllers\Controller; class FlightController extends Controller{ /** * 创建一个新的航班实例 * * @param Request $request * @return Response */ public function store(Request $request) { // 校验请求... $flight = new Flight; $flight->name = $request->name; $flight->save(); } }In this example, we assign the HTTP request parameter
name to the
name# of the App\Flight
model instance ## Attributes. When the save
method is called, a new record will be inserted. created_at
and updated_at
timestamps will be set automatically and no manual assignment is required.
method can also be used to update an existing model in the database. To update the model, you need to retrieve it first, set the properties to be updated, and then call the save
method. Similarly, the updated_at
timestamp will be updated automatically, so there is no need to manually assign the value: $flight = App\Flight::find(1);
$flight->name = 'New Flight Name';$flight->save();
You can also update those that match the query conditions Multiple models. In this example, all
active and destination
flights to San Diego
will be marked as delayed: App\Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);
The method accepts an array whose keys are field names and data are values.
savedand
updated
events. Because during batch updates, the model is never retrieved.
Batch assignment
You can also use the create
method to save a new model, which will return a model instance. However, before using it, you need to specify the fillable
or guarded
attribute on the model, because all Eloquent models cannot be batch assigned by default.
When the user passes in an unexpected parameter via an HTTP request, and the parameter changes a field in the database that you don't need to change. For example: a malicious user may pass in the is_admin
parameter through an HTTP request, and then pass it to the create
method. This operation allows the user to upgrade himself to an administrator.
So, before you start, you should define which attributes on the model can be batch assigned. You can do this via the $fillable
attribute on the model. For example: Let the name
attribute of the Flight
model be batch-assigned:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 可以被批量赋值的属性。 * * @var array */ protected $fillable = ['name']; }
Once we have set up the attributes that can be batch-assigned, we can use create
Method inserts new data into the database. The create
method will return the saved model instance:
$flight = App\Flight::create(['name' => 'Flight 10']);
If you already have a model instance, you can pass an array to the fill
method to assign values:
$flight->fill(['name' => 'Flight 22']);
Protected attributes
$fillable
can be regarded as a "whitelist" for batch assignment. You can also use the $guarded
attribute to fulfill. $guarded
The attribute contains an array that does not allow batch assignment. In other words, $guarded
will function more like a "blacklist". Note: You can only use one of $fillable
or $guarded
, not both at the same time. In the following example, Except for the price
attribute, all other attributes can be assigned values in batches:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model{ /** * 不可批量赋值的属性。 * * @var array */ protected $guarded = ['price']; }
If you want all attributes to be assigned values in batches, you can $guarded
Defined as an empty array:
/** * 不可以批量赋值的属性。 * * @var array */ protected $guarded = [];##Other creation methods
firstOrCreate/
firstOrNew
Here are two methods you might use for batch assignment: firstOrCreate and
firstOrNew .
firstOrCreate The method will match the data in the database through the given column/value. If the corresponding model cannot be found in the database, a record will be created from the attributes of the first parameter and even the attributes of the second parameter and inserted into the database. The
firstOrNew method like the
firstOrCreate method attempts to find a record in the database by the given attribute. The difference is that if the
firstOrNew method cannot find the corresponding model, it will return a new model instance. Note that
firstOrNew the returned model instance has not yet been saved to the database, you need to manually call the
save method to save:
// 通过 name 来查找航班,不存在则创建... $flight = App\Flight::firstOrCreate(['name' => 'Flight 10']); // 通过 name 查找航班,不存在则使用 name 和 delayed 属性创建... $flight = App\Flight::firstOrCreate(['name' => 'Flight 10'], ['delayed' => 1]); // 通过 name 查找航班,不存在则创建一个实例... $flight = App\Flight::firstOrNew(['name' => 'Flight 10']); // 通过 name 查找航班,不存在则使用 name 和 delayed 属性创建一个实例... $flight = App\Flight::firstOrNew(['name' => 'Flight 10'], ['delayed' => 1]);
updateOrCreate
You may also encounter scenarios where you want to update an existing model or create a new model if it does not exist. Laravel provides the updateOrCreate
method that can be implemented in just one step. Like the firstOrCreate
method, updateOrCreate
matches the corresponding model, so there is no need to call the save()
method:
// 如果有从奥克兰到圣地亚哥的航班,则价格定为99美元。 // 如果没匹配到存在的模型,则创建一个。 $flight = App\Flight::updateOrCreate( ['departure' => 'Oakland', 'destination' => 'San Diego'], ['price' => 99] );
Delete model
You can call the delete
method on the model instance to delete the instance:
$flight = App\Flight::find(1); $flight->delete();
Delete model by primary key
In the above example, you need to find the corresponding model in the database before calling delete
. In fact, if you know the primary key of the model, you can directly use the destroy
method to delete the model without first searching it in the database. destroy
In addition to accepting a single primary key as a parameter, the method also accepts multiple primary keys, or uses an array or collection to save multiple primary keys:
App\Flight::destroy(1); App\Flight::destroy(1, 2, 3); App\Flight::destroy([1, 2, 3]); App\Flight::destroy(collect([1, 2, 3]));
Delete by query Model
You can also run delete statements on the model. In this example, we will delete all flights marked as inactive. Like batch update, batch deletion will not trigger any model events for the deleted model:
$deletedRows = App\Flight::where('active', 0)->delete();
##Soft deletionIn addition to actually deleting database records, Eloquent can also "soft delete" models. A soft-deleted model is not actually deleted from the database. In fact, the{note} When executing a batch delete statement through Eloquent,
deleting
anddeleted
Model events. Therefore, when executing a delete statement, the model examples are never retrieved.
deleted_at attribute is set on the model and its value is written to the database. If the
deleted_at value is non-empty, it means that the model has been soft deleted. If you want to enable the model soft deletion function, you need to use the
Illuminate\Database\Eloquent\SoftDeletes trait on the model:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Flight extends Model{ use SoftDeletes; }
{tip}Of course, you need toSoftDeletes
trait Will automatically convert the
deleted_atattribute into
DateTime/
Carboninstance
deleted_at Fields are added to the data table. Laravel's database migration has a method to create this field:
Schema::table('flights', function (Blueprint $table) { $table->softDeletes(); });Now, when you use the
delete method on the model instance, the current date and time will be written to
deleted_at field. At the same time, the query results will automatically exclude records that have been soft deleted.
trashed method to verify whether the current model is soft deleted:
if ($flight->trashed()) { // }Query soft deletion model
Include soft-deleted models
As mentioned earlier, the query results will automatically exclude soft-deleted results. Of course, you can use the withTrashed
method to get models including soft deleted models:
$flights = App\Flight::withTrashed() ->where('account_id', 1) ->get();
withTrashed
The method can also be used in related queries:
$flight->history()->withTrashed()->get();
Retrieve soft deleted model
onlyTrashed
Method Only Get the soft deleted model:
$flights = App\Flight::onlyTrashed() ->where('airline_id', 1) ->get();
Restore Soft-Deleted Model
Sometimes the soft-deleted model is "undone", and the restore
method can be used on the soft-deleted data to restore it to the effective state:
$flight->restore();
You can also use the restore
method in a query to quickly restore multiple models. Like other batch operations, this operation will not trigger any events in the model:
App\Flight::withTrashed() ->where('airline_id', 1) ->restore();
Similar to the withTrashed
method, the restore
method is also used on associations:
$flight->history()->restore();
Permanent deletion
To actually delete data, use the forceDelete
method:
// 单个模型实例的永久删除... $flight->forceDelete(); // 关联模型的永久删除... $flight->history()->forceDelete();
Query scope
##Global scopeGlobal scope Domains can add constraints to model queries. Laravel's Writing global scopeWriting global scope Scope is simple. Define a class that implements theIlluminate\Database\Eloquent\Scope interface and implement the
apply method. According to your needs, add the
where conditions of the query in the
apply method:
<?php namespace App\Scopes; use Illuminate\Database\Eloquent\Scope; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class AgeScope implements Scope{ /** * 把约束加到 Eloquent 查询构造中。 * * @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); } }
{tip} If you need to add fields to the select statement, you should Use theApply global scopeTo assign a global scope to a model, you need to override the model'saddSelect
method instead of the
selectmethod. This will effectively prevent existing select statements from being inadvertently replaced.
boot method and use
addGlobalScope Method:
<?php namespace App;use App\Scopes\AgeScope; use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * 模型的 「启动」 方法. * * @return void */ protected static function boot() { parent::boot(); static::addGlobalScope(new AgeScope); } }After adding the scope, the query for
User::all() will generate the following SQL query statement:
select * from `users` where `age` > 200Anonymous global scopeEloquent also allows the use of closures to define global scopes, so that there is no need to write a separate class for a simple scope:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class User extends Model{ /** *模型的「启动」方法. * * @return void */ protected static function boot() { parent::boot(); static::addGlobalScope('age', function (Builder $builder) { $builder->where('age', '>', 200); }); } }
Cancel the global scope
If you need to cancel the global scope for the current query, you need to use the withoutGlobalScope
method. This method only accepts the global scope class name as its only parameter:
User::withoutGlobalScope(AgeScope::class)->get();
Or, if a closure is used to define the global scope:
User::withoutGlobalScope('age')->get();
If you need to cancel part or all of the global For scope, you need to use the withoutGlobalScopes
method:
// 取消所有的全局作用域... User::withoutGlobalScopes()->get(); // 取消部分全局作用域... User::withoutGlobalScopes([ FirstScope::class, SecondScope::class ])->get();##local scopelocal Scopes allow the definition of common sets of constraints for reuse across applications. For example, you may often need to get all "popular" users. To define such a scope, just add the
scope prefix before the corresponding Eloquent model method:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * 只查询受欢迎的用户的作用域. * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * 只查询 active 用户的作用域. * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeActive($query) { return $query->where('active', 1); } }Using local scopesOnce a scope is defined, scope methods can be called when querying the model. However, it is not necessary to include the
scope prefix when calling these methods. You can even chain calls to multiple scopes, for example:
$users = App\User::popular()->active()->orderBy('created_at')->get();Integrate multiple Eloquent models with the
or query runner, you may need to use closure callbacks:
$users = App\User::popular()->orWhere(function (Builder $query) { $query->active(); })->get();Because this can be a bit cumbersome, Laravel provides the "higher-order"
orWhere method, which allows you to chain call scopes without using closures:
$users = App\User::popular()->orWhere->active()->get();Dynamic ScopeSometimes you may want to define a scope that accepts parameters. This can be achieved by passing additional parameters to the scope. The scope parameters should be placed after the
$query parameters:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * 将查询作用域限制为仅包含给定类型的用户。 * * @param \Illuminate\Database\Eloquent\Builder $query * @param mixed $type * @return \Illuminate\Database\Eloquent\Builder */ public function scopeOfType($query, $type) { return $query->where('type', $type); } }so that the parameters can be passed when calling the scope:
$users = App\User::ofType('admin')->get();Model comparisonSometimes it may be necessary to determine whether two models are "the same". The
is method can be used to quickly verify whether two models have the same primary keys, tables, and database connections:
if ($post->is($anotherPost)) { // }
Events
The Eloquent model triggers several events, allowing you to hook into the following nodes of the model life cycle: retrieved
, creating
, created
, updating
, updated
, saving
, saved
, deleting
, deleted
, restoring
and restored
. Events allow you to execute code whenever a specific model is saved or updated in the database. Each event accepts a model instance through its constructor.
retrieved
Event is fired when an existing model looks up data from the database. Each time a new model is saved, the creating
and created
events are fired. If the model already exists in the database and the save
method is called, the updating
/ updated
events are triggered. In these cases, saving
/ saved
events are also triggered.
{note} When performing batch updates through Eloquent, the
saved
andupdated
events of the updated model will not be triggered. This is because the model is not actually obtained during batch update.
First, define a $dispatchesEvents
attribute on the Eloquent model to map several nodes of the Eloquent model life cycle to your own event class:
<?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; /** * 为模型事件。 * * @var array */ protected $dispatchesEvents = [ 'saved' => UserSaved::class, 'deleted' => UserDeleted::class, ]; }
After defining and mapping Eloquent events, you can use event listeners to process these events.
##ObserverDefine ObserverIf in a There are multiple events listened to on the model, and observers can be used to organize these listeners into a separate class. The method names of the observer class map to the Eloquent events you wish to listen to. These methods all take the model as their only parameter.make:observer The Artisan command can quickly create a new observer class:
php artisan make:observer UserObserver --model=UserThis command will place a new observer class in the
App/Observers folder. If this directory does not exist, Artisan will create it for you. Use the following method to enable an observer:
<?php namespace App\Observers; use App\User; class UserObserver{ /** * 处理 User 「新建」事件。 * * @param \App\User $user * @return void */ public function created(User $user) { // } /** * 处理 User 「更新」 事件。 * * @param \App\User $user * @return void */ public function updated(User $user) { // } /** * 处理 User 「删除」 事件。 * * @param \App\User $user * @return void */ public function deleted(User $user) { // } }Use the
observe method to register an observer on the model you wish to observe. Observers can also be registered in the
boot method of the service provider. The following is an example of registering an observer in
AppServiceProvider:
<?php namespace App\Providers; use App\User;use App\Observers\UserObserver; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * 启动应用服务。 * * @return void */ public function boot() { User::observe(UserObserver::class); } /** * 注册服务提供者。 * * @return void */ public function register() { // } }This article first appeared on the