PHP: цепочка свойств класса в переменных переменных - PullRequest
3 голосов
/ 21 марта 2011

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

$person->contact->phone;
$person->contact->email;
$person->contact->address->line_1;
$person->contact->address->line_2;
$person->dob->day;
$person->dob->month;
$person->dob->year;
$album->name;
$album->image->height;
$album->image->width;
$album->artist->name;
$album->artist->id;

и т.д ... (обратите внимание, что эти примеры не связаны друг с другом).

Можно ли использовать переменные переменные для вызова contact->phone как прямого свойства $person?

Например:

$property = 'contact->phone';
echo $person->$property;

Это не будет работать как есть и выдает E_NOTICE, поэтому я пытаюсь найти альтернативный метод для достижения этой цели.

Есть идеи?

В ответ на ответы, касающиеся прокси-методов:

И я бы исключил этот объект из библиотеки и использую его для заполнения нового объекта картой массивов следующим образом:

array(
  'contactPhone' => 'contact->phone', 
  'contactEmail' => 'contact->email'
);

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

Ответы [ 14 ]

0 голосов
/ 21 марта 2011

Как бы мне не хотелось это говорить, вы можете сделать eval:

foreach ($properties as $property) {
     echo eval("return \$person->$property;");
}
0 голосов
/ 21 марта 2011

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

В приведенном выше примере персона имеет контакт и доб . контакт также содержит адрес . Попытка получить доступ к данным на самом верхнем уровне не редкость при написании сложных приложений для баз данных. Тем не менее, вы можете найти лучшее решение для этого - объединить данные в класс person , вместо того, чтобы пытаться по существу «майнить» во внутренние объекты.

0 голосов
/ 21 марта 2011

Вы можете использовать приведение типов, чтобы изменить объект на массив.

$person = (array) $person;

echo $person['contact']['phone'];
0 голосов
/ 21 марта 2011

ООП - это много, чтобы защитить внутренние объекты от внешнего мира. То, что вы пытаетесь сделать здесь, это предоставить способ опубликовать внутренности phone через интерфейс person. Это не приятно.

Если вам нужен удобный способ получить «все» свойства, вы можете написать явный набор вспомогательных функций для этого, возможно, при желании обернутый в другой класс. Таким образом, вы можете развивать поддерживаемые утилиты, не затрагивая (и, возможно, не нарушая) основные структуры данных:

class conv {
 static function phone( $person ) {
   return $person->contact->phone;
 }

}

// imagine getting a Person from db
$person = getpersonfromDB();

print conv::phone( $p );

Если вам когда-нибудь понадобится более специализированная функция, добавьте ее в утилиты. Это лучшее решение: отделить удобство от ядра, чтобы уменьшить сложность и повысить удобство обслуживания / понятность.

Другим способом является «расширение» класса Person с помощью удобств, построенных на основе базового класса:

class ConvPerson extends Person {
   function __construct( $person ) {
     Person::__construct( $person->contact, $person->name, ... );
   }
   function phone() { return $this->contact->phone; }
}

// imagine getting a Person from db
$person = getpersonfromDB();
$p=new ConvPerson( $person );
print $p->phone();
...