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

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

$parent->test = "hello world!";

$parent->child = new B();

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

class B{

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

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

Спасибо!

Ответ 1

Нет способа вызвать

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

и автоматически ссылается на $parent в B.


Как правило, существует четыре способа структурирования ваших классов:

1. Совокупность родительского объекта через Injection, например

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();
     }
}

Это также отношение 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();
    }
}

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

$parent->child = new B();

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

Ответ 2

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

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

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

Ответ 3

Возможно, это может быть полезно в некоторых случаях: он не доставляет родительский объект в 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

Ответ 4

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

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

Ответ 5

Нет.

Вы можете получить доступ к переменным из суперкласса, используя $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();
?>

Ответ 6

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

class B {
public data;

}
class A { 
public children= array(); 

public function new_child($text='my name is data') {
$child=new B;
$this->children[]=$child;
$this->data=$text;
return $child;
}

public function print_everything () {
foreach($this->children as $child) echo $child->data;
}
}

$parent = new A;
$child = $p->new_child()
$child2 = $p->new_child('im no data')

echo $child->data  // should print 'my name is data' 
echo $child2->data // should print 'im no data'
$child->data = 'somthingelse'
echo $child->data // should print 'somthingelse'

$p->print_everything(); // should print : 'somthingelse' & 'im no data'

поэтому, если вы хотите получить доступ к родительской функции или данным, вы должны поместить эту функцию в родительский объект, а не в дочерний. помните, что родитель также является "экземпляром" своего собственного класса.