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

Php Symfony 4,从自定义类(不是控制器类)获取项目的根路径,php,symfony4,Php,Symfony4,在src/Utils目录中,我为各种事情创建了一个自定义类Foo。我正在寻找一种方法来获得symfony4项目的绝对根路径 从一个控制器,它很容易与: $webPath = $this->get('kernel')->getProjectDir(); 但是,从我在src/Utils目录中创建的自定义类中,如何获取根路径目录 我可以将路径从控制器传递到Foo类: $webPath = $this->get('kernel')->getProjectDir(); $faa

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

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

$webPath = $this->get('kernel')->getProjectDir();
但是,从我在src/Utils目录中创建的自定义类中,如何获取根路径目录

我可以将路径从控制器传递到Foo类:

$webPath = $this->get('kernel')->getProjectDir();
$faa = new Foo($webPath);
$faa->doSomething();
但是我认为将这些信息存储在Foo类中更合适,并且在controller类中只有“controller logic”

这就是工作:

// 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');
    }
}

在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
的mock,这会自动增加复杂性

第二个选项和IMHO更好的方法是只传递一个带有目录路径的字符串。可以通过在
config/services.yaml
中定义如下服务来实现:

services:
    (...)
    MyNamespace\Foo:
        arguments:
            - %kernel.project_dir%
您的构造函数将如下所示:

class Foo 
{
    /** string $rootPath */
    private $rootPath;

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

没有
内核
注入

config/services.yaml

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


如果您的类正在扩展:
Symfony\Bundle\FrameworkBundle\Controller\AbstractController
,然后您可以将根目录作为

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

protected $projectRoot;

public function __construct(ContainerBagInterface $containerBag)
{
    $this->projectRoot = $containerBag->get('kernel.project_dir');;
}
向控制器注入
容器接口

protected $projectRoot;

public function __construct(ContainerBagInterface $containerBag)
{
    $this->projectRoot = $containerBag->get('kernel.project_dir');;
}

protected $projectRoot;

public function __construct(ContainerBagInterface $containerBag)
{
    $this->projectRoot = $containerBag->get('kernel.project_dir');;
}
更好,推荐的方法

root\u 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;
  }
}

将此值作为参数传递给将自动连接的Foo类构造函数。Hmmm,是否可以为我提供构造方法的示例?但是@Tomasz的答案更好;)我很高兴您包含了使用声明。事实上,没有其他解决方案提到
use-Symfony\Component\HttpKernel\KernelInterface
,但是如果没有官方文档中的解决方案,任何事情都不会起作用:对于第一个解释,您还应该提到包含
use-Symfony\Component\HttpKernel\KernelInterface在类文件上方。在2019/2020/2021年,使用Symfony(4,5+)的当前版本,这就是实现这一点的方法。最后一个示例对我来说非常有用。但是,我不得不将
%kernel.root\u dir%
更改为
%kernel.project\u dir%
。谢谢!我做了编辑。