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.
Before getting started, be sure to configure a database connection in .
To get started, create an Eloquent model. Models typically live in the directory, but you are free to place them anywhere that can be auto-loaded according to your file.
Defining An Eloquent Model
Note that we did not tell Eloquent which table to use for our model. The lower-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 model stores records in the table. You may specify a custom table by defining a property on your model:
Note: Eloquent will also assume that each table has a primary key column named . You may define a property to override this convention. Likewise, you may define a property to override the name of the database connection that should be used when utilizing the model.
Once a model is defined, you are ready to start retrieving and creating records in your table. Note that you will need to place and columns on your table by default. If you do not wish to have these columns automatically maintained, set the property on your model to .
Retrieving All Models
Retrieving A Record By Primary Key
Note: All methods available on the query builder are also available when querying Eloquent models.
Retrieving A Model By Primary Key Or Throw An Exception
Sometimes you may wish to throw an exception if a model is not found, allowing you to catch the exceptions using an handler and display a 404 page.
To register the error handler, listen for the
Querying Using Eloquent Models
Of course, you may also use the query builder aggregate functions.
If you are unable to generate the query you need via the fluent interface, feel free to use :
If you need to process a lot (thousands) of Eloquent records, using the command will allow you to do without eating all of your RAM:
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 pulled from the database.
Specifying The Query Connection
You may also specify which database connection should be used when running an Eloquent query. Simply use the method:
When creating a new model, you pass an array of attributes to the model constructor. These attributes are then assigned to the model via mass-assignment. This is convenient; however, can be a serious security concern when blindly passing user input into a model. If user input is blindly passed into a model, the user is free to modify any and all of the model's attributes. For this reason, all Eloquent models protect against mass-assignment by default.
To get started, set the or properties on your model.
Defining Fillable Attributes On A Model
The property specifies which attributes should be mass-assignable. This can be set at the class or instance level.
In this example, only the three listed attributes will be mass-assignable.
Defining Guarded Attributes On A Model
The inverse of is , and serves as a "black-list" instead of a "white-list":
Note: When using , you should still never pass or any raw array of user controlled input into a or method, as any column that is not guarded may be updated.
Blocking All Attributes From Mass Assignment
In the example above, the and attributes may not be mass assigned. All other attributes will be mass assignable. You may also block all attributes from mass assignment using the guard property:
Insert, Update, Delete
To create a new record in the database from a model, simply create a new model instance and call the method.
Saving A New Model
Note: Typically, your Eloquent models will have auto-incrementing keys. However, if you wish to specify your own keys, set the property on your model to .
You may also use the 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 or attribute on the model, as all Eloquent models protect against mass-assignment.
After saving or creating a new model that uses auto-incrementing IDs, you may retrieve the ID by accessing the object's attribute:
Setting The Guarded Attributes On The Model
Using The Model Create Method
Updating A Retrieved Model
To update a model, you may retrieve it, change an attribute, and use the method:
Saving A Model And Relationships
Sometimes you may wish to save not only a model, but also all of its relationships. To do so, you may use the method:
You may also run updates as queries against a set of models:
Note: No model events are fired when updating a set of models via the Eloquent query builder.
Deleting An Existing Model
To delete a model, simply call the method on the instance:
Deleting An Existing Model By Key
Of course, you may also run a delete query on a set of models:
Updating Only The Model's Timestamps
If you wish to simply update the timestamps on a model, you may use the method:
When soft deleting a model, it is not actually removed from your database. Instead, a timestamp is set on the record. To enable soft deletes for a model, apply the to the model:
To add a column to your table, you may use the method from a migration:
Now, when you call the method on the model, the column will be set to the current timestamp. When querying a model that uses soft deletes, the "deleted" models will not be included in query results.
Forcing Soft Deleted Models Into Results
To force soft deleted models to appear in a result set, use the method on the query:
The method may be used on a defined relationship:
If you wish to only receive soft deleted models in your results, you may use the method:
To restore a soft deleted model into an active state, use the method:
You may also use the method on a query:
Like with , the method may also be used on relationships:
If you wish to truly remove a model from the database, you may use the method:
The method also works on relationships:
To determine if a given model instance has been soft deleted, you may use the method:
By default, Eloquent will maintain the and columns on your database table automatically. Simply add these columns to your table and Eloquent will take care of the rest. If you do not wish for Eloquent to maintain these columns, add the following property to your model:
Disabling Auto Timestamps
Providing A Custom Timestamp Format
If you wish to customize the format of your timestamps, you may override the method in your model:
Defining A Query Scope
Scopes allow you to easily re-use query logic in your models. To define a scope, simply prefix a model method with :
Utilizing A Query Scope
Sometimes you may wish to define a scope that accepts parameters. Just add your parameters to your scope function:
Then pass the parameter into the scope call:
Sometimes you may wish to define a scope that applies to all queries performed on a model. In essence, this is how Eloquent's own "soft delete" feature works. Global scopes are defined using a combination of PHP traits and an implementation of .
First, let's define a trait. For this example, we'll use the that ships with Laravel:
If an Eloquent model uses a trait that has a method matching the naming convention, that trait method will be called when the Eloquent model is booted, giving you an opportunity to register a global scope, or do anything else you want. A scope must implement , which specifies two methods: and .
The method receives an query builder object, and is responsible for adding any additional clauses that the scope wishes to add. The method also receives a object and is responsible for reversing the action taken by . In other words, should remove the clause (or any other clause) that was added. So, for our , the methods look something like this:
Of course, your database tables are probably related to one another. For example, a blog post may have many comments, or an order could be related to the user who placed it. Eloquent makes managing and working with these relationships easy. Laravel supports many types of relationships:
One To One
Defining A One To One Relation
A one-to-one relationship is a very basic relation. For example, a model might have one . We can define this relation in Eloquent:
The first argument passed to the method is the name of the related model. Once the relationship is defined, we may retrieve it using Eloquent's dynamic properties:
The SQL performed by this statement will be as follows:
Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, model is assumed to use a foreign key. If you wish to override this convention, you may pass a second argument to the method. Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:
Defining The Inverse Of A Relation
To define the inverse of the relationship on the model, we use the method:
In the example above, Eloquent will look for a column on the table. If you would like to define a different foreign key column, you may pass it as the second argument to the method:
Additionally, you pass a third parameter which specifies the name of the associated column on the parent table:
One To Many
An example of a one-to-many relation is a blog post that "has many" comments. We can model this relation like so:
Now we can access the post's comments through the dynamic property:
If you need to add further constraints to which comments are retrieved, you may call the method and continue chaining conditions:
Again, you may override the conventional foreign key by passing a second argument to the method. And, like the relation, the local column may also be specified:
Defining The Inverse Of A Relation
To define the inverse of the relationship on the model, we use the method:
Many To Many
Many-to-many relations are a more complicated relationship type. An example of such a relationship is a user with many roles, where the roles are also shared by other users. For example, many users may have the role of "Admin". Three database tables are needed for this relationship: , , and . The table is derived from the alphabetical order of the related model names, and should have and columns.
We can define a many-to-many relation using the method:
Now, we can retrieve the roles through the model:
If you would like to use an unconventional table name for your pivot table, you may pass it as the second argument to the method:
You may also override the conventional associated keys:
Of course, you may also define the inverse of the relationship on the model:
Has Many Through
The "has many through" relation provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a model might have many through a model. The tables for this relationship would look like this:
Even though the table does not contain a column, the relation will allow us to access a country's posts via . Let's define the relationship:
If you would like to manually specify the keys of the relationship, you may pass them as the third and fourth arguments to the method:
Polymorphic relations allow a model to belong to more than one other model, on a single association. For example, you might have a photo model that belongs to either a staff model or an order model. We would define this relation like so:
Retrieving A Polymorphic Relation
Now, we can retrieve the photos for either a staff member or an order:
Retrieving The Owner Of A Polymorphic Relation
However, the true "polymorphic" magic is when you access the staff or order from the model:
The relation on the model will return either a or instance, depending on which type of model owns the photo.
Polymorphic Relation Table Structure
To help understand how this works, let's explore the database structure for a polymorphic relation:
The key fields to notice here are the and on the table. The ID will contain the ID value of, in this example, the owning staff or order, while the type will contain the class name of the owning model. This is what allows the ORM to determine which type of owning model to return when accessing the relation.
Many To Many Polymorphic Relations
Polymorphic Many To Many Relation Table Structure
In addition to traditional polymorphic relations, you may also specify many-to-many polymorphic relations. For example, a blog and model could share a polymorphic relation to a model. First, let's examine the table structure:
Next, we're ready to setup the relationships on the model. The and model will both have a relationship via a method:
The model may define a method for each of its relationships:
Querying Relations When Selecting
When accessing the records for a model, you may wish to limit your results based on the existence of a relationship. For example, you wish to pull all blog posts that have at least one comment. To do so, you may use the method:
You may also specify an operator and a count:
If you need even more power, you may use the and methods to put "where" conditions on your queries:
Eloquent allows you to access your relations via dynamic properties. Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the (for one-to-many relationships) or (for one-to-one relationships) method. It will then be accessible via a dynamic property by the same name as the relation. For example, with the following model :
Instead of echoing the user's email like this:
It may be shortened to simply:
Note: Relationships that return many results will return an instance of the class.
Eager loading exists to alleviate the N + 1 query problem. For example, consider a model that is related to . The relationship is defined like so:
Now, consider the following code:
This loop will execute 1 query to retrieve all of the books on the table, then another query for each book to retrieve the author. So, if we have 25 books, this loop would run 26 queries.
Thankfully, we can use eager loading to drastically reduce the number of queries. The relationships that should be eager loaded may be specified via the method:
In the loop above, only two queries will be executed:
Wise use of eager loading can drastically increase the performance of your application.
Of course, you may eager load multiple relationships at one time:
You may even eager load nested relationships:
In the example above, the relationship will be eager loaded, and the author's relation will also be loaded.
Eager Load Constraints
Sometimes you may wish to eager load a relationship, but also specify a condition for the eager load. Here's an example:
In this example, we're eager loading the user's posts, but only if the post's title column contains the word "first".
Of course, eager loading Closures aren't limited to "constraints". You may also apply orders:
Lazy Eager Loading
It is also possible to eagerly load related models directly from an already existing model collection. This may be useful when dynamically deciding whether to load related models or not, or in combination with caching.
Inserting Related Models
Attaching A Related Model
You will often need to insert new related models. For example, you may wish to insert a new comment for a post. Instead of manually setting the foreign key on the model, you may insert the new comment from its parent model directly:
In this example, the field will automatically be set on the inserted comment.
If you need to save multiple related models:
Associating Models (Belongs To)
When updating a relationship, you may use the method. This method will set the foreign key on the child model:
Inserting Related Models (Many To Many)
You may also insert related models when working with many-to-many relations. Let's continue using our and models as examples. We can easily attach new roles to a user using the method:
Attaching Many To Many Models
You may also pass an array of attributes that should be stored on the pivot table for the relation:
Of course, the opposite of is :
Both and also take arrays of IDs as input:
Using Sync To Attach Many To Many Models
You may also use the method to attach related models. The method accepts an array of IDs to place on the pivot table. After this operation is complete, only the IDs in the array will be on the intermediate table for the model:
Adding Pivot Data When Syncing
You may also associate other pivot table values with the given IDs:
Sometimes you may wish to create a new related model and attach it in a single command. For this operation, you may use the method:
In this example, the new model will be saved and attached to the user model. You may also pass an array of attributes to place on the joining table for this operation:
Touching Parent Timestamps
When a model another model, such as a which belongs to a , it is often helpful to update the parent's timestamp when the child model is updated. For example, when a model is updated, you may want to automatically touch the timestamp of the owning . Eloquent makes it easy. Just add a property containing the names of the relationships to the child model:
Now, when you update a , the owning will have its column updated:
Working With Pivot Tables
As you have already learned, working with many-to-many relations requires the presence of an intermediate table. Eloquent provides some very helpful ways of interacting with this table. For example, let's assume our object has many objects that it is related to. After accessing this relationship, we may access the table on the models:
Notice that each model we retrieve is automatically assigned a attribute. This attribute contains a model representing the intermediate table, and may be used as any other Eloquent model.
By default, only the keys will be present on the object. If your pivot table contains extra attributes, you must specify them when defining the relationship:
Now the and attributes will be accessible on our object for the model.
If you want your pivot table to have automatically maintained and timestamps, use the method on the relationship definition:
Deleting Records On A Pivot Table
To delete all records on the pivot table for a model, you may use the method:
Note that this operation does not delete records from the table, but only from the pivot table.
Updating A Record On A Pivot Table
Sometimes you may need to update your pivot table, but not detach it. If you wish to update your pivot table in place you may use method like so:
Defining A Custom Pivot Model
Laravel also allows you to define a custom Pivot model. To define a custom model, first create your own "Base" model class that extends . In your other Eloquent models, extend this custom base model instead of the default base. In your base model, add the following function that returns an instance of your custom Pivot model:
All multi-result sets returned by Eloquent, either via the method or a , will return a collection object. This object implements the PHP interface so it can be iterated over like an array. However, this object also has a variety of other helpful methods for working with result sets.
Checking If A Collection Contains A Key
For example, we may determine if a result set contains a given primary key using the method:
Collections may also be converted to an array or JSON:
If a collection is cast to a string, it will be returned as JSON:
Eloquent collections also contain a few helpful methods for looping and filtering the items they contain:
When filtering collections, the callback provided will be used as callback for array_filter.
Note: When filtering a collection and converting it to JSON, try calling the function first to reset the array's keys.
Applying A Callback To Each Collection Object
Sorting A Collection By A Value
Sorting A Collection By A Value
Returning A Custom Collection Type
Sometimes, you may wish to return a custom Collection object with your own added methods. You may specify this on your Eloquent model by overriding the method:
Accessors & Mutators
Defining An Accessor
Eloquent provides a convenient way to transform your model attributes when getting or setting them. Simply define a method on your model to declare an accessor. Keep in mind that the methods should follow camel-casing, even though your database columns are snake-case:
In the example above, the column has an accessor. Note that the value of the attribute is passed to the accessor.
Defining A Mutator
Mutators are declared in a similar fashion:
By default, Eloquent will convert the and columns to instances of Carbon, which provides an assortment of helpful methods, and extends the native PHP class.
You may customize which fields are automatically mutated, and even completely disable this mutation, by overriding the method of the model:
When a column is considered a date, you may set its value to a UNIX timestamp, date string (), date-time string, and of course a / instance.
To totally disable date mutations, simply return an empty array from the method:
Eloquent models fire several events, allowing you to hook into various points in the model's lifecycle using the following methods: , , , , , , , , , .
Whenever a new item is saved for the first time, the and events will fire. If an item is not new and the method is called, the / events will fire. In both cases, the / events will fire.
Cancelling Save Operations Via Events
If is returned from the , , , or events, the action will be cancelled:
Setting A Model Boot Method
Eloquent models also contain a static method, which may provide a convenient place to register your event bindings.
To consolidate the handling of model events, you may register a model observer. An observer class may have methods that correspond to the various model events. For example, , , methods may be on an observer, in addition to any other model event name.
So, for example, a model observer might look like this:
You may register an observer instance using the method:
Converting To Arrays / JSON
Converting A Model To An Array
When building JSON APIs, you may often need to convert your models and relationships to arrays or JSON. So, Eloquent includes methods for doing so. To convert a model and its loaded relationship to an array, you may use the method:
Note that entire collections of models may also be converted to arrays:
Converting A Model To JSON
To convert a model to JSON, you may use the method:
Returning A Model From A Route
Note that when a model or collection is cast to a string, it will be converted to JSON, meaning you can return Eloquent objects directly from your application's routes!
Hiding Attributes From Array Or JSON Conversion
Sometimes you may wish to limit the attributes that are included in your model's array or JSON form, such as passwords. To do so, add a property definition to your model:
Note: When hiding relationships, use the relationship's method name, not the dynamic accessor name.
Alternatively, you may use the property to define a white-list:
Occasionally, you may need to add array attributes that do not have a corresponding column in your database. To do so, simply define an accessor for the value:
Once you have created the accessor, just add the value to the property on the model:
Once the attribute has been added to the list, it will be included in both the model's array and JSON forms. Attributes in the array respect the and configuration on the model.
Pivot tables and many-to-many relationships
Today I want to talk about a feature of Laravel which is really useful but can be potentially difficult to understand at first. Pivot table is an example of intermediate table with relationships between two other “main” tables.
Real-life example of pivot tables
In official documentation they show the example of User-Role relationships, where user potentially can belong to several roles, and vice versa. So to make things clearer – let’s take another real-life example: Shops and Products.
Let’s say a company has a dozen of Shops all over city/country and a variety of products, and they want to store the information about which Product is sold in which Shop. It’s a perfect example of many-to-many relationship: one product can belong to several shops, and one shop can have multiple products.
So here’s a potential database structure:
The final table in the list – product_shop is called a “pivot” table, as mentioned in the topic title. Now, there are several things to mention here.
- Name of the pivot table should consist of singular names of both tables, separated by undescore symbole and these names should be arranged in alphabetical order, so we have to have product_shop, not shop_product.
- To create a pivot table we can create a simple migration with artisan make:migration or use Jeffrey Way’s package Laravel 5 Generators Extended where we have a command artisan make:migration:pivot.
- Pivot table fields: by default, there should be only two fields – foreign key to each of the tables, in our case product_id and shop_id. You can add more fields if you want, then you need to add them to relationship assignment – we will discuss that later.
Models for Many-to-Many Relationships: BelongsToMany
Ok, we have DB tables and migrations, now let’s create models for them. The main part here is to assign a many-to-many relationship – it can be done from either of “main” tables models.
So, option 1:
Or option 2:
Actually, you can do both – it depends on how will you actuall use the relationship in other parts of the code: will you need $shop->products or more likely to query $product->shops, or both.
Now, with such declaration of relationships Laravel “assumes” that pivot table name obeys the rules and is product_shop. But, if it’s actually different (for example, it’s plural), you can provide it as a second parameter:
Moreover, you can specify the actual field names of that pivot table, if they are different than default product_id and shop_id. Then just add two more parameters – first, the current model field, and then the field of the model being joined:
One of the main benefits here: you don’t need to create a separate model for ProductShop – you will be able to manage that table through pivot commands, we will discuss that right away.
Go to QuickAdminPanel.com
Managing Many-to-Many Relationships: attach-detach-sync
So, we have tables, and we have Models ready. Now, how do we actually save the data with a help of our two Models instead of the third intermediate one? Couple of things here.
For example, if we want to add another product to the current shop instance, we use relationship function and then method attach():
The result – a new row will be added to product_shop table, with $product_id and $shop_id values.
Likewise, we can detach a relationship – let’s say, we want to remove a product from the shop:
Or, more brutally, remove all products from a particular shop – then just call method without parameters:
You can also attach and detach rows, passing array of values as parameters:
And another REALLY useful function, in my experience, is updating the whole pivot table. Really often example – in your admin area there are checkboxes for shops for a particular product, and on Update operation you actually have to check all shops, delete those which are not in new checkbox array, and then add/update existing ones. Pain in the neck.
Not anymore – there’s a method called sync() which accept new values as parameters array, and then takes care of all that “dirty work” of syncing:
Result – no matter what values were in product_shop table before, after this call there will be only three rows with shop_id equals 1, 2, or 3.
Additional Columns in Pivot Tables
As I mentioned above, it’s pretty likely that you would want more fields in that pivot tables. In our example it would make sense to save the amount of products, price in that particular shop and timestamps. We can add the fields through migration files, as usual, but for proper usage in relationships we have to make some additional changes to Models:
As you can see, we can add timestamps with a simple method withTimestamps and additional fields are added just as parameters in method withPivot.
Now, what it gives us is possibility to get those values in our loops in the code. With a property called pivot:
Basically, ->pivot represents that intermediate pivot table, and with this we can access any of our described fields, like created_at, for example.
Now, how to add those values when calling attach()? The method accept another parameter as array, so you can specify all additional fields there:
So, pivot tables and many-to-many relationships are handled quite conveniently with Eloquent, so there’s no need to create a separate model for intermediate table. Hope that helps!
* The products that belong to the shop.
* The shops that belong to the product.