Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cristian9509's avatar

Jobs, Events & Listeners

I am trying to wrap my head around these concepts. I understand a bit the workflow but I would love some input, as to when, which and why to use.

So here is an example: User registers and then will need to create a Stripe Subscription.

User registration: I will need to create a user (CreateUser) here and then send them an welcome email (SendWelcomeEmail)

StripeSubscription: Here I will need to do multiple things. When a user first signs up with my app I would need to create a new subscription with Stripe (CreateNewSubscription). Later if they want to change something to their subscription they can cancel (CancelSubscription), resume a cancelled but on grace period subscription (ResumeSubscription) or reactivate a cancelled and expired subscription (ReactivateSubscription). All these actions done by the user would also require that I send them emails based on the action they took.

What should be done by a Job and what should be done by an Event?

Jobs: UserCreate, SubscriptionCreate, SubscriptionCancel, SubscriptionCancel, SubscriptionReactivate? Events: emailUserCreate, emailSubscriptionCreate, etc?

0 likes
6 replies
toniperic's avatar

You should try to express yourself more clear if you want to receive some help.

Just to name a few - I have no idea what UserCreate, StripeRegistration, CreateNewSubscription or emailUserCreate mean in your context, or the context of your app.

Maybe try explaining one at a time.

MarkRedeman's avatar

An event is something that has happened. For example you could have a UserRegistered event or a UserSubscirbedToPlan event.

A job is something that you want to happen (in other communities instead of jobs we often talk about commands). Most of the time a job / command produces events. For example you could have a RegisterUser job, or a SubscribeUserToPlan job. When these jobs don't fail then they produce UserRegistered and UserSubscirbedToPlan events, which, for example, you can listen to in your event listeners such that you can make sure that the user receives an email.

Events and jobs can be a great tool to communicate the intent of your application. Often when you only look at the events that are produced by your application you can already have a good idea about the goal of your app. As to when you should use a job and / or a event: I often dispatch a new event whenever something special happens and when as a result some other process should start. So when a user has registered, then:

  1. The user should get a welcome email
  2. A new account should be opened on our billing service (Stripe for example)
  3. Send our support team an email notifying them about the new customer

I use a job when I want to clearly show my intent of some action or when I have some kind of action that I want to be available both on our webpage and on a cli tool. However this mostly depends on the type of application you are working on and on what workflow you and your team prefers.

2 likes
cristian9509's avatar

@MarkRedeman Thank you for your answer. I think I am getting closer to putting the bits together. So a simple breakdown for a user registration would be like this:

RegistrationController: receives user input and dispatches a CreateUserJob
UserCreateJob: attempts to create the user and if success it fires an UserCreatedEvent
UserCreatedEvent:can have many listeners which could be anything like: SendWelcomeEmail, CreateBillingAccount, etc

Now, my only remaining questions are: why should I create a Job like CreateUserJob a dispatch it form let's say the controller?

Is it because I might have to do multiple things inside the controller and the best way would do to create multiple jobs that get dispatched inside the controller? Is it because I might reuse the Job and therefore it is best to separate it?

@toniperic I updated my question to provide better understanding for the example I provided!

mehany's avatar

@cristian9509 I have opened this thread a while ago and I got some answers, hope this may get you closer to understanding this patten.

why should I create a Job like CreateUserJob a dispatch it form let's say the controller?
I believe you are right. You will be able to re-use it else where without duplicating the code, say from an admin controller that is being used by an admin page in the application or by a purchase controller where a user could subscribe to the site on checkout page.
mehany's avatar

I learned that: Jobs usually are something that needs to happen and events respond to something that happened ( @jekinney ) which is pretty much what @MarkRedeman said.

MarkRedeman's avatar

There are multiple advantages and disadvantages of using jobs / commands. One of the advantages is that you can easily reuse a command for example @mehany mentioned that you can use the same RegsiterUser job to register a user both on your registration page and on your administration page. There are two other nice advantages of using jobs / command (I'm going to call them commands from now on). When using commands you often use a CommandBus to dispatch, or handle, the command. Laravel is shipped with a default implementation of the bus, another implementation is Tactician (If you want to read more about the command bus then you should read their documentation, it's pretty good :) ). Using the command bus has the advantage that you can use middlewares that are executed before your command is handled. For example I could have a logging middleware that logs the name of each command and the name of the user that is currently logged in whenever a command is handled by the command bus. Another middleware example is a transaction middleware which would look something like this:

<?php

use Illuminate\Database\DatabaseManager;

class UseDatabaseTransactions {

    /**
     * DatabaseManager
     */
    private $db;

    /**
     * Use the
     */
    public function __construct(DatabaseManager $db)
    {
        $this->db = $db;
    }

    /**
     * Wrap the execution of a command inside of a database transaction
     *
     * @param  $command
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($command, $next)
    {
        return $this->db->transaction(function() use ($command, $next)
        {
            return $next($command);
        });
    }

}

By using this middleware whenever a command has made changes to the database, but throws an exception later on, then the state of the database will be reverted.

Middleware can be a really nice tool to have and will act on all commands.

Another nice advantage is that Laravel has the ShouldQueue interface. By adding this interface to your command it will be automatically put on the queue. This is great if your have a command whose only responsibility is notifying some service. As an example: at a current project I have a NotifyWebmaster($companyId, $email) command that adds a webmaster account to our Intercom app. This command is placed on the queue so that the user does not have to wait for a response of the intercom api.

In one project we only used commands inside of our controllers which made our controllers very thin and easily understandable. But it came with the disadvantage that in order to add a new feature you had to write some additional boilerplate code that would not have been necessary without the commands. In the end I personally belief this was worth it since it added much more consistency to our codebase.

Ross Tuck has a really nice presentation about this concept called Models & Service Layers; Hemoglobin & Hobgoblins , you should probably go and watch it. :)


I haven't gone into whether a command should return something, which is a topic of its own. If you're interested in this topic you should look up CQS (Command Query Seperation) and CQRS (Command Query Responsibility Segregation)

1 like

Please or to participate in this conversation.