Як динамічно написати ім’я властивості об’єкта PHP?


83

У моєму коді є властивості об’єкта, які виглядають так:

$obj ->field_name_cars[0];
$obj ->field_name_clothes[0];

Проблема полягає в тому, що у мене 100 імен полів і мені потрібно динамічно писати назву властивості. В іншому випадку назва об’єкта та ключі властивості завжди будуть однаковими. Тому я спробував:

$obj -> $field[0];

Сподіваючись, що ім’я властивості буде динамічно змінюватися і матиме доступ до правильних значень. Але я продовжую отримувати поле "undefined property $ field" у stdClass :: $ field;

Більш-менш я намагаюся динамічно писати php перед його виконанням, щоб він міг вивести належні значення. Думки про те, як до цього підійти?

Відповіді:


210

Оновлення для PHP 7.0

PHP 7 вніс зміни до того, як непрямі змінні та властивості обробляються на рівні парсера (докладніше див. Відповідний RFC ). Це наближає фактичну поведінку до очікуваної і означає, що в цьому випадку $obj->$field[0]буде отримано очікуваний результат.

У випадках, коли (тепер покращена) поведінка за замовчуванням небажана, фігурні дужки все ще можна використовувати, щоб замінити її, як показано нижче.

Оригінальна відповідь

Напишіть доступ так:

$obj->{$field}[0]

Цей фокус "вкласти в фігурні дужки" корисний у PHP, коли є неоднозначність через змінні змінні.

Розглянемо початковий код $obj->$field[0]- чи означає це "доступ до властивості, ім'я якої вказано в $field[0]", або "доступ до елемента за допомогою ключа 0властивості, ім'я якої вказано в $field"? Дужки дозволяють бути чіткими.


Цей сирий вираз працює в моєму коді: echo $ json_dump-> geometry [6] -> obs [2] -> hayabusa2-> delay_from; Але я не можу "змоделювати" це, призначивши "геометрію [6] -> obs [2] -> hayabusa2-> delay_from" $ path та використовуючи echo $ json_dump -> {$ path}, я отримую "Невизначене властивість: stdClass: : $ geometry [6] "
стрибок

31

Я думаю, що ви шукаєте нотацію типу змінної-змінної, яку при доступі до значень з інших масивів / об’єктів найкраще досягти за допомогою синтаксису фігурних дужок, наприклад:

$obj->{field[0]}

12

Чарівний метод __get is you friend:

class MyClass
{
   private $field = array();

   public function __get($name)
   {
      if(isset($this->field[$name]))
        return $this->field[$name];
      else
        throw new Exception("$name dow not exists");
   }
}

Використання:

$myobj = new MyClass();
echo $myobj->myprop;

Пояснення: Усі ваші польові дані зберігаються в масиві. Коли ви отримуєте доступ, $myobj->mypropцього властивості, очевидно, не існує в класі. Саме там __getназивається. __getшукає ім'я в fieldмасиві і повертає правильне значення.


4
Не роби цього. Функції __get - це скачки продуктивності, яких слід уникати, коли це можливо, на додаток до створення серйозних проблем з несподіваною поведінкою. Цей приклад особливо страшний, оскільки він видає виняток, який може спричинити серйозну поведінку, що порушує роботу програми, якщо розробник не планує отримати доступ до неіснуючого атрибута, щоб видалити виняток, перетворюючи простий доступ до атрибута у потенційну фатальну помилку.
moberemk

1

сьогодні я стикаюся з цим викликом. Я закінчив з таким стилем розвитку

$countTickets = new \stdClass;

foreach ($tickets as $key => $value) {

    if(!isset($countTickets->total)){
        $countTickets->total = 0;
    }

    if(!isset($countTickets->{$value['categoryname']})){
        $countTickets->{$value['categoryname']} = 0;
    }

    $countTickets->total += $value['number'];
    $countTickets->{$value['categoryname']} += $value['number']; 
}

0

Я працював над деяким кодом, який використовував динамічно створені властивості об'єкта. Я вважав, що використання динамічно створених властивостей об’єктів було досить крутим (правда, на мій погляд). Однак для запуску моєї програми знадобилося 7 секунд. Я видалив властивості динамічного об’єкта і замінив їх властивостями об’єктів, оголошеними як частина кожного класу (у цьому випадку загальнодоступним). Час процесора перевищив більше 7 секунд до 0,177 секунди. Це досить істотно.

Можливо, я робив щось не так, як використовував динамічні властивості об'єкта. Також можливо, що моя конфігурація якимось чином порушена. Звичайно, я повинен сказати, що на моїй машині я маю дуже просту конфігурацію ванільного PHP.


Цей анекдот можна покращити, показавши невеликі фрагменти коду. Ваш код базувався на одній із відповідей тут? За інформацією в іншому місці, на яку ви можете дати посилання? Деякі однокласні вкладиші можуть бути всім необхідним. Приклад динамічного створення властивості об’єкта. А згодом посилання на цю властивість. Крім того, в середньому, скільки разів ви користувались (посиланням) кожним властивістю? Скільки динамічних властивостей ви додали до об’єкта? Менше шести? Більше 20?
ToolmakerSteve
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.