When writing applications, it is often necessary to weave functionality through the events that occur to an object of a class that you have created. For instance, in this example that I will briefly go through — taken from Jeffrey Way’s Laracasts TDD course — there is this concept of keeping an activity log associated to a given project.
Now, given that ‘Project’ is a class, and that any given instantiation of that class would be the ‘object’ in question, there are a few different ways of tying in functionality to the events surrounding a ‘Project’.
In the app, ‘Projects’ has ‘Tasks’ associated to them. In the picture above, there is a simple example of a ‘recordActivity’ method being called when a ‘Task’ is created or deleted. Not pictured, is a hook for when the ‘Project’ itself is created, deleted, or updated.
The reason this is significant is because this allows for dynamism in the app. For instance, lets imagine that a ‘Project’ could be updated via 3 different ways:
- The project’s fields could be changed
- The project could have tasks added or removed
- The project could be archived or deleted
With no lifecycle hooks, we are adding the code to ‘create an activity’ within every single function call.. well.. thats redundant. Programming is all about reusing logic and making efforts more efficient. What if the logic needed to change? Now we are in the classic situation of having to change all references everywhere. Well, the first thing you should ask is: “Why don’t we just abstract that functionality into it’s own function, and then just call it there?”. Well, yes! That’s exactly what we will do.
Really, the only difference between that solution and the solution of utilizing lifecycle hooks is that the lifecycle hooks are essentially pre-generated abstracted methods that are simply waiting to be populated with functionality, and can respond to most operations you can imagine.
A few ways to tie into Model lifecycle hooks:
- Listen to them in the web.php router file
This is an ugly, inefficient and frankly disorganized approach towards achieving this goal… let’s see how else we can do this.
2. Accessing them from within the Model itself
This approach is fairly organized and can be attractive if your need to access lifecycle hooks is limited. This works by first overriding the ‘boot’ method, which gets called whenever an Object is instantiated from a Class, and then by further overriding the various hook methods from within the Model, as before. Now, if your need for plugging into a Model’s lifecycle hooks is plentiful and involves multiple abstracted sub-functions, then consider the next approach..
3. Creating an Observable Class
This approach involves creating a new class ( using a handy artisan command “php artisan make:observable -model=ModelName” ) and then registering it within the AppServiceProvider. What this does is then give you specific access into each and every lifecycle hook ( pre-generated by Laravel ). With this, if necessary, you can then produce whatever logic necessary to complete anything you’d like to have happen.