monolyth / mural
MUltiple "Resource" AutoLoader
Requires
- php: >=5.3
Requires (Dev)
- phpunit/phpunit: ^4.7
This package is auto-updated.
Last update: 2022-10-07 16:47:14 UTC
README
MUltiple "Resource" AutoLoader
Mural 是一个小型包,包含一个自定义的自动加载器,可以从同一仓库中理智地提供和测试多个 "app"(通常是网站),同时保持共享代码库的整洁。
安装
Composer(推荐)
composer require monolyth/mural
手动
克隆或下载仓库,并确保 Monolyth\\Mural
命名空间映射到 Mural 的 src
目录。由于它只有一个文件,您也可以手动 require
它。
问题
您的普通小型网站将在某个地方(例如,src
)有代码,并有一个公共目录,其中包含您的 index.php
前端控制器(例如,httpdocs
)。由于通常 httpdocs
只包含静态文件,您可以将自动加载器(例如,在 composer.json
中)设置为查看 src
并完成它。同样适用于任何外部包。
然而,更复杂的项目将具有多个面向公共的路径,一些项目特定的覆盖,但主要是大量共享的代码。
可以通过调整 PHP 的 include_path
来自动包含正确的代码,但这在测试期间有问题:您需要一个针对每个项目(网站)的测试套件,因为类名将是相同的,并触发致命错误。
解决方案
Mural 自动加载器允许您特别命名这些覆盖,同时仍然将 "原始" 命名空间暴露给消费类。在测试期间,只需不包含它,并用原始的、完全命名空间(因此是唯一的)类进行测试即可。在您的应用程序中使用 "标准化" 的类名。
WHY $DEITY??? 一个例子
好吧,更多的澄清。这实际上是一个真实世界的例子。
假设你有一组约会网站。有很多功能(消息、资料编辑等)是共享的,但也有一些特定的功能。 straight.com
面向异性恋者,而 gay.com
面向同性恋者(duh)。除了标志和一些其他的 CSS,它们是相同的,但在一个重要的方面不同:在搜索时,straight.com
应仅匹配男性和女性的结果,而 gay.com
应仅匹配男性和男性或女性和女性的结果。一个虚构的目录结构可能如下所示
/path/to/sites
/vendor <- packages
/src <- shared source code
/straight.com
/Search.php
/gay.com
/Search.php
通常,这两个 Search
类将简单地称为 \Search
,或者它们会在它们网站的命名空间中(例如,Straight\Search
等),您将不得不记住在您的(共享)控制器中加载正确的类,这是很繁琐的
<?php
class SearchController
{
public function search()
{
if ($_SERVER['SERVER_NAME'] == 'straight.com') {
$search = new Straight\Search;
} else {
$search = new Gay\Search;
}
// ...
}
}
你明白我的意思了。这种代码让我感到不舒服,而且它很快就变得难以维护。我想要做的是这个
<?php
class SearchController
{
public function search()
{
$search = new Search;
// ...
}
}
...并在其他地方处理 Search
组件的覆盖。那时,Mural 就诞生了!
它是如何工作的
Mural 将自己添加到自动加载器堆栈中,并重新编写它指定的类名
<?php
$mural = new Monolyth\Mural\Autoloader;
$mural->rewrite('\\', 'Straight\\');
上述示例本质上表示“对于每个类,首先检查是否存在在Straight\\
下的版本。如果存在,则使用该版本”。
关于PHP有很多可以说的,但其自动加载机制设计得相当周到。如果没有“别名”类,Mural将直接将自动加载逻辑传递给链中的下一个自动加载器。
总结
在straight.com/index.php
<?php
$mural = new Monolyth\Mural\Autoloader;
$mural->rewrite('\\', 'Straight\\`);
...以及在gay.com/index.php
<?php
$mural = new Monolyth\Mural\Autoloader;
$mural->rewrite('\\', 'Gay\\');
...最后,在测试中,只需测试Straight\Search
和Gay\Search
。
Mural会盲目地检查字符串匹配,并在strpos === 0
时启动操作。因此,您也可以仅覆盖子命名空间,传递完整的类名等。
常见问题解答和注意事项
关于类型检查的注意事项
class_alias
重命名您的类,但保留其他“元数据”完整。因此,使用上述示例
<?php $search = new Search; echo get_class($search); // Straight\Search echo $search instanceof Straight\Search; // true echo $search instanceof Search; // also true!
类、特质、接口...
Mural支持所有这些。
递归性
对于全局重写(即,如上述示例中的空命名空间)Mural不会“递归”,即
<?php $mural->rewrite('\\', 'Foo\\'); // Bar gets rewritten to Foo\Bar, but Bar\Baz is autoloaded verbatim. class Bar extends Bar\Baz { } // To rewrite Bar\Baz to Foo\Bar\Baz as well, you'd need an extra call to // `rewrite` as follows: $mural->rewrite('Bar', 'Foo\\Bar\\');
简单的原因是对于全局命名空间,这会导致无限循环(以及段错误)。
前导和尾随反斜杠
前导反斜杠会自动删除,是可选的。尾随反斜杠很重要
1. Alias with a trailing backslash to specify a namespace;
2. Alias without the backslash to alias a _classname_.