master

laravel/framework

Last updated at: 29/12/2023 09:24

RouteBinding.php

TLDR

This file is part of the Illuminate\Routing namespace and contains the RouteBinding class. This class provides methods for creating route model bindings in the Laravel framework.

Methods

forCallback($container, $binder)

This method creates a route model binding for a given callback. If the $binder parameter is a string, it calls the createClassBinding method to create a class-based binding. Otherwise, it returns the $binder.

createClassBinding($container, $binding)

This protected method creates a class-based binding using the IoC container. It parses the $binding string to get the class name and bind method name, and then creates a closure that calls the bind method on the resolved class instance.

forModel($container, $class, $callback = null)

This method creates a route model binding for a model. It creates a closure that receives a $value parameter and attempts to retrieve the model using the resolveRouteBinding method on the resolved $class instance. If the model is found, it returns the model. If the model is not found and a $callback closure is provided, it calls the $callback with the $value parameter. Otherwise, it throws a ModelNotFoundException exception.

Classes

There are no classes in this file.

<?php

namespace Illuminate\Routing;

use Closure;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Str;

class RouteBinding
{
    /**
     * Create a Route model binding for a given callback.
     *
     * @param  \Illuminate\Container\Container  $container
     * @param  \Closure|string  $binder
     * @return \Closure
     */
    public static function forCallback($container, $binder)
    {
        if (is_string($binder)) {
            return static::createClassBinding($container, $binder);
        }

        return $binder;
    }

    /**
     * Create a class based binding using the IoC container.
     *
     * @param  \Illuminate\Container\Container  $container
     * @param  string  $binding
     * @return \Closure
     */
    protected static function createClassBinding($container, $binding)
    {
        return function ($value, $route) use ($container, $binding) {
            // If the binding has an @ sign, we will assume it's being used to delimit
            // the class name from the bind method name. This allows for bindings
            // to run multiple bind methods in a single class for convenience.
            [$class, $method] = Str::parseCallback($binding, 'bind');

            $callable = [$container->make($class), $method];

            return $callable($value, $route);
        };
    }

    /**
     * Create a Route model binding for a model.
     *
     * @param  \Illuminate\Container\Container  $container
     * @param  string  $class
     * @param  \Closure|null  $callback
     * @return \Closure
     *
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>
     */
    public static function forModel($container, $class, $callback = null)
    {
        return function ($value) use ($container, $class, $callback) {
            if (is_null($value)) {
                return;
            }

            // For model binders, we will attempt to retrieve the models using the first
            // method on the model instance. If we cannot retrieve the models we'll
            // throw a not found exception otherwise we will return the instance.
            $instance = $container->make($class);

            if ($model = $instance->resolveRouteBinding($value)) {
                return $model;
            }

            // If a callback was supplied to the method we will call that to determine
            // what we should do when the model is not found. This just gives these
            // developer a little greater flexibility to decide what will happen.
            if ($callback instanceof Closure) {
                return $callback($value);
            }

            throw (new ModelNotFoundException)->setModel($class);
        };
    }
}