Нет способа вызвать
$parent->test = "hello world!";
$parent->child = new B();
и автоматически имеет ссылку на $ parent в B.
Как правило, существует четыре способа структурирования ваших классов:
1. Агрегировать родительский объект с помощью инъекции, например
class B
{
private $parent;
public function __construct($parent)
{
$this->parent = $parent;
}
public function setParent($parent)
{
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Использовать внедрение конструктора, когда объект должен иметь родителя при создании. Это отношение has-a , и оно создает очень слабую связь. В B нет жестко закодированных зависимостей, поэтому вы можете легко заменить экземпляр Parent, например, с помощью Mock при UnitTesting. Использование Dependency Injection сделает ваш код более понятным.
В вашем UseCase вы передаете $parent
B при создании B:
$parent->child = new B($parent);
2. Использовать композицию
class B
{
private $parent;
public function __construct()
{
$this->parent = new Parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Это также отношение has-a , но оно связывает класс Parent с B. Это также не существующий экземпляр Parent, а новый экземпляр. Из формулировки я нахожу несколько странным иметь родителя, созданного ребенком. Используйте это, когда зависимость - это класс, который не считается существующим вне корневого класса, но является частью всего, что он представляет.
Для вашего UseCase нет способа сделать $parent->child = new B();
и знать, кто является родителем при использовании этого подхода, если только $ parent не является Singleton. Если это так, вы можете получить экземпляр Singleton, например, Parent::getInstance()
для достижения того, чего вы хотите, но учтите, что синглтоны - не любимая модель, например, трудно проверить.
3. Использовать наследование
class B extends Parent
{
public function accessParent()
{
$this->someMethodInParent();
}
}
Таким образом, вы создаете отношения is-a . Все открытые и защищенные методы и свойства из класса Parent (но не для конкретного экземпляра) будут доступны в B, и вы можете получить к ним доступ через ключевое слово $this
экземпляра B.
Для вашего UseCase этот подход не работает, так как вам вообще не нужно иметь экземпляр Parent, но B будет инкапсулировать все Parent при его создании
$b = new B;
4. Используйте глобальное ключевое слово
class B extends Parent
{
private $parent;
public function __construct()
{
global $parent;
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Ключевое слово global
импортирует глобальные переменные в текущую область. В целом, вам следует избегать использования глобального ключевого слова в контексте ОО, но используйте один из трех вышеупомянутых методов, предпочтительно первый. Несмотря на то, что это языковая функция, она не одобряется - хотя это следующая вещь, ближайшая к первой, например,
$parent->child = new B();
В любом случае, надеюсь, это поможет.