Jak dynamicznie zapisać nazwę właściwości obiektu PHP?

83

Mam właściwości obiektu w moim kodzie, które wyglądają następująco:

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

Problem polega na tym, że mam setki nazw pól i muszę dynamicznie zapisywać nazwę właściwości. W przeciwnym razie nazwa obiektu i klucze właściwości będą zawsze takie same. Więc spróbowałem:

$obj -> $field[0];

Mając nadzieję, że nazwa właściwości zostanie dynamicznie zmieniona i uzyska dostęp do poprawnych wartości. Ale ciągle otrzymuję 'undefined property $ field in stdClass :: $ field;

Mniej więcej próbuję dynamicznie zapisywać php przed jego wykonaniem, aby mógł wyprowadzać właściwe wartości. Zastanawiasz się, jak do tego podejść?

user658182
źródło

Odpowiedzi:

210

Aktualizacja dla PHP 7.0

W PHP 7 wprowadzono zmiany w sposobie obsługi zmiennych pośrednich i właściwości na poziomie parsera ( więcej szczegółów można znaleźć w odpowiednim dokumencie RFC ). To przybliża rzeczywiste zachowanie do oczekiwanego i oznacza, że ​​w tym przypadku$obj->$field[0] przyniesie oczekiwany rezultat.

W przypadkach, gdy (teraz ulepszone) zachowanie domyślne jest niepożądane, nadal można użyć nawiasów klamrowych, aby je zastąpić, jak pokazano poniżej.

Oryginalna odpowiedź

Wpisz dostęp w ten sposób:

$obj->{$field}[0]

Ta sztuczka "ujęć w nawiasy" jest przydatna w PHP, gdy występuje niejednoznaczność z powodu zmiennych zmiennych.

Rozważmy kod początkowy $obj->$field[0]- czy to oznacza „dostęp do właściwości, której nazwa jest podana w $field[0]”, czy „dostęp do elementu z kluczem 0właściwości, której nazwa jest podana w $field”? Szelki pozwalają wyrazić się wyraźnie.

Jon
źródło
Ta surowa instrukcja działa w moim kodzie: echo $ json_dump-> geometry [6] -> obs [2] -> hayabusa2-> delay_from; Ale nie mogę tego „zasymulować”, przypisując „geometry [6] -> obs [2] -> hayabusa2-> delay_from” do ścieżki $ path i używając echo $ json_dump -> {$ path}, otrzymuję „Undefined property: stdClass: : $ geometry [6] "
Jumpjack
31

Myślę, że szukasz notacji typu zmienna-zmienna, która podczas uzyskiwania dostępu do wartości z innych tablic / obiektów najlepiej osiągnąć za pomocą składni nawiasów klamrowych w następujący sposób:

$obj->{field[0]}
Mike Brant
źródło
12

Magiczna metoda __get to twój przyjaciel:

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

Stosowanie:

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

Objaśnienie: Wszystkie dane pola są przechowywane w tablicy. Gdy uzyskujesz dostęp, $myobj->mypropta właściwość oczywiście nie istnieje w klasie. To jest, gdzie __getjest nazywany. __getwyszukuje nazwę w fieldtablicy i zwraca poprawną wartość.

JvdBerg
źródło
4
Nie rób tego. Funkcje __get są ograniczeniami wydajności, których należy unikać, gdy jest to możliwe, oprócz tworzenia poważnych problemów z nieoczekiwanym zachowaniem. Ten przykład jest szczególnie przerażający, ponieważ zgłasza wyjątek, który może powodować poważne zachowanie zerwania aplikacji, jeśli deweloper nie planuje dostępu do nieistniejącego atrybutu w celu wyrzucenia wyjątku, zmieniając prosty dostęp do atrybutu w potencjalny błąd krytyczny.
moberemk
1

dziś stoję przed tym wyzwaniem. Skończyło się na tym stylu rozwoju

$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']; 
}
Jordan Georgiadis
źródło
0

Pracowałem nad kodem, który używał dynamicznie tworzonych właściwości obiektów. Pomyślałem, że używanie dynamicznie tworzonych właściwości obiektów jest całkiem fajne (moim zdaniem prawda). Jednak mój program działał 7 sekund. Usunąłem dynamiczne właściwości obiektu i zastąpiłem je właściwościami obiektu zadeklarowanymi jako część każdej klasy (w tym przypadku publicznymi). Czas procesora wzrósł z ponad 7 sekund do 0,177 sekundy. To całkiem pokaźne.

Możliwe, że robiłem coś złego w sposobie korzystania z dynamicznych właściwości obiektu. Możliwe też, że moja konfiguracja jest w jakiś sposób zepsuta. Oczywiście powinienem powiedzieć, że mam bardzo prostą, waniliową konfigurację PHP na moim komputerze.

Peter Schaeffer
źródło
Tę anegdotę można poprawić, pokazując małe fragmenty kodu. Czy Twój kod był oparty na jednej z odpowiedzi tutaj? W informacjach, do których możesz podać link? Potrzebne mogą być tylko niektóre jednolinijki. Przykład dynamicznego tworzenia właściwości obiektu. A później odwołanie do tej właściwości. Ponadto, średnio, ile razy korzystałeś ( aś ) z każdej właściwości? Ile właściwości dynamicznych dodałeś do obiektu? Mniej niż sześć? Więcej niż 20?
ToolmakerSteve