Search code examples
phplaravellaravel-5.4

Laravel how to call a method of the job class before and after execution


I have a problem working with laravel queues. Since I'm working with scaling architechture, most everything I do is implemeted using queues and jobs. For example, when processing large files, a job is created for every 1000 rows in the file and the result is saved into output file.

I have a "Process" class that I'm currently using as a parent for the jobs. The process class has start() and end() methods that should be called once the job handle() method is called and after the method is executed. The current solution is to call these methods from the handle method, but the problem is that this solution increases unneccesary code in the job class itself and is up to the implementer to remember to call these methods.

public function handle()
{
    $this->start(); // <- implementer has to remember to call this

    // Do the actual handle functionality

    $this->end(); // <- and this
}

So I was wondering wether there is a "clean" way of doing this that does not require parent method calls from the job (child) class? I tried using queue events but the job class cannot be constructed from the given event object. Dispatching an event from the job doesn't really help, since you would still have to add those two extra lines in each of the job classes.

Outside of laravel specific implementations I also looked into the magic __call() method, but that would only work if the "handle" method didn't exist, which isn't really optimal considering that the artisan make:job command generates the method by default (again requiring the implementer to be savvy enough to remove it).

To be clear about this, the current solution does indeed work but it seems like a code smell to be duplicating the same lines for each and every class.


Solution

  • You can create a parent class that will have the handle function, and he will call a protected function in the child that will have your logic, for example :

    class MyJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        protected function start() {
            // your start logic
        }
    
        protected function stop() {
            // your stop logic
        }
    
        protected function process() {
            // will be overrittten
        }
    
        public function handle() {
            $this->start();
            $this->process();
            $this->stop();
        }
    }
    

    And all your jobs will extend your class, for example:

    class SpecificJob extends MyJob
    {
        protected function process() {
             // logic
        }
    }