#2 [Illuminate2] Model Guards Attributes on Create

In my first article a few weeks ago, I covered the benefits of a Model-centric approach to Laravel. If you haven’t already, check out that article here.

This week is the second in a long line of tutorials for the Model-centric components I’ve built over the past several months. If you read my first piece, you’ll know that all of my components were originally developed as the result of mish-mash experimentation and hacking something together until it did what I wanted. As I publish this tutorial series, I’ll also be cleaning things up by re-developing each of the components into my new package, helium/illuminate2.

Guards Attributes On Create

Installation

composer require helium/illuminate2

Please note that this package is only compatible with Laravel 8.14 and later, so you should make sure your project is up-to-date with the most recent release.

Fillable On Create

use Helium\Illuminate2\Database\Eloquent\Concerns\GuardsAttributesOnCreate;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
use GuardsAttributesOnCreate;
}

Great! Now all that’s left is to declare your fillable and fillableOnCreate properties.

protected $fillableOnCreate = [
'user_id',
'post_id'
];
protected $fillable = [
'comment'
];

In the given example, the $fillableOnCreate property declares a list of attributes which are only mass-assignable if the object is being created (i.e. not updated). And, as always, the $fillable property declares a list of attributes which are always mass-assignable.

In Practice

$comment = Comment::create([
'user_id' => 1,
'post_id' => 1,
'comment' => 'Hello, World!'
]);
$comment->update([
'comment' => 'Hello, Laravel!'
]);

In the given example, you are able to mass-assign the user_id and post_id while creating the Comment instance, but once they're set, any attempt to mass-assign those attributes on a call to update will result in the changes being ignored.

Guarded On Create

use Helium\Illuminate2\Database\Eloquent\Concerns\GuardsAttributesOnCreate;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use GuardsAttributesOnCreate;
protected $guardedOnCreate = [
'published_at'
];
}

Customization

Please note that the $creationState property shown here is not part of the GuardsAttributesOnCreate trait. Instead, it is intended to demonstrate one the many ways in which you could customize the logic of these getter functions to meet your circumstantial needs.

class Comment extends Model
{
use GuardsAttributesOnCreate;
public static $creationState = 'parent'; public function getFillableOnCreate()
{
if (static::creationState == 'child') {
return ['parent_id'];
}
}
public function getGuardedOnCreate()
{
if (static::creationState == 'parent') {
return ['parent_id'];
}
}
}
class CommentController extends Controller
{
public function create(Request $request)
{
return Comment::create($request->all());
}
public function reply(Request $request)
{
Comment::$creationState = 'child';
return Comment::create($request->all());
}
}

A Word On Philosophy

To understand my particular approach on using Laravel, I encourage you to read my opinion piece The Case For Model-Centric Laravel.

Conclusion

Software That Works