将模型绑定目标路由到抽象 class
Route Model Binding target to abstract class
假设以下模型架构:
namespace MyApp\Models;
abstract class Person{
abstract function getName();
}
然后,我在Employ中实现:
namespace MyApp\Models;
class Employ extends Person{
public function getName(){
return "Employ";
}
}
用户相同:
namespace MyApp\Models;
class Employ extends User{
public function getName(){
return "User";
}
}
有趣的是..我正在使用我自己的解析逻辑 int 路由绑定上面的模型。
Route::bind('person', function($value)
{
// this method returns an instace of Employ OR User
$person = load_person_from_db($value);
return $person;
});
Route::get('test/{person}', function(MyApp\Models\Person $person){
return $person->getName();
});
问题?当我访问 url...
http://example.com/test/1
...触发了以下异常:
BindingResolutionException in Container.php line 785:
Target [MyApp\Models\Person] is not instantiable.
是啊!我知道 Person
是不可实例化的,但为什么 laravel 此时不返回我加载的实例? $person = load_person_from_db($value);
。
Laravel 尝试解析注入到路由闭包中的依赖项。解决方案是简单地删除类型提示:
Route::get('test/{person}', function(MyApp\Models\Person $person){
return $person->getName();
});
有趣的是,Laravel 会检查参数是否已被模型绑定解析。然而问题是,它通过比较 class:
Illuminate\Routing\RouteDependencyResolverTrait
protected function alreadyInParameters($class, array $parameters)
{
return ! is_null(array_first($parameters, function($key, $value) use ($class)
{
return is_object($value) && get_class($value) === $class;
}));
}
所以因为你的类型提示说 Person
但你的模型绑定 returns 其他东西,Laravel 试图通过 IoC 容器解决依赖关系。
您可以使用 app()->bind(%AbstractClass%, %Implementation%)(例如在控制器的 __construct 方法中),路由器将解析您的模型
假设以下模型架构:
namespace MyApp\Models;
abstract class Person{
abstract function getName();
}
然后,我在Employ中实现:
namespace MyApp\Models;
class Employ extends Person{
public function getName(){
return "Employ";
}
}
用户相同:
namespace MyApp\Models;
class Employ extends User{
public function getName(){
return "User";
}
}
有趣的是..我正在使用我自己的解析逻辑 int 路由绑定上面的模型。
Route::bind('person', function($value)
{
// this method returns an instace of Employ OR User
$person = load_person_from_db($value);
return $person;
});
Route::get('test/{person}', function(MyApp\Models\Person $person){
return $person->getName();
});
问题?当我访问 url...
http://example.com/test/1
...触发了以下异常:
BindingResolutionException in Container.php line 785:
Target [MyApp\Models\Person] is not instantiable.
是啊!我知道 Person
是不可实例化的,但为什么 laravel 此时不返回我加载的实例? $person = load_person_from_db($value);
。
Laravel 尝试解析注入到路由闭包中的依赖项。解决方案是简单地删除类型提示:
Route::get('test/{person}', function(MyApp\Models\Person $person){
return $person->getName();
});
有趣的是,Laravel 会检查参数是否已被模型绑定解析。然而问题是,它通过比较 class:
Illuminate\Routing\RouteDependencyResolverTrait
protected function alreadyInParameters($class, array $parameters)
{
return ! is_null(array_first($parameters, function($key, $value) use ($class)
{
return is_object($value) && get_class($value) === $class;
}));
}
所以因为你的类型提示说 Person
但你的模型绑定 returns 其他东西,Laravel 试图通过 IoC 容器解决依赖关系。
您可以使用 app()->bind(%AbstractClass%, %Implementation%)(例如在控制器的 __construct 方法中),路由器将解析您的模型