路径模型将目标绑定到抽象类

时间:2015-02-07 19:21:43

标签: php laravel laravel-5

假设以下模型建议:

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();
});

问题?当我访问网址时...

 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);

2 个答案:

答案 0 :(得分:1)

Laravel尝试解决注入路由闭包的依赖关系。解决方案是简单地删除类型提示:

Route::get('test/{person}', function(MyApp\Models\Person $person){
    return $person->getName();
});

有趣的是,Laravel确实检查参数是否已通过模型绑定解析。但问题是,它通过比较类来实现:

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但你的模型绑定返回其他内容,Laravel会尝试通过IoC容器解析依赖关系。

答案 1 :(得分:0)

您可以使用 app()->bind(%AbstractClass%, %Implementation%)(例如在控制器的 __construct 方法中),路由器将解析您的模型