Using annotations in Laravel 5

Let us recall the pathway that was implemented in Laravel, as illustrated here:

  • The HTTP request gets routed to a controller
  • The command is instantiated inside of the controller
  • An event is fired
  • The event is handled
Using annotations in Laravel 5

Laravel's modern command-based pub-sub pathway.

Using annotations, this process can be rendered even easier. First, a reservations controller will be created:

$ php artisan make:controller ReservationsController

To create a route to allow the user to create a new reservation, the POST HTTP verb will be used. The @Post annotation will listen to requests with the POST method attached to the /bookRoom url. This is used in place of the route that would normally be found inside of the routes.php file:

<?php namespace MyCompanyHttpControllers;

use ...

class ReservationsController extends Controller {
/**
* @Post("/bookRoom")
*/
  public function reserve()
  {
  }

If we want to limit requests to a valid URL, the domain parameter limits requests to a certain URL. Additionally, the auth middleware requires the authentication of any request that wishes to reserve a room:

<?php namespace AppHttpControllers;

use …
/**
* @Controller(domain="booking.hotelwebsite.com")
*/

class ReservationsController extends Controller {

/**
* @Post("/bookRoom")
* @Middleware("auth")
*/
  public function reserve()
  {

Next, the ReserveRoom command should be created. This command will be instantiated inside the controller:

$ php artisan make:command ReserveRoom

Contents of the ReserveRoom Command are as follows:

<?php namespace MyCompanyCommands;

use MyCompanyCommandsCommand;
use MyCompanyUser;
use MyCompanyAccommodationRoom;
use MyCompanyEventsRoomWasReserved;

use IlluminateContractsBusSelfHandling;

class ReserveRoomCommand extends Command implements SelfHandling {
  
  public function __construct()
  {
  }
  /**
   * Execute the command.
   */
  public function handle()
  {
  }
}

Next, we will need to instantiate the ReserveRoom command from inside the reservation controller:

<?php namespace MyCompanyHttpControllers;

use MyCompanyAccommodationReservation;
use MyCompanyCommandsPlaceOnWaitingListCommand;
use MyCompanyCommandsReserveRoomCommand;
use MyCompanyEventsRoomWasReserved;
use MyCompanyHttpRequests;
use MyCompanyHttpControllersController;
use MyCompanyUser;
use MyCompanyAccommodationRoom;

use IlluminateHttpRequest;

class ReservationsController extends Controller {

/**
 * @Post("/bookRoom")
 * @Middleware("auth")
 */
  public function reserve()
  {	
    $this->dispatch(
    new ReserveRoom(Auth::user(),$start_date,$end_date,$rooms)
    );
  }

Now we will create the RoomWasReserved event:

$ php artisan make:event RoomWasReserved

To instantiate the RoomWasReserved event from the ReserveRoom handler, we may take advantage of the event() helper method. In this example, the command is self-handling, thus it is simple to do this:

<?php namespace AppCommands;

use AppCommandsCommand;
use IlluminateContractsBusSelfHandling;

class ReserveRoom extends Command implements SelfHandling {
    public function __construct(User $user, $start_date, $end_date, $rooms)
    {
    }
    public function handle()
    {
        $reservation = Reservation::createNew();
        event(new RoomWasReserved($reservation));
    }
}

Since the user needs to be sent the details of the room reservation email, the next step is to create an e-mail sender handler for the RoomWasReserved event. To do this, artisan is used again to create the handler:

$ php artisan handler:event RoomReservedEmail –event=RoomWasReserved

The methods of the SendEmail handler for the RoomWasReserved event are simply constructor and handler. The job of sending the e-mail would be performed inside the handler method. The @Hears annotation is added to its DocBlock to complete the process:

<?php namespace MyCompanyHandlersEvents;

use MyCompanyEventsRoomWasReserved;

use IlluminateQueueInteractsWithQueue;
use IlluminateContractsQueueShouldBeQueued;

class RoomReservedEmail {
  public function __construct()
  {
  }

  /**
   * Handle the event.
   * @Hears("AppEventsRoomWasReserved")
   * @param  RoomWasReserved  $event
   */
  public function handle(RoomWasReserved $event)
  {
     //TODO: send email to $event->user
  }
}

Simply add RoomReservedEmail to the scanEvents array to allow that event to be scanned as follows:

protected $scanEvents = [
   'AppHandlersEventsRoomReservedEmail'
];

The last step is to import. Artisan is used to scan events for annotations and write to the output file:

$ php artisan event:scan

  Events scanned!

Here is the output of the storage/framework/events.scanned.php file, which shows the event listener:

<?php $events->listen(array(0 => 'App\Events\RoomWasReserved',
), AppHandlersEventsRoomReservedEmail@handle'),

The final view of the scanned annotation files inside the storage directory is as follows. Note that they are parallel:

storage/framework/events.scanned.php
storage/framework/routes.scanned.php

Tip

Laravel uses artisan to cache routes, but not to scan events, so the following command produces a cached file:

$ php artisan route:cache
Route cache cleared!
Routes cached successfully!

The route:scan command must be run before the route:cache is run, so it is important to execute the two commands in this order:

$ php artisan route:scan
Routes scanned!

$ php artisan route:cache
Route cache cleared!
Routes cached successfully!

This command writes to: storage/framework/routes.php.

<?php

app('router')->setRoutes(
  unserialize(base64_decode('TzozNDoiSWxsdW1pbmF0ZVxSb3V0aW5nXFd…'))
);

Both the files will be created, but only the compiled routes.php file is used until php artisan route:scan is run again.

Advantages

There are several principle advantages of using DocBlock annotations for routing in Laravel:

  • Each controller remains independent. The controller is not "tied" to a separate route and this makes sharing controllers, and moving them from project to project, easier. The routes.php file may be viewed as unnecessary for a simple project with only a few controllers.
  • Developers need not worry about routes.php. When working with other developers, the routes file needs to be kept continually in synchronization. With the DocBlock annotations approach, the routes.php file is cached and not placed under source code control; each developer may simply concentrate on his or her controllers.
  • The route annotation keeps the route together with the controller. When controllers and routes are separate, and when a new programmer reads the code for the first time, it may not be immediately clear to which routes each controller method is attached. By placing the route directly in the DocBlock above the function, it is immediately evident.
  • Developers that are familiar with, and are used to, using annotations in frameworks, such as Symfony and Zend may find using annotations in Laravel to be a very convenient way of developing software applications. Also, Java and C# developers using Laravel as their first PHP experience will find annotations very convenient.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset