-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
21de409
commit e75730e
Showing
2 changed files
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
namespace Illuminate\Routing; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class ImplicitRouteBinding | ||
{ | ||
/** | ||
* Resolve the implicit route bindings for the given route. | ||
* | ||
* @param \Illuminate\Container\Container $container | ||
* @param \Illuminate\Routing\Route $route | ||
* @return void | ||
*/ | ||
public static function resolveForRoute($container, $route) | ||
{ | ||
$parameters = $route->parameters(); | ||
|
||
foreach ($route->signatureParameters(Model::class) as $parameter) { | ||
$class = $parameter->getClass(); | ||
|
||
if (array_key_exists($parameter->name, $parameters) && | ||
! $route->parameter($parameter->name) instanceof Model) { | ||
$method = $parameter->isDefaultValueAvailable() ? 'first' : 'firstOrFail'; | ||
|
||
$model = $container->make($class->name); | ||
|
||
$route->setParameter( | ||
$parameter->name, $model->where( | ||
$model->getRouteKeyName(), $parameters[$parameter->name] | ||
)->{$method}() | ||
); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<?php | ||
|
||
namespace Illuminate\Routing; | ||
|
||
use Closure; | ||
use Illuminate\Database\Eloquent\ModelNotFoundException; | ||
|
||
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 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. | ||
$segments = explode('@', $binding); | ||
|
||
$method = count($segments) == 2 ? $segments[1] : 'bind'; | ||
|
||
$callable = [$container->make($segments[0]), $method]; | ||
|
||
return call_user_func($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 | ||
*/ | ||
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->where($instance->getRouteKeyName(), $value)->first()) { | ||
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 call_user_func($callback, $value); | ||
} | ||
|
||
throw (new ModelNotFoundException)->setModel($class); | ||
}; | ||
} | ||
} |