class Header
{
public function __construct()
{
global $app;
print($app->config);
}
}
class Modules
{
public function __construct()
{
$this->header = new Header();
}
}
class Project
{
public $config = "config";
public function __construct()
{
$this->modules = new Modules();
}
}
$app = new Project();
现在,如果我想从Header
范围内访问根对象(即Project类的实例),我必须记住我为实例选择的名称(可能会有所不同)和使用global
关键字引用它。但我觉得这只是一个快速修复。我需要一种可靠的方法来访问根对象,从中构造当前对象(及其父对象)。
换句话说,我需要访问$app
内的$app->modules->header
,因为名称app
本身是可变的,而且链的长度也是动态的。
我可以访问父级的parent::
名称空间,但拥有first_ancestor::
之类的内容会很高兴。
答案 0 :(得分:12)
所以,本着回答这个问题的精神,当然有一种方式(警告:这里是龙):
function YouAreAnIdiotIfYouDoThisForReal($skip = 0) {
$bt = debug_backtrace();
if (isset($bt[1]['function']) && $bt[1]['function'] === "__construct") {
// called from constructor, so skip it!
$skip++;
}
foreach ($bt as $stack) {
if (isset($stack['function']) && $stack['function'] === "__construct" && $skip-- <= 0) {
return $stack['object'];
}
}
return null;
}
可以这样使用:
class Header
{
public function __construct()
{
$this->project = YouAreAnIdiotIfYouDoThisForReal(1);
$this->modules = YouAreAnIdiotIfYouDoThisForReal();
}
}
现在,这就是你所要求的。但是,请在没有情况下你真的应该这样做。
严重。
我不能强调如果你这样做会有多糟糕。
它很脆弱。
肮脏。
依赖于调试功能。
施工顺序之间的硬编码关系。
和其他垃圾一样。
相反,重构接受显式依赖:
class Header
{
public function __construct(Project $project, Modules $modules)
{
$this->project = $project;
$this->modules = $modules;
}
}
class Modules
{
public function __construct(Project $project)
{
$this->project = $project;
$this->header = new Header($project, $this);
}
}
class Project
{
public $config = "config";
public function __construct()
{
$this->modules = new Modules($this);
}
}
您的依赖关系是明确的,并且一切都清楚地知道发生了什么。
更好的是,完全从等式中删除New:
class Header
{
public function __construct(Project $project)
{
$this->project = $project;
}
}
class Modules
{
public function __construct(Header $header)
{
$this->header = $header;
}
}
class Project
{
public $config = "config";
public function __construct()
{
}
public function setModules(Modules $modules) {
$this->modules = $modules;
}
}
$project = new Project();
$headers = new Header($project);
$modules = new Modules($headers);
$project->setModules($modules);
现在,您的代码本身将完全隔离,而不依赖于任何东西。您可以根据需要覆盖每个依赖项(例如,当您想要将假项目注入Header()
时进行测试)...
说真的,不要使用第一种方法。它更像是一个笑话而不是任何东西(展示PHP的力量,但是好主,不,那是邪恶......