重用composer.phar包中的模板

时间:2016-05-31 12:05:17

标签: php composer-php

在一个非常抽象的例子中:我想要在包A中加载一些模板或文件,这些模板或文件位于第三方包B中,它们都在Application Z中加载,例如:

{
  "name": "application/Z",
  "require": {
    "lib/A": "*"
  }  
}

{
  "name": "lib/A",
  "require": {
    "lib\B": "*"
  }
}

现在我喜欢这样做:

<?php
namespace lib\A;

class TemplateLoader {
 public function getInclude() {
    return file_get_contents(__DIR__ . '/../../vendor/lib/b/templates/my.inc');
 }
}

这样可行,但使用相对路径似乎是一个坏主意,尤其是在单元测试中,路径以'../vendor'开头。所以路径不可靠。

现在我的问题:是否可以从自动加载器中使用的composer获取供应商路径?或者有这样的实现的最佳实践吗?

创建函数\Lib\B\Templates::getIncludePath()的明显解决方案是不可能的,因为我无法访问此库。

2 个答案:

答案 0 :(得分:1)

假设lib/B的composer.json包含:

"autoload": {
    "psr-0": {
        "lib\\B": "src/"
        }
    },

要回答这个问题,您可以使用作曲家的ClassLoader,因此您的lib\A\TemplateLoader可能如下所示:

namespace lib\A;

use Composer\Autoload\ClassLoader;

class TemplateLoader {
    /** @var  ClassLoader  */
    protected $loader;

    public function __construct(ClassLoader $loader)
    {
        $this->loader = $loader;
    }

    public function getInclude() {
        $libs = $this->loader->getPrefixes();
        if (!isset($libs['lib\\B'])) {
            throw new \RuntimeException("Package lib/B is not loaded. Be sure it is included in composer.json and you ran 'compose install'.");
        }
        $path = $libs['lib\\B'][0];
        // At this point $path contains base path for classes in lib/B package,
        // depending on 'autoload' directive of lib/B's composer.json above.
        // In this example it is '/full/path/to/vendor/lib/B/src'

        $parts = explode('/', $path);
        array_pop($parts);
        $path = implode('/', $parts);

        return file_get_contents($path . '/templates/my.inc');
    }
}

正确的方法是fork lib/B并在那里添加模板加载器:

namespace lib\B;

class TemplateLoader {
    public static function getTemplate($name) {
        return file_get_contents(__DIR__ . '/../templates/'.$name);
    }
}

所以在lib\A中它很简单:

namespace lib\A;

class TemplateLoader {
    public function getInclude() {
        return \lib\B\TemplateLoader::getTemplate('my.inc');
    }
}

答案 1 :(得分:1)

至于寻找作曲家vendor-dir的方法,我看到过一些尝试做这种非常脆弱的事情,我不建议。

  • 一种非常糟糕的方法是通过查看autoload.php的两个常见位置来对上下文进行假设。

  • 稍微好一点的方法是对spl_autoload_functions的结果使用反射来确定自动加载器来自的文件。

理想的方法是在项目中使用composer/composer作为库,并在本地存储库中查找包元数据。

我建议,一种非常简单的方法是使用模板加载器配置路径。这可能允许您拥有多个第三方库,这些库具有不同的约定,它们放置在仓库中。