【问题标题】:Why absolute path constants __DIR__ and __FILE__ should not be used in Symfony为什么绝对路径常量 __DIR__ 和 __FILE__ 不应该在 Symfony 中使用
【发布时间】:2016-03-23 17:33:15
【问题描述】:

我使用SensioLabs Insight 来控制我的代码质量。

对于简单的文件上传,我必须获取上传目录的绝对路径:

protected function getUploadRootDir()
{
    // the absolute directory path where uploaded
    return __DIR__.'/../../../../web/'.$this->getUploadDir();
}

代码直接来自官方文档 (How to handle file uploads with Doctrine)

但如果分析的代码包含__DIR____FILE__ PHP 魔术常量,则 SLInsight 会发出警告:

__DIR____FILE__ 常量可能与 Symfony 资源覆盖系统冲突。

如何使用这个常量会导致与 Symfony 的冲突?

我怎样才能在我的代码中避免它们?

【问题讨论】:

  • 标题具有误导性。通常推荐使用绝对路径常量__FILE____DIR__仅当您在项目中使用 Symfony(或它的文件定位器)时,最好使用 Symfony 的文件定位器。
  • 对,我已经更新了。谢谢
  • 说实话,如果我看到这段代码,我的反应会是“肯定有比这更好的方法”。您正在硬编码您想要的路径正好是 4 级,然后是一个名为“web”的目录,然后是一个动态段。这看起来非常脆弱和不灵活。当然,整个路径应该配置在某个地方,相对于某个特定的基础。
  • 你说得对,Symfony 提供了帮助程序来获取应用程序不同部分的路径(即@JavierEguiluz 的答案),但它们不能从实体访问。此外,整个方法可以通过在控制器而不是实体中进行优化。

标签: php symfony magic-constants


【解决方案1】:

对于文件上传类,您可能可以忽略此错误消息。但在其他情况下,最好使用 Symfony 文件定位器而不是硬编码文件路径。例如:

$path = $this->get('kernel')->locateResource('@AppBundle/Resources/config/services.xml');

代替:

$path = __DIR__.'/../../../src/Acme/AppBundle/Resources/config/services.xml'

【讨论】:

  • 您好 Eguiluz 先生,在实体模型中使用此代码是否正确? (我曾经认为调用内核或其他服务在模型内部不是“非常干净”......
  • 好吧,我想说从实体获取上传目录已经不干净了。实体不应该负责知道上传文件的存储位置(甚至可能不在本地,而是在 S3 上)
  • 感谢先生的解释,非常感谢您的整个工作。
【解决方案2】:

嗯,这实际上是 SensioLabs Insight 无法正确处理的问题。 由于资源覆盖系统,它会警告不要使用常量,但在许多情况下,这些常量用于与资源覆盖系统无关的地方(您的代码可能就是这种情况)。所以在这种情况下你可以忽略警告

【讨论】:

  • 今天早上,在单元测试中发出了警告。这个规则应该限制在可以使用 symfony 资源覆盖系统的类。 prnt.sc/aa68cw
【解决方案3】:

如果您正在创建第三方捆绑包并希望找到一些资源,@Javier 提出的(好的)解决方案不适用,因为它会引发异常:

ServiceNotFoundException in ContainerBuilder.php line 816:
You have requested a non-existent service "kernel".

在这种情况下,解决方案是使用$this->getPath(),这是BundleNameBundleSymfony\Component\HttpKernel\Bundle\Bundle 类继承的方法。

这将返回与realpath(__DIR__) 相同的结果。

所以$this->getPath() . '/Resources/config/doctrine/mappings'realpath(__DIR__ . '/Resources/config/doctrine/mappings') 是一样的。

原提议here

【讨论】:

  • kernel 服务在编译时不可用(首先因为它是合成的)所以你不能从编译器传递中使用它,但它实际上在任何运行时上下文中都可以正常工作。这里上下文是一个实体,所以我们不应该使用服务,并且由于我的实体不是 Bundle 实例(因为它没有意义),getPath 不可用。因此,忽略前两个答案中所述的警告仍然是我猜的最佳解决方案
  • 是的,我知道。我已经添加了答案,因为在包创建上下文中查找问题时会显示此问题。但这里提出的解决方案并不适用。所以我添加了答案,以便在创建捆绑包的上下文中寻找解决方案的人无论如何都可以找到它。用于内部链接...
猜你喜欢
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
相关资源
最近更新 更多