DEV Community

Cover image for Laravel101: The Role of Mass Assignment in Eloquent Model
Kazem
Kazem

Posted on

Laravel101: The Role of Mass Assignment in Eloquent Model

Clean and readable code is an important aspect that distinguishes experienced programmers from beginners. Achieving this level of code quality requires experience and observation. While each framework has its own set of rules, I’ll focus on sharing some helpful principles within the context of the Laravel framework in this training course.

In our previous article, we discussed the REST Architecture which with its template enhance our code readability inside our controllers. Now, let’s explore the concept of mass assignment and the a tool called Request.


Before we begin, let’s take a moment to understand the output of the validate function:

Image description

An essential aspect to understand about the validate function is that it exclusively returns an array of data that conforms to the rules you have specified. In other words, even if a user attempts to send an injected field to our server, the validate function will only return the information that we have defined! This helps to maintain the integrity and security of our server-side data processing:

$data = request()->validate([
    'title' => 'required|min:3|max:120|unique:tasks,title',
    'description' => 'nullable|min:3|max:255',
    'expired_at' => 'nullable|date|after:now'
]);

Task::create($data);
Enter fullscreen mode Exit fullscreen mode

See? It’s much more readable now. Let’s proceed and make a request to see the results:

Image description

The reason for the error you encountered is that models in Laravel, by default, prevent mass assignment to avoid accepting incorrect values. For example, if you haven’t properly defined the validation rules, sensitive user information like email or password could be set incorrectly. Laravel wants to ensure you’re aware of this potential issue. Luckily, we have two solutions to change this default behavior.

One solution is to use the fillable property, which is an array of fields that you want to allow for mass assignment

protected $fillable = ['attribute'];
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can use the guarded property, which works the opposite way by allowing you to specify the fields you don't want to be mass assignable:

protected $guarded = ['attribute'];
Enter fullscreen mode Exit fullscreen mode

In our example, we need to include one of these properties in our model:

Image description

I personally prefer to use an empty array of guarded

Now, let’s explore another useful tool within Laravel called FormRequest, which allows us to separate request validation from our controller. This separation enhances code clarity and organization.

By creating a Request class, we can define the validation rules specific to that request, keeping our controller focused on handling the business logic.

To create a Request class, we can use the following artisan command:

php artisan make:request <request-name>
Enter fullscreen mode Exit fullscreen mode

Additionally, Laravel provides convenient options when using the make:model artisan command.

For example, you can include the -c option to generate a new controller for the model, the -r option to indicate that the generated controller should be a resource controller, the -m option to create a new migration file for the model, and the -R option to create new form request classes and automatically use them in the resource controller:

php artisan make:model <model-name> -c -r -m -R
Enter fullscreen mode Exit fullscreen mode

Well, let’s back to our project add a request for our store function:

php artisan make:request StoreTaskRequest
Enter fullscreen mode Exit fullscreen mode

Once created, you can open the StoreTaskRequest file inside directory app/Http/Requests and define your validation rules inside the rules method:

(Hint: I just drop unique rule for title to make it more sense! )

class StoreTaskRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'title' => 'required|min:3|max:120',
            'description' => 'nullable|min:3|max:255',
            'expired_at' => 'nullable|date|after:now'
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

By default, there is an authorize function too that you can decide if an user is authorized to make this request, right? for now just set its value true to let anyone has access to do request.

In addition to the rules, you can also customize the error messages by overriding the messages method in your FormRequest file:

public function messages(): array
{
    return [
        'title.required' => 'Hey, don\'t forget to fill in your title!',
        'title.min' => 'Oops! Your name should be at least three characters long.',
        'description.min' => 'Hold up! The description too short!!!',
    ];
}
Enter fullscreen mode Exit fullscreen mode

Now let’s use it!

To achieve that, we can inject the StoreTaskRequest class into the store method of our controller. This allows Laravel to handle the validation process automatically. If the validation fails, the user will be redirected back to the previous page, along with the error messages. On the other hand, if the validation passes successfully, the controller method will be executed.

Image description

In the picture above, to obtain validated data, you can use the validated method. If you don't specify any keys as input for the validated function, it will return all the keys defined in the rules array. Alternatively, if you only want specific keys or an array of desired ones, you can simply pass them as input to the function. It's straightforward, right?

Now Let’s do same thing for our update method and make the UpdateTaskRequest for update function:

php artisan make:request UpdateTaskRequest
Enter fullscreen mode Exit fullscreen mode

And update UpdateTaskRequest as follow:

class UpdateTaskRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'title' => 'required|min:3|max:120',
            'description' => 'nullable|min:3|max:255',
            'expired_at' => 'nullable|date|after:now'
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

Again to use that we only need to we can easily include the UpdateTaskRequest class as a parameter in the update method of our controller, But this time we have to apply the update method on binding model, as shown below:

public function update(Task $task, UpdateTaskRequest $request)
{
    $task->update($request->validated());
    return redirect("/tasks");
}
Enter fullscreen mode Exit fullscreen mode

And that brings us to the end of this article. We’ve covered how to refactor our code and improve its clarity. In the next article, we’ll dive into authorization within Laravel. I hope you found this article enjoyable and informative. Stay tuned for more!

Top comments (2)

Collapse
 
sreno77 profile image
Scott Reno

Very nice! Custom request classes are awesome

Collapse
 
kazemmdev profile image
Kazem • Edited

Yeah, They are very helpful and clean