Laravel-Tips

Laravel Tips

A collection of daily Laravel/PHP tips shared by OussamaMater on X and LinkedIn.

Tip #1 💡: Use rebinding events to refresh dependencies

When a bound instance in the Laravel container is rebound, a rebinding event is triggered. You can listen to this event to ensure that the classes using the instance stay up to date. You can achieve this by using the rebinding method or simply using the refresh shortcut 🚀

<?php

namespace App\\Providers;

use App\\Services\\PaymentService;
use Illuminate\\Support\\ServiceProvider;
use Illuminate\\Contracts\\Foundation\\Application;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton('payment.service', function (Application $app) {
            $paymentService = new PaymentService();

            $paymentService->setTaxService($app['tax.service']);

            // Will set a new TaxService instance for the Payment Service
            $app->refresh('tax.service', $paymentService, 'setTaxService');

            return $paymentService;
        });
    }
}

Tip #2 💡: Get Original Attributes

Laravel accessors allow you to transform your model attributes when retrieving them. But sometimes, you may wish to get the original value. Well, Laravel provides a method just for that: getRawOriginal 🚀

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Casts\\Attribute;

class User extends Model
{
    protected function username(): Attribute
    {
        return Attribute::make(
            function (string $value, array $attributes) {
                return sprintf('%s#%s', $value, $attributes['app_id']);
            }
        );
    }
}

User::create([
    'username' => 'oussama',
]);

$book->getOriginal('username'); // oussama#1234
$book->getRawOriginal('username'); // oussama

Tip #3 💡: Model Binding in Form Requests

Route Model Binding allows you to inject the model instances directly into your routes. It is usually used within a controller, but did you know you could also access the model instance in your Form Request?

<?php

// Route definition
Route::put('/post/{post}', [PostsController::class, 'create']);

// Form Request defintion
class PostController extends FormRequest
{
    public function authorize(): bool
    {
        // The post instance, if found
        return $this->user()->can('create', $this->route('post'));
    }

    public function rules(): array
    {
        return [
            // ...
        ];
    }
}

Tip #4 💡: Mapping Exceptions via Handler

Did you know that you can map exceptions to other exceptions? This is helpful when you have custom exceptions that you'd like to be handled like internal ones, or when you want to wrap third-party exceptions and map them to your own 🚀

<?php

namespace App\\Exceptions;

use App\\Exceptions\\MyCustomException;
use Illuminate\\Database\\Eloquent\\ModelNotFoundException;
use Illuminate\\Foundation\\Exceptions\\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    // MyCustomException is now handled as if it were ModelNotFoundException
    protected $exceptionMap = [
        MyCustomException::class => ModelNotFoundException::class,
    ];
}

Tip #5 💡: Mapping Exception via Custom Exception Classes

When defining a custom exception, there is a secret way to map the exception to another one, and this is done by defining the getInnerException method 🚀

Curious about how the mapping is done? Take a look at Illuminate\\Foundation\\Exceptions\\Handler::mapException()

<?php

namespace App\\Exceptions;

use Exception;
use Throwable;
use Illuminate\\Database\\Eloquent\\ModelNotFoundException;

class MyCustomException extends Exception
{
    // MyCustomException is now handled as if it were ModelNotFoundException
    public function getInnerException(): Throwable
    {
        return new ModelNotFoundException;
    }
}

Tip #6 💡: Route Absolute and Relative Path