Silex ControllerCollection 不会级联__call到其他 ControllerCollectio


Silex ControllerCollection not cascading __call to fellow ControllerCollection

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

我们正在处理的一些插件将自身附加到对象,在管理界面中为其表示添加路由。 这会导致路由构建看起来像(细分):

$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]方法也表现出相同的行为。 这是预期行为吗? 该值从第一个装载到扩展视图传输得恰到好处,生成器会顺利处理它,但assert的行为不符合预期。

我做错了什么?

问题在于 ControllerCollection 对 __call() 的实现。控制器集合首先检查它是否支持该方法:

    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实例。 这在网络上几乎没有静态,所以我认为它要么是预期的行为,要么不是许多人的标准程序。

修复就像向if条件添加|| $controller instanceof ControllerCollection一样简单,我有两种解决方案可供其他期望此行为的人使用:

Silex 存储库拉取请求

Silex控制器集合的扩展类

非此即彼。 我们拭目以待。