Laravel-Docs/eloquent.md

848 lines
31 KiB
Markdown
Raw Permalink Normal View History

2015-05-17 16:59:24 +02:00
# Eloquent: Getting Started
2013-01-10 20:08:51 +01:00
- [Introduction](#introduction)
2015-05-16 20:36:20 +02:00
- [Defining Models](#defining-models)
2015-07-02 16:54:27 +02:00
- [Eloquent Model Conventions](#eloquent-model-conventions)
2016-08-02 22:00:19 +02:00
- [Retrieving Models](#retrieving-models)
- [Collections](#collections)
- [Chunking Results](#chunking-results)
2015-05-16 20:36:20 +02:00
- [Retrieving Single Models / Aggregates](#retrieving-single-models)
2015-07-02 16:54:27 +02:00
- [Retrieving Aggregates](#retrieving-aggregates)
2015-05-16 20:36:20 +02:00
- [Inserting & Updating Models](#inserting-and-updating-models)
2016-08-02 22:00:19 +02:00
- [Inserts](#inserts)
- [Updates](#updates)
2015-07-02 16:54:27 +02:00
- [Mass Assignment](#mass-assignment)
2016-08-02 22:00:19 +02:00
- [Other Creation Methods](#other-creation-methods)
2015-05-16 20:36:20 +02:00
- [Deleting Models](#deleting-models)
2015-07-02 16:54:27 +02:00
- [Soft Deleting](#soft-deleting)
- [Querying Soft Deleted Models](#querying-soft-deleted-models)
2015-06-05 17:04:33 +02:00
- [Query Scopes](#query-scopes)
2015-12-19 15:11:48 +01:00
- [Global Scopes](#global-scopes)
- [Local Scopes](#local-scopes)
2018-06-30 22:23:47 +02:00
- [Comparing Models](#comparing-models)
2015-05-19 19:35:19 +02:00
- [Events](#events)
2016-08-17 19:37:07 +02:00
- [Observers](#observers)
2013-01-10 20:08:51 +01:00
<a name="introduction"></a>
## Introduction
2015-05-16 20:36:20 +02:00
The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database. Each database table has a corresponding "Model" which is used to interact with that table. Models allow you to query for data in your tables, as well as insert new records into the table.
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
Before getting started, be sure to configure a database connection in `config/database.php`. For more information on configuring your database, check out [the documentation](/docs/{{version}}/database#configuration).
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
<a name="defining-models"></a>
## Defining Models
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
To get started, let's create an Eloquent model. Models typically live in the `app` directory, but you are free to place them anywhere that can be auto-loaded according to your `composer.json` file. All Eloquent models extend `Illuminate\Database\Eloquent\Model` class.
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
The easiest way to create a model instance is using the `make:model` [Artisan command](/docs/{{version}}/artisan):
2015-02-04 20:54:25 +01:00
php artisan make:model Flight
2015-02-04 20:54:25 +01:00
If you would like to generate a [database migration](/docs/{{version}}/migrations) when you generate the model, you may use the `--migration` or `-m` option:
2015-03-18 22:48:13 +01:00
php artisan make:model Flight --migration
2015-03-18 22:48:13 +01:00
php artisan make:model Flight -m
2015-03-18 22:48:13 +01:00
2015-05-16 20:36:20 +02:00
<a name="eloquent-model-conventions"></a>
### Eloquent Model Conventions
2013-03-28 20:41:25 +01:00
2016-08-02 22:00:19 +02:00
Now, let's look at an example `Flight` model, which we will use to retrieve and store information from our `flights` database table:
2013-03-28 20:41:25 +01:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2013-06-06 16:30:54 +02:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2013-03-28 20:41:25 +01:00
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
//
}
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
#### Table Names
2013-06-16 03:17:32 +02:00
2016-08-02 22:00:19 +02:00
Note that we did not tell Eloquent which table to use for our `Flight` model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the `Flight` model stores records in the `flights` table. You may specify a custom table by defining a `table` property on your model:
2013-06-16 03:17:32 +02:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2013-12-10 04:06:43 +01:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2013-12-10 04:06:43 +01:00
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'my_flights';
}
2013-05-03 22:48:12 +02:00
2015-05-16 20:36:20 +02:00
#### Primary Keys
2013-05-03 22:48:12 +02:00
2017-09-25 08:49:51 +02:00
Eloquent will also assume that each table has a primary key column named `id`. You may define a protected `$primaryKey` property to override this convention.
2013-05-03 22:48:12 +02:00
2017-10-19 14:42:29 +02:00
In addition, Eloquent assumes that the primary key is an incrementing integer value, which means that by default the primary key will be cast to an `int` automatically. If you wish to use a non-incrementing or a non-numeric primary key you must set the public `$incrementing` property on your model to `false`. If your primary key is not an integer, you should set the protected `$keyType` property on your model to `string`.
2015-05-16 20:36:20 +02:00
#### Timestamps
2013-05-03 22:48:12 +02:00
2015-05-16 20:36:20 +02:00
By default, Eloquent expects `created_at` and `updated_at` columns to exist on your tables. If you do not wish to have these columns automatically managed by Eloquent, set the `$timestamps` property on your model to `false`:
2013-05-03 22:48:12 +02:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2013-05-03 22:48:12 +02:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2013-05-03 22:48:12 +02:00
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
}
2015-05-16 20:36:20 +02:00
If you need to customize the format of your timestamps, set the `$dateFormat` property on your model. This property determines how date attributes are stored in the database, as well as their format when the model is serialized to an array or JSON:
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';
}
2016-11-01 15:57:45 +01:00
If you need to customize the names of the columns used to store the timestamps, you may set the `CREATED_AT` and `UPDATED_AT` constants in your model:
<?php
class Flight extends Model
{
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'last_update';
}
2015-11-10 15:28:05 +01:00
#### Database Connection
By default, all Eloquent models will use the default database connection configured for your application. If you would like to specify a different connection for the model, use the `$connection` property:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The connection name for the model.
*
* @var string
*/
protected $connection = 'connection-name';
}
2016-08-02 22:00:19 +02:00
<a name="retrieving-models"></a>
## Retrieving Models
2013-03-28 20:17:02 +01:00
Once you have created a model and [its associated database table](/docs/{{version}}/migrations#writing-migrations), you are ready to start retrieving data from your database. Think of each Eloquent model as a powerful [query builder](/docs/{{version}}/queries) allowing you to fluently query the database table associated with the model. For example:
2013-03-28 20:17:02 +01:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
use App\Flight;
2013-03-28 20:17:02 +01:00
2016-08-02 22:00:19 +02:00
$flights = App\Flight::all();
2015-07-02 16:54:27 +02:00
foreach ($flights as $flight) {
echo $flight->name;
}
2015-05-16 20:36:20 +02:00
#### Adding Additional Constraints
2014-07-03 04:01:07 +02:00
2015-05-16 20:36:20 +02:00
The Eloquent `all` method will return all of the results in the model's table. Since each Eloquent model serves as a [query builder](/docs/{{version}}/queries), you may also add constraints to queries, and then use the `get` method to retrieve the results:
2014-07-03 04:01:07 +02:00
2015-07-02 16:54:27 +02:00
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
2014-07-03 04:01:07 +02:00
2016-08-02 22:00:19 +02:00
> {tip} Since Eloquent models are query builders, you should review all of the methods available on the [query builder](/docs/{{version}}/queries). You may use any of these methods in your Eloquent queries.
2014-07-03 04:01:07 +02:00
2016-08-02 22:00:19 +02:00
<a name="collections"></a>
### Collections
For Eloquent methods like `all` and `get` which retrieve multiple results, an instance of `Illuminate\Database\Eloquent\Collection` will be returned. The `Collection` class provides [a variety of helpful methods](/docs/{{version}}/eloquent-collections#available-methods) for working with your Eloquent results:
$flights = $flights->reject(function ($flight) {
return $flight->cancelled;
});
2014-07-03 04:01:07 +02:00
2018-01-23 18:48:13 +01:00
Of course, you may also loop over the collection like an array:
2015-07-02 16:54:27 +02:00
foreach ($flights as $flight) {
echo $flight->name;
}
2014-07-03 04:01:07 +02:00
2016-08-02 22:00:19 +02:00
<a name="chunking-results"></a>
### Chunking Results
2014-07-03 04:01:07 +02:00
2015-05-16 20:36:20 +02:00
If you need to process thousands of Eloquent records, use the `chunk` command. The `chunk` method will retrieve a "chunk" of Eloquent models, feeding them to a given `Closure` for processing. Using the `chunk` method will conserve memory when working with large result sets:
2014-07-03 04:01:07 +02:00
2015-07-02 16:54:27 +02:00
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
The first argument passed to the method is the number of records you wish to receive per "chunk". The Closure passed as the second argument will be called for each chunk that is retrieved from the database. A database query will be executed to retrieve each chunk of records passed to the Closure.
2016-07-28 15:48:14 +02:00
#### Using Cursors
2016-08-02 22:00:19 +02:00
The `cursor` method allows you to iterate through your database records using a cursor, which will only execute a single query. When processing large amounts of data, the `cursor` method may be used to greatly reduce your memory usage:
2016-07-28 15:48:14 +02:00
foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
//
2016-07-28 15:48:14 +02:00
}
2015-05-16 20:36:20 +02:00
<a name="retrieving-single-models"></a>
## Retrieving Single Models / Aggregates
Of course, in addition to retrieving all of the records for a given table, you may also retrieve single records using `find` or `first`. Instead of returning a collection of models, these methods return a single model instance:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
// Retrieve a model by its primary key...
$flight = App\Flight::find(1);
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();
2013-01-10 20:08:51 +01:00
2016-02-04 20:44:54 +01:00
You may also call the `find` method with an array of primary keys, which will return a collection of the matching records:
2016-02-04 20:44:54 +01:00
$flights = App\Flight::find([1, 2, 3]);
2015-05-16 20:36:20 +02:00
#### Not Found Exceptions
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The `findOrFail` and `firstOrFail` methods will retrieve the first result of the query; however, if no result is found, a `Illuminate\Database\Eloquent\ModelNotFoundException` will be thrown:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$model = App\Flight::findOrFail(1);
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$model = App\Flight::where('legs', '>', 100)->firstOrFail();
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
If the exception is not caught, a `404` HTTP response is automatically sent back to the user. It is not necessary to write explicit checks to return `404` responses when using these methods:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
Route::get('/api/flights/{id}', function ($id) {
return App\Flight::findOrFail($id);
});
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
<a name="retrieving-aggregates"></a>
### Retrieving Aggregates
2013-12-10 04:48:07 +01:00
2016-08-02 22:00:19 +02:00
You may also use the `count`, `sum`, `max`, and other [aggregate methods](/docs/{{version}}/queries#aggregates) provided by the [query builder](/docs/{{version}}/queries). These methods return the appropriate scalar value instead of a full model instance:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$count = App\Flight::where('active', 1)->count();
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$max = App\Flight::where('active', 1)->max('price');
2014-01-03 16:30:54 +01:00
2015-05-16 20:36:20 +02:00
<a name="inserting-and-updating-models"></a>
## Inserting & Updating Models
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
<a name="inserts"></a>
### Inserts
2013-01-10 20:08:51 +01:00
2018-01-23 18:48:13 +01:00
To create a new record in the database, create a new model instance, set attributes on the model, then call the `save` method:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App\Http\Controllers;
2015-07-02 16:54:27 +02:00
use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
2015-07-02 16:54:27 +02:00
class FlightController extends Controller
{
/**
* Create a new flight instance.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Validate the request...
2015-07-02 16:54:27 +02:00
$flight = new Flight;
2013-12-10 04:44:58 +01:00
2015-07-02 16:54:27 +02:00
$flight->name = $request->name;
2013-12-10 04:44:58 +01:00
2015-07-02 16:54:27 +02:00
$flight->save();
}
}
2013-12-10 04:44:58 +01:00
2018-01-23 18:48:13 +01:00
In this example, we assign the `name` parameter from the incoming HTTP request to the `name` attribute of the `App\Flight` model instance. When we call the `save` method, a record will be inserted into the database. The `created_at` and `updated_at` timestamps will automatically be set when the `save` method is called, so there is no need to set them manually.
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
<a name="updates"></a>
### Updates
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
The `save` method may also be used to update models that already exist in the database. To update a model, you should retrieve it, set any attributes you wish to update, and then call the `save` method. Again, the `updated_at` timestamp will automatically be updated, so there is no need to manually set its value:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flight = App\Flight::find(1);
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flight->name = 'New Flight Name';
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flight->save();
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
#### Mass Updates
2015-05-16 20:36:20 +02:00
Updates can also be performed against any number of models that match a given query. In this example, all flights that are `active` and have a `destination` of `San Diego` will be marked as delayed:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
App\Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
The `update` method expects an array of column and value pairs representing the columns that should be updated.
2013-12-10 04:48:07 +01:00
2016-09-01 08:11:55 +02:00
> {note} When issuing a mass update via Eloquent, the `saved` and `updated` model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.
2016-08-02 22:00:19 +02:00
2015-05-16 20:36:20 +02:00
<a name="mass-assignment"></a>
### Mass Assignment
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
You may also use the `create` method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a `fillable` or `guarded` attribute on the model, as all Eloquent models protect against mass-assignment by default.
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
A mass-assignment vulnerability occurs when a user passes an unexpected HTTP parameter through a request, and that parameter changes a column in your database you did not expect. For example, a malicious user might send an `is_admin` parameter through an HTTP request, which is then passed into your model's `create` method, allowing the user to escalate themselves to an administrator.
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
So, to get started, you should define which model attributes you want to make mass assignable. You may do this using the `$fillable` property on the model. For example, let's make the `name` attribute of our `Flight` model mass assignable:
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
}
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
Once we have made the attributes mass assignable, we can use the `create` method to insert a new record in the database. The `create` method returns the saved model instance:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flight = App\Flight::create(['name' => 'Flight 10']);
2016-12-26 15:35:40 +01:00
If you already have a model instance, you may use the `fill` method to populate it with an array of attributes:
$flight->fill(['name' => 'Flight 22']);
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
#### Guarding Attributes
2016-08-02 22:21:31 +02:00
While `$fillable` serves as a "white list" of attributes that should be mass assignable, you may also choose to use `$guarded`. The `$guarded` property should contain an array of attributes that you do not want to be mass assignable. All other attributes not in the array will be mass assignable. So, `$guarded` functions like a "black list". Of course, you should use either `$fillable` or `$guarded` - not both. In the example below, all attributes **except for `price`** will be mass assignable:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = ['price'];
}
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
If you would like to make all attributes mass assignable, you may define the `$guarded` property as an empty array:
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
<a name="other-creation-methods"></a>
### Other Creation Methods
2013-01-10 20:08:51 +01:00
2016-10-25 22:29:30 +02:00
#### `firstOrCreate`/ `firstOrNew`
There are two other methods you may use to create models by mass assigning attributes: `firstOrCreate` and `firstOrNew`. The `firstOrCreate` method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the attributes from the first parameter, along with those in the optional second parameter.
2013-01-10 20:08:51 +01:00
2017-10-24 17:49:59 +02:00
The `firstOrNew` method, like `firstOrCreate` will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by `firstOrNew` has not yet been persisted to the database. You will need to call `save` manually to persist it:
2013-01-10 20:08:51 +01:00
2017-04-06 16:03:57 +02:00
// Retrieve flight by name, or create it if it doesn't exist...
2015-07-02 16:54:27 +02:00
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
2013-03-29 15:00:02 +01:00
2017-04-06 16:03:57 +02:00
// Retrieve flight by name, or create it with the name and delayed attributes...
$flight = App\Flight::firstOrCreate(
['name' => 'Flight 10'], ['delayed' => 1]
);
// Retrieve by name, or instantiate...
2015-07-02 16:54:27 +02:00
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
2013-03-29 15:00:02 +01:00
2017-04-06 16:03:57 +02:00
// Retrieve by name, or instantiate with the name and delayed attributes...
$flight = App\Flight::firstOrNew(
['name' => 'Flight 10'], ['delayed' => 1]
);
2013-03-29 15:00:02 +01:00
2016-10-25 22:29:30 +02:00
#### `updateOrCreate`
You may also come across situations where you want to update an existing model or create a new model if none exists. Laravel provides an `updateOrCreate` method to do this in one step. Like the `firstOrCreate` method, `updateOrCreate` persists the model, so there's no need to call `save()`:
2016-10-25 22:29:30 +02:00
// 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(
2016-10-25 22:29:30 +02:00
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);
2015-05-16 20:36:20 +02:00
<a name="deleting-models"></a>
## Deleting Models
2013-03-29 15:00:02 +01:00
2015-05-16 20:36:20 +02:00
To delete a model, call the `delete` method on a model instance:
2013-03-29 15:00:02 +01:00
2015-07-02 16:54:27 +02:00
$flight = App\Flight::find(1);
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
$flight->delete();
2013-12-11 04:14:14 +01:00
2015-05-16 20:36:20 +02:00
#### Deleting An Existing Model By Key
2013-12-11 04:14:14 +01:00
2015-05-16 20:36:20 +02:00
In the example above, we are retrieving the model from the database before calling the `delete` method. However, if you know the primary key of the model, you may delete the model without retrieving it. To do so, call the `destroy` method:
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
App\Flight::destroy(1);
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
App\Flight::destroy([1, 2, 3]);
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
App\Flight::destroy(1, 2, 3);
2013-12-11 04:14:14 +01:00
2015-05-16 20:36:20 +02:00
#### Deleting Models By Query
2013-12-11 04:14:14 +01:00
2016-09-07 04:05:04 +02:00
Of course, you may also run a delete statement on a set of models. In this example, we will delete all flights that are marked as inactive. Like mass updates, mass deletes will not fire any model events for the models that are deleted:
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
$deletedRows = App\Flight::where('active', 0)->delete();
2013-12-11 04:14:14 +01:00
2016-09-07 04:05:04 +02:00
> {note} When executing a mass delete statement via Eloquent, the `deleting` and `deleted` model events will not be fired for the deleted models. This is because the models are never actually retrieved when executing the delete statement.
2015-05-16 20:36:20 +02:00
<a name="soft-deleting"></a>
### Soft Deleting
2013-12-11 04:14:14 +01:00
2015-05-16 20:36:20 +02:00
In addition to actually removing records from your database, Eloquent can also "soft delete" models. When models are soft deleted, they are not actually removed from your database. Instead, a `deleted_at` attribute is set on the model and inserted into the database. If a model has a non-null `deleted_at` value, the model has been soft deleted. To enable soft deletes for a model, use the `Illuminate\Database\Eloquent\SoftDeletes` trait on the model and add the `deleted_at` column to your `$dates` property:
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2013-12-11 04:14:14 +01:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
class Flight extends Model
{
use SoftDeletes;
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = ['deleted_at'];
}
2013-01-10 20:08:51 +01:00
Of course, you should add the `deleted_at` column to your database table. The Laravel [schema builder](/docs/{{version}}/migrations) contains a helper method to create this column:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
Schema::table('flights', function ($table) {
$table->softDeletes();
});
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
Now, when you call the `delete` method on the model, the `deleted_at` column will be set to the current date and time. And, when querying a model that uses soft deletes, the soft deleted models will automatically be excluded from all query results.
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
To determine if a given model instance has been soft deleted, use the `trashed` method:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
if ($flight->trashed()) {
//
}
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
<a name="querying-soft-deleted-models"></a>
### Querying Soft Deleted Models
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
#### Including Soft Deleted Models
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
As noted above, soft deleted models will automatically be excluded from query results. However, you may force soft deleted models to appear in a result set using the `withTrashed` method on the query:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flights = App\Flight::withTrashed()
->where('account_id', 1)
->get();
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
The `withTrashed` method may also be used on a [relationship](/docs/{{version}}/eloquent-relationships) query:
2015-07-02 16:54:27 +02:00
$flight->history()->withTrashed()->get();
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
#### Retrieving Only Soft Deleted Models
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
The `onlyTrashed` method will retrieve **only** soft deleted models:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flights = App\Flight::onlyTrashed()
->where('airline_id', 1)
->get();
2014-01-03 16:32:13 +01:00
2015-05-16 20:36:20 +02:00
#### Restoring Soft Deleted Models
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
Sometimes you may wish to "un-delete" a soft deleted model. To restore a soft deleted model into an active state, use the `restore` method on a model instance:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flight->restore();
2013-01-10 20:08:51 +01:00
2016-08-02 22:00:19 +02:00
You may also use the `restore` method in a query to quickly restore multiple models. Again, like other "mass" operations, this will not fire any model events for the models that are restored:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
App\Flight::withTrashed()
->where('airline_id', 1)
->restore();
2015-05-16 20:36:20 +02:00
Like the `withTrashed` method, the `restore` method may also be used on [relationships](/docs/{{version}}/eloquent-relationships):
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$flight->history()->restore();
2013-01-10 20:08:51 +01:00
2015-05-16 20:36:20 +02:00
#### Permanently Deleting Models
2013-08-16 05:13:37 +02:00
2015-05-16 20:36:20 +02:00
Sometimes you may need to truly remove a model from your database. To permanently remove a soft deleted model from the database, use the `forceDelete` method:
2013-08-16 05:13:37 +02:00
2015-07-02 16:54:27 +02:00
// Force deleting a single model instance...
$flight->forceDelete();
2013-08-16 05:13:37 +02:00
2015-07-02 16:54:27 +02:00
// Force deleting all related models...
$flight->history()->forceDelete();
2015-05-19 19:35:19 +02:00
2015-06-05 17:04:33 +02:00
<a name="query-scopes"></a>
## Query Scopes
2015-12-19 15:11:48 +01:00
<a name="global-scopes"></a>
### Global Scopes
2016-08-02 22:00:19 +02:00
Global scopes allow you to add constraints to all queries for a given model. Laravel's own [soft delete](#soft-deleting) functionality utilizes global scopes to only pull "non-deleted" models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints.
2015-12-19 15:11:48 +01:00
#### Writing Global Scopes
Writing a global scope is simple. Define a class that implements the `Illuminate\Database\Eloquent\Scope` interface. This interface requires you to implement one method: `apply`. The `apply` method may add `where` constraints to the query as needed:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class AgeScope implements Scope
2015-12-19 15:11:48 +01:00
{
/**
* 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);
2015-12-19 15:11:48 +01:00
}
}
2017-07-13 03:41:25 +02:00
> {tip} If your global scope is adding columns to the select clause of the query, you should use the `addSelect` method instead of `select`. This will prevent the unintentional replacement of the query's existing select clause.
2015-12-19 15:11:48 +01:00
#### Applying Global Scopes
To assign a global scope to a model, you should override a given model's `boot` method and use the `addGlobalScope` method:
<?php
namespace App;
use App\Scopes\AgeScope;
2015-12-19 15:11:48 +01:00
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);
2015-12-19 15:11:48 +01:00
}
}
2015-12-20 16:42:38 +01:00
After adding the scope, a query to `User::all()` will produce the following SQL:
2015-12-20 10:49:55 +01:00
select * from `users` where `age` > 200
2015-12-20 16:42:38 +01:00
#### Anonymous Global Scopes
2015-12-21 00:45:00 +01:00
Eloquent also allows you to define global scopes using Closures, which is particularly useful for simple scopes that do not warrant a separate class:
<?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();
2016-11-11 16:35:36 +01:00
static::addGlobalScope('age', function (Builder $builder) {
2016-01-03 05:23:56 +01:00
$builder->where('age', '>', 200);
});
}
}
2015-12-21 00:45:00 +01:00
#### Removing Global Scopes
2016-08-02 22:00:19 +02:00
If you would like to remove a global scope for a given query, you may use the `withoutGlobalScope` method. The method accepts the class name of the global scope as its only argument:
2015-12-21 00:45:00 +01:00
User::withoutGlobalScope(AgeScope::class)->get();
2018-02-11 15:37:12 +01:00
Or, if you defined the global scope using a Closure:
2018-02-11 02:34:17 +01:00
User::withoutGlobalScope('age')->get();
2015-12-21 00:45:00 +01:00
If you would like to remove several or even all of the global scopes, you may use the `withoutGlobalScopes` method:
2016-08-02 22:00:19 +02:00
// Remove all of the global scopes...
2015-12-21 00:45:00 +01:00
User::withoutGlobalScopes()->get();
2016-08-02 22:00:19 +02:00
// Remove some of the global scopes...
User::withoutGlobalScopes([
FirstScope::class, SecondScope::class
])->get();
2015-12-21 00:45:00 +01:00
2015-12-19 15:11:48 +01:00
<a name="local-scopes"></a>
### Local Scopes
2018-01-23 18:48:13 +01:00
Local scopes allow you to define common sets of constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered "popular". To define a scope, prefix an Eloquent model method with `scope`.
2015-10-23 17:32:45 +02:00
Scopes should always return a query builder instance:
2015-06-05 17:04:33 +02:00
2015-07-02 16:54:27 +02:00
<?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
2015-07-02 16:54:27 +02:00
* @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
2015-07-02 16:54:27 +02:00
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive($query)
{
return $query->where('active', 1);
}
}
2015-06-05 17:04:33 +02:00
2016-08-02 22:00:19 +02:00
#### Utilizing A Local Scope
2015-06-05 17:04:33 +02:00
Once the scope has been defined, you may call the scope methods when querying the model. However, you should not include the `scope` prefix when calling the method. You can even chain calls to various scopes, for example:
2015-06-05 17:04:33 +02:00
$users = App\User::popular()->active()->orderBy('created_at')->get();
2015-06-05 17:04:33 +02:00
#### Dynamic Scopes
2016-08-02 22:00:19 +02:00
Sometimes you may wish to define a scope that accepts parameters. To get started, just add your additional parameters to your scope. Scope parameters should be defined after the `$query` parameter:
2015-06-05 17:04:33 +02:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App;
2015-06-05 17:04:33 +02:00
2015-07-02 16:54:27 +02:00
use Illuminate\Database\Eloquent\Model;
2015-06-05 17:04:33 +02:00
2015-07-02 16:54:27 +02:00
class User extends Model
{
/**
* Scope a query to only include users of a given type.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param mixed $type
2015-07-02 16:54:27 +02:00
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
}
2015-06-05 17:04:33 +02:00
Now, you may pass the parameters when calling the scope:
2015-07-02 16:54:27 +02:00
$users = App\User::ofType('admin')->get();
2015-06-05 17:04:33 +02:00
2018-06-30 22:23:47 +02:00
<a name="comparing-models"></a>
## Comparing Models
Sometimes you may need to determine if two models are the "same". The `is` method may be used to quickly verify two models have same primary key, table, and database connection:
if ($post->is($anotherPost)) {
//
}
2015-05-19 19:35:19 +02:00
<a name="events"></a>
## Events
Eloquent models fire several events, allowing you to hook into the following points in a model's lifecycle: `retrieved`, `creating`, `created`, `updating`, `updated`, `saving`, `saved`, `deleting`, `deleted`, `restoring`, `restored`. Events allow you to easily execute code each time a specific model class is saved or updated in the database. Each event receives the instance of the model through its constructor.
2015-05-19 19:35:19 +02:00
2017-09-03 17:22:57 +02:00
The `retrieved` event will fire when an existing model is retrieved from the database. When a new model is saved for the first time, the `creating` and `created` events will fire. If a model already existed in the database and the `save` method is called, the `updating` / `updated` events will fire. However, in both cases, the `saving` / `saved` events will fire.
2015-05-19 19:35:19 +02:00
> {note} When issuing a mass update via Eloquent, the `saved` and `updated` model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.
2017-03-05 17:32:38 +01:00
To get started, define a `$dispatchesEvents` property on your Eloquent model that maps various points of the Eloquent model's lifecycle to your own [event classes](/docs/{{version}}/events):
2015-05-19 19:35:19 +02:00
2015-07-02 16:54:27 +02:00
<?php
2017-01-16 17:37:51 +01:00
namespace App;
2015-07-02 16:54:27 +02:00
2017-01-16 17:37:51 +01:00
use App\Events\UserSaved;
use App\Events\UserDeleted;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
2015-07-02 16:54:27 +02:00
2017-01-16 17:37:51 +01:00
class User extends Authenticatable
2015-07-02 16:54:27 +02:00
{
2017-01-16 17:37:51 +01:00
use Notifiable;
2015-07-02 16:54:27 +02:00
/**
2017-01-16 17:37:51 +01:00
* The event map for the model.
2015-07-02 16:54:27 +02:00
*
2017-01-16 17:37:51 +01:00
* @var array
2015-07-02 16:54:27 +02:00
*/
2017-03-05 16:26:57 +01:00
protected $dispatchesEvents = [
2017-01-16 17:37:51 +01:00
'saved' => UserSaved::class,
'deleted' => UserDeleted::class,
];
2015-07-02 16:54:27 +02:00
}
2016-08-17 19:37:07 +02:00
<a name="observers"></a>
### Observers
#### Defining Observers
2018-07-02 16:39:40 +02:00
If you are listening for many events on a given model, you may use observers to group all of your listeners into a single class. Observers classes have method names which reflect the Eloquent events you wish to listen for. Each of these methods receives the model as their only argument. The `make:observer` Artisan command is the easiest way to create a new observer class:
php artisan make:observer UserObserver --model=User
2018-07-02 16:39:40 +02:00
This command will place the new observer in your `App/Observers` directory. If this directory does not exist, Artisan will create it for you. Your fresh observer will look like the following:
2016-08-17 19:37:07 +02:00
<?php
namespace App\Observers;
2016-08-18 15:44:14 +02:00
use App\User;
class UserObserver
{
/**
* Handle to the User "created" event.
2016-08-18 15:44:14 +02:00
*
2017-10-21 23:53:28 +02:00
* @param \App\User $user
2016-08-18 15:44:14 +02:00
* @return void
*/
public function created(User $user)
{
//
}
2016-08-17 19:37:07 +02:00
2016-08-18 15:44:14 +02:00
/**
* Handle the User "updated" event.
*
* @param \App\User $user
* @return void
*/
public function updated(User $user)
{
//
}
/**
* Handle the User "deleted" event.
2016-08-18 15:44:14 +02:00
*
2017-10-21 23:53:28 +02:00
* @param \App\User $user
2016-08-18 15:44:14 +02:00
* @return void
*/
public function deleted(User $user)
2016-08-18 15:44:14 +02:00
{
//
}
2016-08-17 19:37:07 +02:00
}
2016-08-18 15:44:14 +02:00
To register an observer, use the `observe` method on the model you wish to observe. You may register observers in the `boot` method of one of your service providers. In this example, we'll register the observer in the `AppServiceProvider`:
2016-08-17 19:37:07 +02:00
<?php
namespace App\Providers;
use App\User;
2016-08-18 15:44:14 +02:00
use App\Observers\UserObserver;
2016-08-17 19:37:07 +02:00
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}