Symfony 4,从自定义类(不是控制器类)获取项目的根路径

Posted

技术标签:

【中文标题】Symfony 4,从自定义类(不是控制器类)获取项目的根路径【英文标题】:Symfony 4, get the root path of the project from a custom class (not a controller class) 【发布时间】:2019-03-21 20:58:42 【问题描述】:

在 src/Utils 目录中,我为各种事物创建了一个自定义类 Foo。我正在寻找一种方法来获取 symfony 4 项目的绝对根路径

从一个控制器,它很容易:

$webPath = $this->get('kernel')->getProjectDir();

但是从我在 src/Utils 目录中创建的自定义类中,我怎样才能获得根路径目录?

我可以将控制器的路径传递给 Foo 类:

$webPath = $this->get('kernel')->getProjectDir();
$faa = new Foo($webPath);
$faa->doSomething();

但我认为将这些信息存储在 Foo 类中并且在控制器类中只有“控制器逻辑”更合适

【问题讨论】:

将此值作为参数传递给 Foo 类 constructor,它将自动装配。 嗯,可以给我提供一个构造方法的例子吗? 【参考方案1】:

这是工作:

// from Foo class
use Symfony\Component\HttpKernel\KernelInterface;
...
class Foo
    private $rootDir;
    public function __construct(KernelInterface $kernel)
    
        $this->rootDir = $kernel->getProjectDir();
    
    public function myfoomethod()
        return $this->getRootDir();
    
    public function getRootDir()
        return $this->rootDir;
    



// from the controller class 
use App\Utils\Foo;
...
class FaaController extends AbstractController

    /**
     * @Route("/scenario", name="scenario")
     */
    public function new(Foo $foo)
    
        dump($foo->myfoomethod()); //show the dir path !
        return $this->render('faa/index.html.twig');
    

【讨论】:

但@Tomasz 的回答更好;) 很高兴您包含了使用声明 确实,没有其他解决方案提到use Symfony\Component\HttpKernel\KernelInterface,但没有它就什么都行不通【参考方案2】:

在 Symfony 中,AppKernel 类正在处理方法 getProjectDir() 下的项目根目录。要在控制器中获取它,您可以执行以下操作:

$projectRoot = $this->get('kernel')->getProjectDir();

它会返回一个项目根目录。

如果您需要在您的一个类中使用项目根目录,您有两个选择,我将向您介绍。首先是传递AppKernel 作为依赖:

class Foo 

    /** KernelInterface $appKernel */
    private $appKernel;

    public function __construct(KernelInterface $appKernel)
    
        $this->appKernel = $appKernel;
    

感谢 Symfony 4 自动装配依赖项,它将自动注入到您的类中,您可以通过以下方式访问它:

$this->appKernel->getProjectDir();

请注意:我认为这不是一个好主意,除非您有真正的需要并且更多地与AppKernel 类有关,而不是获取项目根目录。特别是如果您稍后考虑为您的班级创建单元测试。例如,您需要创建 AppKernel 的模拟,从而自动增加复杂性。

第二个选项和恕我直言更好的是只传递一个带有目录路径的字符串。您可以通过在 config/services.yaml 中定义一个服务来实现这一点,如下所示:

services:
    (...)
    MyNamespace\Foo:
        arguments:
            - %kernel.project_dir%

你的构造函数看起来像:

class Foo 

    /** string $rootPath */
    private $rootPath;

    public function __construct(string $rootPath)
    
        $this->rootPath = $rootPath;
    

【讨论】:

对于第一个解释,您还应该提到在类文件上方包含use Symfony\Component\HttpKernel\KernelInterface;【参考方案3】:

没有Kernel注入

config/services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true
        bind:
            $projectDir: '%kernel.project_dir%'

....

class Foo

    private $projectDir;

    public function __construct(string $projectDir)
    
        $this->projectDir = $projectDir;
    

【讨论】:

官方文档中的解决方案:symfony.com/blog/new-in-symfony-4-2-important-deprecations【参考方案4】:

如果您的课程正在扩展: Symfony\Bundle\FrameworkBundle\Controller\AbstractController,那么就可以得到根目录了

$projectRoot = $this->getParameter('kernel.project_dir');

ContainerBagInterface 注入您的控制器

protected $projectRoot;

public function __construct(ContainerBagInterface $containerBag)

    $this->projectRoot = $containerBag->get('kernel.project_dir');;

更好的推荐方法

root_dir 注入您的Foo 类。将以下内容添加到服务下的配置中

services:
    foo:
        class:     App\Path\To\Foo
        arguments: ['%kernel.project_dir%']

容器应在解析时将参数传递给您的类,Foo 类应如下所示

<?php

namespace App\Path\To;

class Foo 

  private $projectDir;

  public function __construct($projectDir) 
  
     $this->projectDir = $projectDir;
  

【讨论】:

在 2019/2020/2021 年,使用当前版本的 Symfony (4,5+) 这是执行此操作的方法。 最后一个例子对我很有效。但是,我不得不将%kernel.root_dir% 更改为%kernel.project_dir%

以上是关于Symfony 4,从自定义类(不是控制器类)获取项目的根路径的主要内容,如果未能解决你的问题,请参考以下文章

如何从自定义 UIButton 类显示视图控制器?

如何从自定义 UIView 类调用函数?

从自定义类管理 NSURLSession 的完成处理程序

如何从自定义视图控制器类加载初始视图控制器

从自定义数据源中获取选定的行?

如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException