【问题标题】:Read controllers custom annotations from a custom Command in Symfony 2从 Symfony 2 中的自定义命令读取控制器自定义注释
【发布时间】:2015-08-06 20:21:51
【问题描述】:

我已经创建了自定义注释来生成 JSON 文件(如果您问的话,可以使用 NodeRed...),并且我正在通过虚拟控制器中的虚拟方法成功地测试它们。

我想将所有这些移植到一个自定义 Sf 命令,它的工作是读取我的包中的所有控制器注释并获得相同的结果(也就是创建 JSON 文件)。

我怎样才能做到这一点?使用查找器循环遍历 XxxxController.php 文件是一个不错的选择吗? 还是野心太大? :p

注释示例:

/**
 * @NodeRedFlows(
 *     triggerBy="testFlow", options={"interval":"45"}  
 * )
 */
 public function indexAction() { /*...*/ }

抱歉,发布更多代码并不容易,因为我有整个阅读器类、注释类和另一个基于triggerBy="testFlow" id 创建 JSON 流的类。

底线:*

我希望能够从命令而不是在我的控制器中创建我的 JSON 流文件(用于测试)。

【问题讨论】:

    标签: php symfony annotations


    【解决方案1】:

    加载所有在 Symfony 中分配了路由的控制器动作(参见thisthis)。

    然后为每个找到的控制器操作加载注释:

    use Doctrine\Common\Annotations\AnnotationReader;
    use Symfony\Component\HttpFoundation\Request;
    
    $annotationReader = new AnnotationReader();
    $routes = $this->container->get('router')->getRouteCollection()->all();
    $this->container->set('request', new Request(), 'request');
    
    foreach ($routes as $route => $param) {
        $defaults = $params->getDefaults();
    
        if (isset($defaults['_controller'])) {
             list($controllerService, $controllerMethod) = explode(':', $defaults['_controller']);
             $controllerObject = $this->container->get($controllerService);
             $reflectedMethod = new \ReflectionMethod($controllerObject, $controllerMethod);
    
             // the annotations
             $annotations = $annotationReader->getMethodAnnotations($reflectedMethod );
        }
    }
    

    更新:

    如果您需要所有控制器方法,包括那些没有 @Route 注释的方法,那么我会按照您在问题中的建议进行操作:

    // Load all registered bundles
    $bundles = $this->container->getParameter('kernel.bundles');
    
    foreach ($bundles as $name => $class) {
        // Check these are really your bundles, not the vendor bundles
        $bundlePrefix = 'MyBundle';
        if (substr($name, 0, strlen($bundlePrefix)) != $bundlePrefix) continue;
    
        $namespaceParts = explode('\\', $class);
        // remove class name
        array_pop($namespaceParts);
        $bundleNamespace = implode('\\', $namespaceParts);
        $rootPath = $this->container->get('kernel')->getRootDir().'/../src/';
        $controllerDir = $rootPath.$bundleNamespace.'/Controller';
    
        $files = scandir($controllerDir);
        foreach ($files as $file) {
            list($filename, $ext) = explode('.', $file);
            if ($ext != 'php') continue;
    
            $class = $bundleNamespace.'\\Controller\\'.$filename;
            $reflectedClass = new \ReflectionClass($class);
    
            foreach ($reflectedClass->getMethods() as $reflectedMethod) {
                // the annotations
                $annotations = $annotationReader->getMethodAnnotations($reflectedMethod);
            }
        }
    }
    

    【讨论】:

    • 谢谢,但评论并不总是有@Route注解...此外,行“$controllerObject = $container->get($controllerService);”给出错误:“您无法创建非活动范围(“请求”)的服务(“请求”)。”。看来这是朝着正确的方向发展。
    • 我更新了答案以解决You cannot create a service ("request") of an inactive scope ("request")。错误
    • 更新了答案以包含没有@Route 注释的操作。我还没有测试过代码,但它应该可以工作。
    • 谢谢。我会在事后考虑你的第一个解决方案。它运行良好(我更改了反射以避免You cannot create a service ("request") of an inactive scope ("request") 错误,但我奇怪地得到了双重注释
    • 只需执行$this->container->set('request', new Request(), 'request'); 即可避免错误。
    猜你喜欢
    • 2011-10-08
    • 2013-03-10
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 2015-04-15
    • 2018-06-24
    相关资源
    最近更新 更多