{"id":16549,"date":"2024-01-26T18:00:00","date_gmt":"2024-01-26T18:00:00","guid":{"rendered":"https:\/\/www.directimpactsolutions.com\/?p=16549"},"modified":"2024-01-24T20:41:52","modified_gmt":"2024-01-24T20:41:52","slug":"observers-in-laravel","status":"publish","type":"post","link":"https:\/\/www.directimpactsolutions.com\/en\/observers-in-laravel\/","title":{"rendered":"Observers in Laravel"},"content":{"rendered":"<p>During development on a web project, you may need something to occur when a database table is modified. For example, you might want to send a confirmation notification to a user whenever a record is created. Or you might want to create a record in a log table whenever a record is updated or deleted. Or you might want to sanitize your data before it is sent to the database and strip out any html or script tags.<\/p><p>While you could do this in your controller methods, chances are that you are manipulating a table in multiple places, so you would have to maintain that code in multiple places. A more efficient way to do this is to place the code in Laravel&#8217;s built-in events.<\/p><h2 class=\"wp-block-heading\" id=\"Model-Events\" style=\"font-style:normal;font-weight:400\">Model Events<\/h2><p>Laravel includes a number of events that are triggered during the lifetime of a model. These events correspond to different actions performed on a database table. These events include record creation: updating a record, saving (which is triggered as part creation or updating), and deleting.<\/p><p>There are actually two events that trigger for each of these events; one event occurs before the action occurs, and the other happens after it occurs. For example, the creating event fires before the record is created in the database, while the created event fires once the record has been created. The full list looks something like this:<\/p><ul class=\"wp-block-list\"><li>Creating\/Created<\/li>\n\n<li>Updating\/Updated<\/li>\n\n<li>Saving\/Saved<\/li>\n\n<li>Deleting\/Deleted<\/li>\n\n<li>ForceDeleting\/ForceDeleted<\/li>\n\n<li>Restoring\/Restored<\/li><\/ul><p>Note: performing a mass update or delete (for example &#8211; User::where(&#8216;active&#8217;, &#8216;=&#8217;, 0)-&gt;delete();) will <strong>not<\/strong> trigger an event, since the models are not actually retrieved in these cases. In this case, you might want to retrieve the records and then loop through them to perform the update\/delete.<\/p><p>There are a few ways to tie into these events; below we&#8217;ll look at two of the most common\u2014closures and observers.<\/p><h3 class=\"wp-block-heading has-ast-global-color-2-color has-text-color\" id=\"Closures\">Closures<\/h3><p>Eloquent models have a static method defined for each event (created, updated, deleted, etc.), which can be used to register closures for each event. These closures are defined in the model&#8217;s booted method.<\/p><p>We&#8217;ll use the example of a simple table used to store appointments. When an appointment is created, we want to send an AppointmentNotification (which we&#8217;ll assume has already been created in the system) to the User associated with the Appointment.<\/p><p>use App\\Notifications\\AppointmentNotification;<br>use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;<br>use Illuminate\\Database\\Eloquent\\Model;<\/p><pre class=\"wp-block-code\"><code>use App\\Notifications\\AppointmentNotification;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Appointment extends Model\n{\n    use HasFactory;\n\n    \/\/ ***********************************\n    #region Booted\n    \/\/ ***********************************\n    protected static function booted() {\n        parent::booted();\n\n        static::created(function (Appointment $appointment) {\n            $appointment->user()->notify(new AppointmentNotification($appointment));\n        });\n    }\n    #endregion\n\n    \/\/ ***********************************\n    #region Relationships\n    \/\/ ***********************************\n    public function user() {\n        return $this->belongsTo(User::class);\n    }\n    #endregion\n}<\/code><\/pre><p>In the example above, you\u2019ll notice that we added this line to the booted method of the appointment class:<\/p><pre class=\"wp-block-code\"><code>        $appointment->user()->notify(new AppointmentNotification($appointment));<\/code><\/pre><p>This tells Laravel that after an appointment has been created, we want to retrieve the user associated with the Appointment, then send an Appointment Notification to that user.<\/p><p>If you want to run the code in the background, you can register the event as queueable. This will execute the event listener in the application&#8217;s queue:<\/p><pre class=\"wp-block-code\"><code>use function Illuminate\\Events\\queueable;\n\n\/\/...\n\nstatic::created(queueable(function (Appointment $appointment) {\n    \/\/ ...\n}));<\/code><\/pre><h3 class=\"wp-block-heading has-ast-global-color-2-color has-text-color\" id=\"Observers\">Observers<\/h3><p>If you need to listen for multiple events on a model, you might want to group them together using an observer. An observer is an object that has methods for each of the model events, each of which receives the affected model as an argument. Observers are created with an Artisan command:<\/p><p>php artisan make:observer AppointmentObserver &#8211;model=User<\/p><p>This command creates a the new observer in the app\/Observers directory. When first created, the observer will look like something like this:<\/p><pre class=\"wp-block-code\"><code>use App\\Models\\Appointment;\n\nclass AppointmentObserver\n{\n    \/**\n     * Handle the Appointment \"created\" event.\n     *\/\n    public function created(Appointment $appointment): void\n    {\n        \/\/ ...\n    }\n\n    \/**\n    * Handle the Appointment \"updated\" event.\n    *\/\n    public function updated(Appointment $appointment): void\n    {\n        \/\/ ...\n    }\n    \n    \/**\n    * Handle the Appointment \"deleted\" event.\n    *\/\n    public function deleted(Appointment $appointment): void\n    {\n        \/\/ ...\n    }\n}<\/code><\/pre><p>We can now add our code for sending the Appointment Notification to the created method:<\/p><pre class=\"wp-block-code\"><code>use App\\Notifications\\AppointmentNotification;\n...\n\npublic function created(Appointment $appointment): void\n{\n    $appointment->user()->notify(new AppointmentNotification($appointment));\n}<\/code><\/pre><p>Once the observer is created, you will need to register it in the <strong>boot<\/strong> method of the <strong>App\\Providers\\EventServiceProvider<\/strong> class to start listening for events.<\/p><pre class=\"wp-block-code\"><code>use App\\Models\\Appointment;\nuse App\\Observers\\AppointmentObserver;\n\n\/**\n\nRegister any events for your application.\n*\/\npublic function boot(): void\n{\n Appointment::observe(AppointmentObserver::class);\n}<\/code><\/pre><p>Alternately, you can list the observers in the <strong>$observers<\/strong> property of the <strong>App\\Providers\\EventServiceProvider<\/strong> class.<\/p><pre class=\"wp-block-code\"><code>use App\\Models\\Appointment;\nuse App\\Observers\\AppointmentObserver;\n\n \/**\n\nThe model observers for your application.\n\n@var array\n*\/\nprotected $observers = &#91;\n Appointment::class => &#91;AppointmentObserver::class],\n];<\/code><\/pre><h3 class=\"wp-block-heading has-ast-global-color-2-color has-text-color\" id=\"Muting-Events\">Muting Events<\/h3><p>Occasionally, you might need to run a command on the model without triggering any events; there are a couple ways to do this. The <strong>withoutEvents<\/strong> method accepts a closure as its argument; any code run inside this close will not trigger an event.<\/p><pre class=\"wp-block-code\"><code>use App\\Models\\Appointment\n\n$appointment = Appointment::withoutEvents(function() {\n    $appointment = Appointment::findOrFail(1)->update&#91;'cancelled=>true]);\n   ....\n    return $appoitnment\n});<\/code><\/pre><p>Using <strong>withoutEvents<\/strong> is convenient if you are modifying multiple records, or performing multiple actions on a model. If you need to run a single action on a model, you can use use methods like <strong>saveQuietly<\/strong>, <strong>deleteQuietly<\/strong>, <strong>forceDeleteQuietly<\/strong> and <strong>restoreQuietly.<\/strong><\/p><pre class=\"wp-block-code\"><code>$appointment = Appointment::findOrFail(1);\n$appointment->cancelled = true;\n$appointment->saveQuietly();<\/code><\/pre><h2 class=\"wp-block-heading\" id=\"Conclusion\" style=\"font-style:normal;font-weight:400\">Conclusion<\/h2><p>We hope that this helps to clarify the role of observers in Laravel, and that you have a better idea of when and how to use them. If you have a Laravel project in mind, we would be happy to assist. <a href=\"https:\/\/www.directimpactsolutions.com\/en\/contact-us\/\">Send us a note<\/a> and we\u2019ll be in touch.<\/p>","protected":false},"excerpt":{"rendered":"<p>During development on a web project, you may need something to occur when a database table is modified. For example, you might want to send a confirmation notification to a user whenever a record is created. Or you might want to create a record in a log table whenever a record is updated or deleted. &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"\" href=\"https:\/\/www.directimpactsolutions.com\/en\/observers-in-laravel\/\"> <span class=\"screen-reader-text\">Observers in Laravel<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":9,"featured_media":16551,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","footnotes":""},"categories":[32],"tags":[],"class_list":["post-16549","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-applications"],"uagb_featured_image_src":{"full":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading.png",500,300,false],"thumbnail":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading-150x150.png",150,150,true],"medium":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading-300x180.png",300,180,true],"medium_large":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading.png",500,300,false],"large":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading.png",500,300,false],"1536x1536":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading.png",500,300,false],"2048x2048":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading.png",500,300,false],"woocommerce_thumbnail":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading-300x300.png",300,300,true],"woocommerce_single":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading.png",500,300,false],"woocommerce_gallery_thumbnail":["https:\/\/www.directimpactsolutions.com\/wp-content\/uploads\/2024\/01\/Add-a-heading-100x100.png",100,100,true]},"uagb_author_info":{"display_name":"Alan Bruce","author_link":"https:\/\/www.directimpactsolutions.com\/en\/author\/alan-bruce\/"},"uagb_comment_info":0,"uagb_excerpt":"During development on a web project, you may need something to occur when a database table is modified. For example, you might want to send a confirmation notification to a user whenever a record is created. Or you might want to create a record in a log table whenever a record is updated or deleted.&hellip;","_links":{"self":[{"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/posts\/16549","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/comments?post=16549"}],"version-history":[{"count":1,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/posts\/16549\/revisions"}],"predecessor-version":[{"id":16550,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/posts\/16549\/revisions\/16550"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/media\/16551"}],"wp:attachment":[{"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/media?parent=16549"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/categories?post=16549"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.directimpactsolutions.com\/en\/wp-json\/wp\/v2\/tags?post=16549"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}