Laravel Mass Assignment Example

Eloquent ORM

Introduction

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 .

Basic Usage

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. All Eloquent models extend .

Defining An Eloquent Model

You may also generate Eloquent models using the command:

Note that we did not tell Eloquent which table to use for our model. 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 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 Records

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. To do this, you may use the method:

Doing this will let you catch the exception so you can log and display an error page as necessary. To catch the , add some logic to your file.

Querying Using Eloquent Models

Eloquent Aggregates

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 :

Chunking Results

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:

If you are using read / write connections, you may force the query to use the "write" connection with the following method:

Mass Assignment

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:

Soft Deleting

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:

Timestamps

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:

Query Scopes

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

Dynamic Scopes

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:

Global Scopes

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 the it's applied to, and is responsible for adding any additional clauses that the scope wishes to add. The method also receives a object and 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:

Relationships

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

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

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:

Nested statements may also be constructed using "dot" notation:

If you need even more power, you may use the and methods to put "where" conditions on your queries:

Dynamic Properties

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

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.

You may also pass a Closure to set constraints on the query:

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:

Collections

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:

Iterating Collections

Eloquent collections also contain a few helpful methods for looping and filtering the items they contain:

Filtering Collections

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:

Date Mutators

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:

Attribute Casting

If you have some attributes that you want to always convert to another data-type, you may add the attribute to the property of your model. Otherwise, you will have to define a mutator for each of the attributes, which can be time consuming. Here is an example of using the property:

Now the attribute will always be cast to a boolean when you access it, even if the underlying value is stored in the database as an integer. Other supported cast types are: , , , , , , and .

The cast is particularly useful for working with columns that are stored as serialized JSON. For example, if your database has a TEXT type field that contains serialized JSON, adding the cast to that attribute will automatically deserialize the attribute to a PHP array when you access it on your Eloquent model:

Now, when you utilize the Eloquent model:

Model Events

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:

Where To Register Event Listeners

Your serves as a convenient place to register your model event bindings. For example:

Model Observers

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:

Model URL Generation

When you pass a model to the or methods, it's primary key is inserted into the generated URI. For example:

In this example the property will be inserted into the place-holder of the generated URL. However, if you would like to use another property instead of the ID, you may override the method on your model:

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.

A Quick Overview of Eloquent’s (Laravel) Mass-assignment Protection May 14, 2013

Posted by Tournas Dimitrios in PHP.
trackback

Laravel’s  ORM (Eloquent) provides a beautiful , simple Active-Record implementation for working with your database . Each database table has a corresponding “Model_Class” which is used to interact with that table . As I’m aware off , many [all] ORM’s had the ability to mass-assign properties directly into the database , which is a   security vulnerability . Mass assignment is something most programmers make use of as it provides an easy (convenient) way to populate the properties of a model object from a form . Unfortunately its simplicity can make it a target for hackers , a submitted form can easily be forged just by using a CLI-tool (CURL) or by using a browser plugin (Firefox’s Firebug) to pass POST parameters to a page . The way to stop this kind of attack is by limiting the attributes that can be set from the form (or from a POST method) .

Basics first :

Active-Record is designed upon the principles of the “Active-Record” design pattern , which was first described by Martin Fowler . The Active -Record pattern has been implemented in many forms across  all  programming languages , the basic concepts remain the same though . A database table is mapped into  a Class (the Model in a MVC paradigm) , and each instance of that Class represents a table row . The tables and rows of the database are abstracted into native PHP objects . This allows the programmer to focus more on manipulating the data and less on writing SQL queries . The following lines of code are just a representation  of what I’m talking about , it’s evident that the code hides (abstracts) the database query language (SQL) .

// Get all records from Users table $users = User::all() ; // How many records of the Users table has been voted more than 100 times $count = User::where('votes', '>', 100)->count(); // Updating a record into Users table User::where('username', '=', 'user3')->update(array('password' => Hash::make('John123')));

To keep things concentrated , most Frameworks apply the “Convention Over Configuration” paradigm  . In our Active Record implementation ,  a User Model Class maps to a Users Database-table (notice the plural and singular expression) . This default convention can be explicitly overwritten though .

Back on track : 

Let’s recap : a Class that implements the Active-Record design pattern is used to interact with our database-tables . All we have to do is  using CRUD operations on an Object that was previously instantiated from the aforementioned  Class  , neglecting the underlying SQL logic . And you might wonder , where is the vulnerability that we talked about at the beginning of this article  . Well let’s be honest , we’re almost always lazy programmers  and prefer to write less code (yes I’m cheating here , assuming that all programmers behave like me ) . Our laziness establishes an assured “achilles heel” into  application’s foundations . Sooner or later a “black hat guy” will discover our application’s vulnerability and most likely he will try to  occupy administrator privileges . In such a scenario , the consequences are evident , I don’t even want to think about it .
A couple years ago (early in 2012 ) , a Russian developer named Homakov , discovered the “Mass Assignment” vulnerability into Github’s website and used this “security hole”  to gain commit access . Github’s web-app was build on Rails , but as aforementioned previously , the concepts remain the same , no matter which programming language is used to implement an Active Record design pattern . Don’t fear , the flaw has since been fixed in Rail’s  and Eloquent (Laravel’s Active Record implementation) , and I’m sure that other ORMs have taken their precautions to .
Do you remember my aforementioned “Convention Over Configuration” paradigm ? This also applies into this situation , the default “set-up” in Laravel’s and Rail’s Active Record implementation is to suspend “mass assignment” functionality , it can be overwritten though .  This restriction protects our application , in case a programmer  skipped to apply basic security practices . There are situations that we don’t need this “strict security model” though ( for instance : during prototyping or development cycle of our application ) .
A practical example will illustrate what this article is trying to describe . First , the code-example shows how mass assignment was done until the restrictions were applied ( after Homakov’s discovery)  .

<?php class UserController extends BaseController { public function save() { $user = new User(Input::all()) ; $user->save() ; // Do other stuff here } }

In the above code , all form submitted fields were inserted into the database-table (mass assignment ) . It’s not shown here , but the code took all precautions to protect our application against SQL-injection , Cross-Site-Scripting XSS and Cross-Site-Request-Forgery CSRF . Mass assignment wasn’t restricted , an hacker had to guess how the database-table indicated an administrator / logged-in user (perhaps a column with a name of : is_loggedIn , is_admin ) . Last step of attacker’s journey was to submit a forged form which contained those column fields into the submitted data and boooom , he gained free access to the web-app .

The following code demonstrates how we could protect our app against the mass assignment vulnerability :

<?php class UserController extends BaseController { public function save() { $user = new User() ; $user->email = Input::get('name'); $user->pnone = Input::get('phone'); $user->name = Input::get('name'); $user->save() ; // Do other stuff here } }

The code above demonstrates the right way to store submitted form data  . We allow only specific field to be stored into the database table .
As aforementioned , by default , mass assignment is disabled in Laravel , we can loosen or disable this restriction though . In Laravel 4 two properties can configure Model’s behavior ($fillable and $guarded ) .

<?php class User extends Eloquent { /* In this example , only the three listed attributes will be mass-assignable. */ protected $fillable = array('first_name', 'last_name', 'email'); } class User extends Eloquent { /* In the example , the id and password attributes may not be mass assigned */ protected $guarded = array('id', 'password'); /* Or blocking all attributes from Mass Assignment */ protected $guarded = array('*'); }

Happy coding .

0 Replies to “Laravel Mass Assignment Example”

Lascia un Commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *