Upgrade to Pro — share decks privately, control downloads, hide ads and more …

I Didn't Know Laravel Could Do That!

I Didn't Know Laravel Could Do That!

If you’re into to Laravel, you’ve probably already tried out the basic MVC features. What you probably haven’t gotten to yet is all of the amazing features that make Laravel truly a “full stack” framework. In this talk, we’ll cover queueing jobs, send emails, search, browser tests, event broadcasting and more. This will be a great crash course on letting Laravel do the heavy lifting for you, and making sure you know what it’s capable of so you don’t accidentally reinvent the wheel.

Josh Butts

April 20, 2018
Tweet

More Decks by Josh Butts

Other Decks in Technology

Transcript

  1. About Me • SVP of Engineering,
 Ziff Davis • Austin

    PHP Organizer • github.com/jimbojsb • @jimbojsb 2
  2. Preface • I really used to dislike Laravel • I

    used to thing everyone had a smug sense of superiority • I used to think the only way to write PHP was explicitly • I’ll admit it, I was wrong 3
  3. Laravel Queues - Why? • Offload slow tasks to asynchronous

    back- end processes • Keep web response time snappy • Especially for integrations with remote services • Things that have complex failure models 6
  4. Laravel Queues • Built in to the framework • Various

    drivers for the queue service of your choice • Many other first-class parts of the framework are natively queue-able 7
  5. Configuring Queues • Set the queue driver of your choice

    in your .env file (you don’t want sync) • Use artisan to make a failed jobs table (optional) • If using DB driver, use artisan to make a jobs table • Set up credentials for whatever queue service you need in config/queue.php or .env 8
  6. <?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use

    Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class MessageLoggerJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * Create a new job instance. * * @return void */ public function __construct($message) { } /** * Execute the job. * * @return void */ public function handle() { } }
  7. use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class MessageLoggerJob implements ShouldQueue

    { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; private $message; public $tries = 5; public $timeout = 600; public $delay = 5; /** * Create a new job instance. * * @return void */ public function __construct($message) { $this->message = $message; } /** * Execute the job. * * @return void */ public function handle() { logger()->info($this->message); } }
  8. <?php namespace App\Http\Controllers; use App\Jobs\MessageLoggerJob; use Illuminate\Http\Request; class JobDispatcherController extends

    Controller { public function index(Request $request) { $job = new MessageLoggerJob($request->get('message')); dispatch($job); } }
  9. Laravel Horizon • Fancy dashboard to manage all your queues

    • Has baked in assumptions about your deployment infrastructure • Manages supervisors for queue workers 21
  10. Sending Emails • Uses SwiftMailer under the hood • Create

    objects to represent emails • Email objects are natively queue-able • Email bodies are rendered using blade • Emails are natively aware of Laravel users for name and email address 24
  11. use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class WelcomeEmail extends Mailable

    { use Queueable, SerializesModels; public function __construct() { // } public function build() { return $this->view('view.name'); } }
  12. class WelcomeEmail extends Mailable { use Queueable, SerializesModels; private $user;

    public function __construct(User $user) { $this->user = $user; } public function build() { return $this->view('welcome.blade.php'); } }
  13. class WelcomeEmail extends Mailable implements ShouldQueue { use Queueable, SerializesModels;

    private $user; public function __construct(User $user) { $this->user = $user; } public function build() { $this->subject("Welcome to Our App"); $this->from("[email protected]"); return $this->view('welcome.blade.php'); } }
  14. <html> <body> <h1>Welcome to our app, {{$user->name}}</h1> <p>Please confirm your

    email, <a href="{{url(route("email_confirm"))}}">click here</a> </p> </body> </html>
  15. <?php namespace App\Http\Controllers; use App\Mail\WelcomeEmail; use App\User; use Illuminate\Http\Request; use

    Illuminate\Support\Facades\Mail; class MailSenderController extends Controller { public function index(User $user) { $mail = new WelcomeEmail($user); Mail::to($user)->send($mail); } }
  16. <?php namespace App\Http\Controllers; use App\Mail\WelcomeEmail; use App\User; use Illuminate\Http\Request; use

    Illuminate\Support\Facades\Mail; class MailSenderController extends Controller { public function index(User $user) { $mail = new WelcomeEmail($user); Mail::to($user)->queue($mail); } }
  17. Nobody ever wants to build search • Good news, its

    basically free in Laravel • Well, free as free time, but not necessarily free as in beer • Works best with Algolia, which is totally worth whatever you pay them 35
  18. Drawbacks • Scout is EASY • There are tradeoffs •

    Scout hides the true power of Algolia and other engines 47
  19. Wait I already knew this one • Laravel comes with

    really nice HTTP dispatching tests built in • These won’t be sufficient for SPAs or apps that have Vue or React components 49
  20. <?php namespace Tests\Browser; use Tests\DuskTestCase; use Laravel\Dusk\Browser; use Illuminate\Foundation\Testing\DatabaseMigrations; class

    MyHomepageTest extends DuskTestCase { public function testExample() { $this->browse(function (Browser $browser) { $browser->visit('/') ->assertSee('Laravel'); }); } }
  21. use Laravel\Dusk\Browser; use Illuminate\Foundation\Testing\DatabaseMigrations; class MyHomepageTest extends DuskTestCase { /**

    * A Dusk test example. * * @return void */ public function testExample() { $this->browse(function (Browser $browser) { $browser->visit('/') ->drag('#available', '#selected') ->assertSee('Success!'); }); } }
  22. Events • Laravel ships with a full-featured event bus •

    Create event objects • Dispatch events • Listen for events • Queue events • Broadcast events 61
  23. use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class SignupEvent { use

    Dispatchable, InteractsWithSockets, SerializesModels; public function __construct() { // } public function broadcastOn() { return new PrivateChannel('channel-name'); } }
  24. use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class SignupEvent { use Dispatchable, InteractsWithSockets,

    SerializesModels; public $user; public $request; public function __construct(User $user, Request $request) { $this->user = $user; $this->request = $request; } }
  25. <?php namespace App\Http\Controllers; use App\Events\SignupEvent; use App\User; use Illuminate\Http\Request; class

    SignupController extends Controller { public function register(Request $request) { $user = new User($request->all()); $user->save(); $event = new SignupEvent($user, $request); event($event); } }
  26. <?php namespace App\Listeners; use App\Mail\WelcomeEmail; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use

    Illuminate\Support\Facades\Mail; class SignupListener { public function handle($event) { $mail = new WelcomeEmail($event->user); Mail::to($event->user)->send($mail); } }
  27. Broadcasting Events • Laravel can sent your events real-time to

    the client using Web Sockets • Laravel Echo JS lib • Laravel doesn’t natively have a socket server, and PHP is terrible for this • Native Pusher, Socket.io support 72
  28. class FollowedEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public

    $user; public $followedBy; public function __construct(User $user, User $followedBy) { $this->user = $user; $this->followedBy = $followedBy; } public function broadcastOn() { return new PrivateChannel($this->user->id); } }
  29. window.Echo = new Echo({ broadcaster: 'pusher', key: ‘…’, cluster: 'us',

    encrypted: true }); Echo.private(user.id) .listen('Followed', function(e) { // maybe append a flash-messagy-sorta-thing? });