Extending Laravel's Blade Posted on January 19th, 2016
Lets assume you want to convert DateTime
objects into human readable strings easily in your blade files. The laravel docs suggests adding the following code snippet into AppServiceProvider::boot
method:
// allows @datetime(new \DateTime('now')) to display the current date and time
Blade::directive('datetime', function($expression) {
return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
});
This is pretty simple. However it's a little more complex to abstract the format into a second parameter for the datetime
directive e.g.: @datetime(new \DateTime('now'), 'm/d/Y H:i')
. Rather than using regex to get the 2 separate parameters, I like to create a self executing class capable of handling any number of parameters.
class DateFormatter
{
public function __invoke(\DateTime $date, $format)
{
return $date->format($format);
}
}
Remember, when you add the __invoke
method to any class, it can be executed like a closure.
$formatter = new \DateFormatter();
echo $formatter(new \DateTime('2016-01-19'), 'Y'); // 2016
The Blade::directive
should now be updated to use our DateFormatter
class and a DateFormatter
instance should be injected into the templates.
// Inject DateFormatter instance into all templates
View::with('dateFormatter', new \DateFormatter);
// Update directive to use `DateFormatter`
Blade::directive('datetime', function ($expression) {
return "<?php echo \$dateFormatter{$expression}; ?>";
});
Imagine the following template code:
Registered on @datetime($user->createdAt, 'Y-m-d')
When the template is compiled, the above line will be compiled to:
Registered on <?php echo $dateFormatter($user->createdAt, 'Y-m-d'); ?>