joyparkma's avatar

Laracasts Command Bus

Hello,

I am trying to build a Laravel e-commerce site, in which the "Command Bus" approach is used.

I have a question about handling placing an order.

I guess when user places an order, the followings things will happen:

  • Charge user credit card
  • Create an order object
  • Raise an event of order has been created
  • Persistent the order
  • Send user "order confirmation" email

In the handler:


$data = [ 'amount' => 10, ... ] // Charge user $this->payment->charge($data); // Create an order $order = Order::place($data) // Save order to database $this->orderRepo->persistent($order); // Dispatch events $this->dispatchEventsFor($order);

In the order model:

public static function place($data)
{
$order = new static($data);

$order->raise(new OrderWasPlaced($order));

return $order;
}

Then we will send the email to user in the event listener, I'd like to have order_id to query the database about order info, however by the time the event OrderWasPlaced was raised, we have not saved the order object to database yet. Should I persistent the order object first, then raise an OrderWasPlaced event?

0 likes
7 replies
pobble's avatar
pobble
Best Answer
Level 3

Yes. If it hasn't been persisted then the order is still floating about and hasn't really been placed.

joyparkma's avatar

Actually, @pobble, in the Jeffery way's example, he raises the event "UserWasRegistered" before the user was saved to database.

pobble's avatar

Yeah, but you know! What if something went wrong saving the order? Your going to trigger an event that didn't really happen.

Jeff's tutorials are fantastic. God knows I'd still be programming in the dark ages if they weren't. But don't do everything parrot fashion

1 like
joyparkma's avatar

An alternative approach is to generate an unique order number when we create the order object:

In the order model:

public static function place($data)
{
    $data['order_number'] = OrderNumber::generate();
    $order = new static($data);

    $order->raise(new OrderWasPlaced($order));

    return $order;
}

Then in the Event Listener, we can use the order number to query the number. It makes sense an order has id(for database) and order number (for business rule).

RayRutjes's avatar

I just wanted to give some more info on this one, I think nothing is wrong with Jeff's example, and nothing was wrong with this one either:

public static function place($data)
{
$order = new static($data);

$order->raise(new OrderWasPlaced($order));

return $order;
}

First of all raising the event doesn't dispatch it. Moreover the OrderWasPlaced event reflects that the order was indeed placed, that was the intention, even if it has not been persisted. If something goes wrong or you really need to ensure that the events are only dispatched if the persistance is ok, then do that check and only dispatch if all goes fine. You could also create a new event like OrderWasPersisted raised when the order was correctly persisted, then you would give a maximum flexibility to other devs to hook into your code.

1 like

Please or to participate in this conversation.