Let us recall the pathway that was implemented in Laravel, as illustrated here:
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
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.
There are several principle advantages of using DocBlock annotations for routing in Laravel:
routes.php
file may be viewed as unnecessary for a simple project with only a few controllers.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.