Steven Maguire
I've been building web software since 2004.
"Captures the memory of something interesting which affects the domain" - Martin Fowler
http://martinfowler.com/eaaDev/DomainEvent.html
User
Plan
Payment
Account
Tweet
Refund
registered
changed
processed
posted
flagged
notified
deleted
User
Plan
Payment
Account
Tweet
Refund
registered
selected
processed
activated
posted
flagged
notified
deleted
\\ App\Services\OrderManager@processOrder
$order = $this->createOrder($attributes);
$user = $this->getCurrentUser();
$user->addOrder($order);
$payment = $this->processPayment($order);
$user->sendReceipt($order);
\\ App\Services\OrderManager@processOrder
$order = $this->createOrder($attributes);
$user = $this->getCurrentUser();
$user->addOrder($order);
$payment = $this->processPayment($order);
if ($payment) {
$user->sendReceipt($order);
} else {
throw new FailedPaymentException();
}
\\ App\Services\OrderManager@processOrder
$order = $this->createOrder($attributes);
$user = $this->getCurrentUser();
$user->addOrder($order);
$payment = $this->processPayment($order);
if ($payment) {
$user->sendReceipt($order);
if ($user->isNew()) {
$user->sendWelcome();
}
} else {
throw new FailedPaymentException();
}
\\ App\Services\OrderManager@processOrder
$order = $this->createOrder($attributes);
$user = $this->getCurrentUser();
$user->addOrder($order);
$payment = $this->processPayment($order);
if ($payment) {
if ($user->isNew()) {
$user->sendWelcomeReceipt($order);
} else {
$user->sendReceipt($order);
}
} else {
throw new FailedPaymentException();
}
You saw it coming.
en.wikipedia.org/wiki/Cyclomatic_complexity
Change
Risk
Anti
Patterns
php artisan make:event UserWasRegistered
php artisan make:event PlanWasChanged
php artisan make:event PaymentWasProcessed
php artisan make:event TweetWasPosted
// App\Events\UserWasRegistered;
public function __construct(User $user)
{
$this->user = $user;
}
// App\Events\PlanWasChanged;
public function __construct(Plan $plan)
{
$this->plan = $plan;
}
// App\Events\PaymentWasProcessed;
public function __construct(Payment $payment)
{
$this->payment = $payment;
}
// App\Events\TweetWasPosted;
public function __construct(Tweet $tweet)
{
$this->tweet = $tweet;
}
Inject event subject(s)
<?php namespace App\Events;
use Carbon\Carbon;
abstract class Event {
public $created_at;
public function __construct()
{
$this->created_at = Carbon::now();
}
}
Capturing time information in base class
// App\Events\UserWasRegistered;
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
}
php artisan handler:event SendWelcomeEmail --event=UserWasRegistered
php artisan handler:event AssignDefaultPlan --event=UserWasRegistered
php artisan handler:event ProcessPayment --event=PlanWasChanged
php artisan handler:event SendReceiptEmail --event=PaymentWasProcessed
php artisan handler:event RetweetMention --event=TweetWasPosted
// App\Handlers\Events\SendWelcomeEmail
public function __construct(
Illuminate\Contracts\Mail\Mail $mail)
{
$this->mail = $mail
}
public function handle(UserWasRegistered $event)
{
$user = $event->user;
$this->mail->send('email.view',
['name' => $user->name],
function($message) use ($user)
{
$message->to($user->email, $user->name)
->subject('Welcome!');
}
);
}
Inject required services
Use service to handle event
// App\Providers\EventServiceProvider
protected $listen = [
'App\Events\UserWasRegistered' => [
'App\Handlers\Events\SendWelcome',
'App\Handlers\Events\AssignDefaultPlan',
],
'App\Events\PlanWasChanged' => [
'App\Handlers\Events\ProcessPayment',
],
'App\Events\PaymentWasProcessed' => [
'App\Handlers\Events\SendReceiptEmail',
],
'App\Events\TweetWasPosted' => [
'App\Handlers\Events\RetweetMention',
],
];
php artisan event:generate
// App\User
use App\Events\UserWasCreated;
use Illuminate\Support\Facades\Event;
class User extends Eloquent
{
//
public static function createUser($attributes = [])
{
$user = static::create($attributes);
if ($user) {
$result = Event::fire(new UserWasCreated($user));
}
return $user;
}
//
}
// App\Handlers\Commands\CreateUser
use App\User;
use App\Events\UserWasCreated;
use Illuminate\Support\Facades\Event;
// using statements for base Command and SelfHandling contract
class CreateUser extends Command implements SelfHandling {
{
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
// Handle the logic to create the $user...
$result = Event::fire(new UserWasCreated($user));
}
}
// App\Services\Registrar
use App\User;
use App\Events\UserWasCreated;
use Illuminate\Support\Facades\Event;
use Illuminate\Contracts\Auth\Registrar as RegistrarContract;
class Registrar implements RegistrarContract
{
public function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
if ($user) {
Event::fire(new UserWasCreated($user));
}
return $user;
}
}
// App\Http\Controllers\UserController
use App\User;
use App\Events\UserWasCreated;
use Illuminate\Support\Facades\Event;
class UserController extends Controller
{
public function postRegisterUser(Request $request)
{
$user = new User($request->input());
if ($user) {
$result = Event::fire(new UserWasRegistered($user));
}
return $user;
}
}
github.com/stevenmaguire/ifttt-demo
(bit.ly/laravel-events-demo)
Sprinkle in for style
// App\Handlers\Events
class UserEventHandler {
public function onUserRegistration($event)
{
//
}
public function subscribe($events)
{
$events->listen('App\Events\UserWasRegistered',
'App\Handlers\Events\UserEventHandler@onUserRegistration'
);
}
}
Event::subscribe('App\Handlers\Events\UserEventHandler');
Include in boot() method of Service Provider
If that tickles your fancy
Event::listen('App\Events\UserWasRegistered', function($event)
{
// Handle the event...
});
Include in boot() method in Service Provider
Event::listen('App\Events\UserWasRegistered', function($event)
{
// Handle the event...
return false;
});
Stopping the propagation of an Event
Queues FTW
php artisan handler:event SendWelcomeEmail \
--event=UserWasRegistered --queued
--queued flag generates handler with queue support
// App\Handlers\Events\SendWelcomeEmail
public function handle(UserWasRegistered $event)
{
if (true)
{
$this->release(30);
}
}
laravel.com/docs/5.0/queues
use Illuminate\Support\Facades\Event;
//
Event::fire(new UserWasCreated($user));
event(new UserWasCreated($user));
@stevenmaguire
on twitter
stevenmaguire@gmail.com
on electronic mail
stevenmaguire
on github
By Steven Maguire
Deck originally created for a presentation to a gathering of the Chicago Laravel Meetup group - bit.ly/laravel-events