Laravel101: The Role of Mass Assignment in Eloquent Model
Tags: laravel, php, laravel101
Published: 2023-08-11 05:01:48

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6n2aw9lletnf4xrogqre.png)

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:
```php
$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);
```
See? It’s much more readable now. Let’s proceed and make a request to see the results:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9g4fw6s6ba7t22jxwtd.png)

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
```php
protected $fillable = ['attribute'];
```
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:
```php
protected $guarded = ['attribute'];
```
In our example, we need to include one of these properties in our model:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh18jcx9xrbf9phx4zl0.png)


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
php artisan make:request <request-name>
```
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:
```sh
php artisan make:model <model-name> -c -r -m -R
```
Well, let’s back to our project add a request for our store function:
```sh
php artisan make:request StoreTaskRequest
```
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! )
```php
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'
        ];
    }
}
```
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:
```php
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!!!',
    ];
}
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1x74sxxdx05mucajoar.png)


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
php artisan make:request UpdateTaskRequest
```
And update `UpdateTaskRequest` as follow:

```php
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'
        ];
    }
}
```

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:
```php
public function update(Task $task, UpdateTaskRequest $request)
{
    $task->update($request->validated());
    return redirect("/tasks");
}
```

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!