So, in the spirit of answering the question, of course there's a way (warning: here be dragons):
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;
}
Which can be used as so:
class Header
{
public function __construct()
{
$this->project = YouAreAnIdiotIfYouDoThisForReal(1);
$this->modules = YouAreAnIdiotIfYouDoThisForReal();
}
}
Now, this does what you ask. But please, under NO CIRCUMSTANCES should you actually do that.
Seriously.
I cannot stress how bad it would be if you were doing that.
It's fragile.
And dirty.
And relies on debug functionality.
And hard-coded relationships between construction order.
And other garbage.
Real Answer:
Instead, refactor to accept explicit dependencies:
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);
}
}
Your dependencies are explicit, and everything is clear as to what's happening where.
Even Better Yet
Even better yet, remove New from the equation entirely:
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);
Now, your code itself will be completely isolated, and not depend on anything. You can override each dependency as needed (say for testing, when you want to inject a fake project into Header()
)...
This is called Dependency Injection.
Seriously, don't use the first method. It was more of a joke than anything (to show what the power of PHP is, but good lord, no, that's evil...