Laravel 5.4 continues refining the framework with Markdown mail, improved testing with Dusk, and quality-of-life improvements. At ZIRA Software, we've upgraded all projects to take advantage of these features.
Markdown Mail
// Create Markdown mailable
php artisan make:mail OrderConfirmation --markdown=emails.orders.confirmation
// app/Mail/OrderConfirmation.php
class OrderConfirmation extends Mailable
{
use Queueable, SerializesModels;
public $order;
public function __construct(Order $order)
{
$this->order = $order;
}
public function build()
{
return $this->markdown('emails.orders.confirmation')
->subject('Order #' . $this->order->id . ' Confirmed');
}
}
{{-- resources/views/emails/orders/confirmation.blade.php --}}
@component('mail::message')
# Order Confirmed
Thank you for your order, {{ $order->customer->name }}!
**Order Number:** {{ $order->id }}
**Date:** {{ $order->created_at->format('M d, Y') }}
@component('mail::table')
| Item | Qty | Price |
|:-----|:---:|------:|
@foreach($order->items as $item)
| {{ $item->name }} | {{ $item->quantity }} | ${{ number_format($item->price, 2) }} |
@endforeach
| **Total** | | **${{ number_format($order->total, 2) }}** |
@endcomponent
@component('mail::button', ['url' => route('orders.show', $order)])
View Order
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
Laravel Dusk
composer require --dev laravel/dusk
php artisan dusk:install
// tests/Browser/LoginTest.php
class LoginTest extends DuskTestCase
{
public function test_user_can_login()
{
$user = User::factory()->create();
$this->browse(function (Browser $browser) use ($user) {
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'password')
->press('Login')
->assertPathIs('/dashboard')
->assertSee('Welcome back');
});
}
public function test_user_cannot_login_with_invalid_credentials()
{
$this->browse(function (Browser $browser) {
$browser->visit('/login')
->type('email', 'invalid@example.com')
->type('password', 'wrong-password')
->press('Login')
->assertPathIs('/login')
->assertSee('These credentials do not match');
});
}
}
// Run tests
php artisan dusk
Higher-Order Collection Messages
// Before 5.4
$users->each(function ($user) {
$user->notify(new WelcomeNotification);
});
// Laravel 5.4 - Higher-order messages
$users->each->notify(new WelcomeNotification);
// More examples
$posts->each->publish();
$orders->each->markAsShipped();
// Filter with higher-order
$activeUsers = $users->filter->isActive();
$publishedPosts = $posts->filter->isPublished();
// Reject
$pendingOrders = $orders->reject->isComplete();
// Map
$userNames = $users->map->name;
$orderTotals = $orders->map->total;
// Sum
$totalRevenue = $orders->sum->total;
Route Model Binding Improvements
// Custom key for route binding
Route::get('posts/{post:slug}', function (Post $post) {
return $post;
});
// Scoped bindings
Route::get('users/{user}/posts/{post:slug}', function (User $user, Post $post) {
// $post is automatically scoped to $user
return $post;
});
// In model - customize route key name
class Post extends Model
{
public function getRouteKeyName()
{
return 'slug';
}
// Customize resolution logic
public function resolveRouteBinding($value, $field = null)
{
return $this->where($field ?? $this->getRouteKeyName(), $value)
->where('published', true)
->firstOrFail();
}
}
Real-Time Facades
// Generate facade on the fly
use Facades\App\Services\PaymentGateway;
class OrderController extends Controller
{
public function store(Request $request)
{
// Use as facade without registration
PaymentGateway::charge($request->amount);
}
}
// Easy mocking in tests
public function test_order_charges_payment()
{
PaymentGateway::shouldReceive('charge')
->once()
->with(100)
->andReturn(true);
$response = $this->post('/orders', ['amount' => 100]);
$response->assertStatus(200);
}
JSON Resources
// Transform models for API responses
public function index()
{
return User::all()->map(function ($user) {
return [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'member_since' => $user->created_at->diffForHumans(),
];
});
}
Conclusion
Laravel 5.4 brings Markdown mail for beautiful emails, Dusk for browser testing, and higher-order collection messages for cleaner code. Each feature improves developer productivity.
Upgrading to Laravel 5.4? Contact ZIRA Software for migration assistance.