Silex ControllerCollection 未级联 __call 到其他 ControllerCollection

Silex ControllerCollection not cascading __call to fellow ControllerCollection

本周在使用 Silex、Routes 和 ControllerCollection class 时,我 运行 遇到了以下问题:

我们正在开发的一些插件将自身附加到对象,将路由添加到它们在管理界面中的表示。这导致路线构建看起来像(断开):

$admin = $app['controllers_factory'];
$app->mount('/admin', $admin);

$user = $app['controllers_factory'];
$admin->mount('/user', $user);

$user->get('/', function() { return 'User List'; })
->bind('admin.user.list');
$user->get('/new', function() { return 'New User'; })
->bind('admin.user.new');

$user_detail  = $app['controllers_factory'];
$user->mount('/{id}', $user_detail);
$user->assert('id', '\d+');

$user_detail->get('/', function($id) {
    return "User: $id ";
})
->bind('admin.user.detail');

$user_extension = $app['controllers_factory'];
$user_detail->mount('/extension/{extension_name}', $user_extension);

$user_extension->get('/', function($id, $extension_name) {
    return "User: $id\nExtension: $extension_name";
})
->bind('admin.user.extension.view');

我 运行 遇到的问题是,虽然调用 $app['url_generator']->generate('admin.user.edit', array('id' => 's2')); 会使用户 ID (\d+) 的断言失败,但调用 $app['url_generator']->generate('admin.user.extension.view', array('id' => 's2', 'extension_name' => 'something')); 不会.分别访问它们的 URL 也是如此:/admin/user/s2(失败)和 /admin/user/s2/extension/something/(成功)。

beforeaftervalueconvertrequire[http/s] 方法表现出相同的行为出色地。这是预期的行为吗?该值是 t运行sferred 从第一次挂载到扩展视图时很好,并且生成器可以流畅地处理它,但是 assert 的行为并不像预期的那样。

我做错了什么?

问题出在ControllerCollection对__call()的实现上。 ControllerCollection 首先检查它是否支持方法:

    if (!method_exists($this->defaultRoute, $method)) {
        throw new \BadMethodCallException(sprintf('Method "%s::%s" does not exist.', get_class($this->defaultRoute), $method));
    }

然后它将调用级联到它的控制器(毕竟它是一个控制器集合):

    foreach ($this->controllers as $controller) {
        if ($controller instanceof Controller) {
            call_user_func_array(array($controller, $method), $arguments);
        }
    }

问题在于 instanceof 检查,它没有考虑 ControllerCollection 的额外实例。这在网络上几乎没有静态,所以我认为这要么是预期的行为,要么不是许多人的标准程序。

解决方法就像将 || $controller instanceof ControllerCollection 添加到 if 条件一样简单,我有两个解决方案可供其他任何期待此行为的人使用:

Silex Repo Pull Request

Extended Class for Silex Controller Collection

Either/Or。我们拭目以待。