Родительский объект в php

есть ли способ пересечь объект, чтобы получить данные родительского объекта? С «родительским объектом» я не имею в виду родительский класс, но буквально объект. Вот пример, в мире javascripty :-):

$parent->test = "hello world!"; $parent->child = new B(); 

Было бы здорово, если бы я мог получить доступ ко всем данным от родителя в дочернем объекте:

 class B{ //I know this doesn't exists, but it's what I wanted do do function B(){ $this->parent = $this->parent(); echo $this->parent->test; //it would ouput "hello world" } } 

На данный момент мое решение – передать родительский объект дочернему элементу (в качестве ссылки) или сделать родительский глобальным. У вас есть лучшее решение?

Благодаря!

Невозможно вызвать

 $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(); } } , 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 нет закодированных зависимостей, поэтому вы можете легко заменить экземпляр родителя, например, с помощью 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(); } } , class B { private $parent; public function __construct() { $this->parent = new Parent; } public function accessParent() { $this->parent->someMethodInParent(); } } 

Это также отношение has-a , но сопрягает класс Parent с B. Это также не существующий родительский экземпляр, а новый экземпляр. Из формулировки я считаю несколько странным иметь родителя, созданного ребенком. Используйте это, когда зависимость – это класс, который не считается существующим вне корневого класса, но является частью всего, что он представляет.

Для вашего UseCase нет способа сделать $parent->child = new B(); и знать, что такое родитель при использовании этого подхода, если только $ parent не является Singleton. Если это так, вы можете получить экземпляр Singleton, например Parent::getInstance() чтобы достичь того, чего вы хотите, но обратите внимание, что Singletons не являются любимым шаблоном каждого пользователя, например, трудно тестировать.

3. Использовать наследование

 class B extends Parent { public function accessParent() { $this->someMethodInParent(); } } 

Таким образом вы создаете отношения is-a . Все общедоступные и защищенные методы и свойства класса Parent (но не определенного экземпляра) будут доступны в B, и вы можете получить к ним доступ через ключевое слово $this экземпляра экземпляра B.

Для вашего UseCase этот подход не работает, так как вам не обязательно иметь экземпляр родителя вообще, но B будет инкапсулировать все из родителя, когда он будет создан

 $b = new B; 

4. Используйте глобальное ключевое слово

 class B extends Parent { private $parent; public function __construct() { global $parent; $this->parent = $parent; } public function accessParent() { $this->parent->someMethodInParent(); } } , class B extends Parent { private $parent; public function __construct() { global $parent; $this->parent = $parent; } public function accessParent() { $this->parent->someMethodInParent(); } } 

global ключевое слово импортирует глобальные переменные в текущую область. В общем, вам следует избегать использования ключевого слова global в контексте OO, но используйте один из трех других методов выше, предпочтительно первый. Хотя это языковая функция, она нахмурилась – хотя это будет следующая ближайшая вещь к первой, например

 $parent->child = new B(); 

В любом случае, надеюсь, что это поможет.

Передача родителя ребенку – лучшее решение. Хотя это несколько нежелательные симбиотические отношения.

Должен ли B () иметь какое-либо знание объекта, это атрибут? Скорее всего, нет. Они связаны только по композиции.

Почему B () должен быть атрибутом его родителя? Вам нужно иметь эту реализацию в B () или она должна быть частью родителя?

Возможно, это может быть полезно в некоторых случаях: он не доводит родительский объект до ChildClass очень рано в конструкторе, но на один шаг позже. Он играет с возможностью перехвата несуществующего метода:

 class ParentClass { const CHILD_PROPERTY_NAME = 'child'; public $data = 'Some data'; public function __set($property_name, $property_value) { if ($property_name == self::CHILD_PROPERTY_NAME) { $property_value->set_parent_object($this); } } } class ChildClass { private $parent_object = null; public function set_parent_object($object) { $this->parent_object = $object; echo $this->parent_object->data; } } $p = new ParentClass(); $p->child = new ChildClass(); 

Это приведет к выходу Some data

Нет.

Вы можете получить доступ к переменным из суперкласса, используя $ this:

 <?php class A { public function __construct() { $this->foo = 'hello'; } } class B extends A { public function printFoo() { echo $this->foo; } } $b = new B(); $b->printFoo(); ?> 

Я уверен, что PHP не имеет ничего подобного.

Думаю, ваше решение о передаче родительского объекта ребенку – лучшее решение. Вы должны подумать о том, чтобы установить родительское свойство только в конструкторе дочернего элемента, чтобы у нескольких родителей не было одного и того же ребенка.