Holen Sie sich die PHP-Klasseneigenschaft nach Zeichenfolge

139

Wie erhalte ich eine Eigenschaft in einem PHP basierend auf einer Zeichenfolge? Ich werde es nennen magic. Also was ist magic?

$obj->Name = 'something';
$get = $obj->Name;

wäre wie...

magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');
Daniel A. White
quelle

Antworten:

241

So was

<?php

$prop = 'Name';

echo $obj->$prop;

Wenn Sie die Kontrolle über die Klasse haben, implementieren Sie die ArrayAccess- Schnittstelle und führen Sie dies einfach aus

echo $obj['Name'];
Peter Bailey
quelle
Gibt es einen Vorteil bei der Verwendung der zweiten Option gegenüber der ersten?
Clox
2
@Clox Im Allgemeinen ist der Hauptvorteil der Verwendung des letzteren, wenn Sie ein vorhandenes System haben, das eine Variable auf Array-ähnliche Weise verwendet, aber die Flexibilität und Leistung von Objekten wünschen. Wenn eine Klasse implementiert ArrayAccess, Countableund einer der Iterator - Schnittstellen, ist es meist nicht von einem normalenarray()
Peter Bailey
158

Wenn Sie auf die Eigenschaft zugreifen möchten, ohne eine Zwischenvariable zu erstellen, verwenden Sie die {}Notation:

$something = $object->{'something'};

Auf diese Weise können Sie den Eigenschaftsnamen auch in einer Schleife erstellen, zum Beispiel:

for ($i = 0; $i < 5; $i++) {
    $something = $object->{'something' . $i};
    // ...
}
Laurent
quelle
8
Dies ist die einzige Möglichkeit, wenn Sie auf einen Array-Wert zugreifen möchten $this->{$property}[$name], andernfalls $this->$property[$name]wird ein Fehler
ausgegeben
@goyote: Es kommt auf Werte und PHP-Version an. In 5.3 wird ein E_NOTICE ausgelöst, da die Eigenschaft nicht gefunden werden kann, sondern ein "Fehler", da die PHP-Syntax weiterhin gültig ist. Es ist möglich, dass dies $this->$property[$name]tatsächlich gelingt, obwohl dies wahrscheinlich ein Fehler ist. $namewird stillschweigend in eine ganze Zahl umgewandelt. Im Fall einer nicht numerischen Zeichenfolge ist dies 0. Dann ist dieser String - Index des Wertes $propertywird als Eigenschaftsnamen verwendet. Wenn $propertyder Wert "abc" enthalten ist, bezieht sich dies auf die Eigenschaft $this->a(Index 0). Wenn es eine solche Eigenschaft gibt, ist dies erfolgreich.
MrWhite
@goyote: In PHP 5.4 wird ein nicht numerischer Zeichenfolgenindex jedoch nicht stillschweigend in die Ganzzahl 0 umgewandelt, sondern es wird eine E_WARNING ausgelöst.
MrWhite
13

Was Sie fragen, heißt Variable Variablen . Alles, was Sie tun müssen, ist, Ihre Zeichenfolge in einer Variablen zu speichern und wie folgt darauf zuzugreifen:

$Class = 'MyCustomClass';
$Property = 'Name';
$List = array('Name');

$Object = new $Class();

// All of these will echo the same property
echo $Object->$Property;  // Evaluates to $Object->Name
echo $Object->{$List[0]}; // Use if your variable is in an array
Matpie
quelle
3
Variablenvariablen sind eine andere Sache.
Ólafur Waage
2
Die Frage ist, wie man eine Klasseneigenschaft (Variable) erhält, wenn der Name in einer Zeichenfolge (Variable) enthalten ist. Oder habe ich die Frage falsch verstanden?
Matpie
8

Etwas wie das? Ich habe es nicht getestet, sollte aber gut funktionieren.

function magic($obj, $var, $value = NULL)
{
    if($value == NULL)
    {
        return $obj->$var;
    }
    else
    {
        $obj->$var = $value;
    }
}
Ólafur Waage
quelle
2
+1, wusste nicht, dass Objekteigenschaften mithilfe von Zeichenfolgen aufgerufen werden können.
Marco Demaio
5

Speichern Sie einfach den Eigenschaftsnamen in einer Variablen und verwenden Sie die Variable, um auf die Eigenschaft zuzugreifen. So was:

$name = 'Name';

$obj->$name = 'something';
$get = $obj->$name;
Jon Benedicto
quelle
5

Möglicherweise gibt es Antworten auf diese Frage, aber Sie möchten möglicherweise diese Migrationen zu PHP 7 sehen

rückwärts inkompatible Änderung

Quelle: php.net

Muhammad Maulana
quelle
4

Es ist einfach, $ obj -> {$ obj-> Name} die geschweiften Klammern umschließen die Eigenschaft ähnlich einer variablen Variablen.

Dies war eine Top-Suche. Aber meine Frage, die $ this verwendete, wurde nicht gelöst. In meinem Fall half auch die Verwendung der geschweiften Klammer ...

Beispiel mit Code Igniter get Instanz

in einer Quellbibliotheksklasse, die mit einer übergeordneten Klasseninstanz aufgerufen wird

$this->someClass='something';
$this->someID=34;

Die Bibliotheksklasse muss auch mit der übergeordneten Instanz aus einer anderen Klasse stammen

echo $this->CI->{$this->someClass}->{$this->someID};
Mark Allen
quelle
2

Nur als Ergänzung: Auf diese Weise können Sie auf Eigenschaften mit Namen zugreifen, die sonst unbrauchbar wären

$ x = neue StdClass;

$ prop = 'a b'; $ x -> $ prop = 1; $ x -> {'x y'} = 2; var_dump ($ x);

Objekt (stdClass) # 1 (2) {
  ["a b"] =>
  int (1)
  ["x y"] =>
  int (2)
}}
(nicht das du solltest, aber falls du musst).
Wenn Sie noch schickere Sachen machen wollen, sollten Sie sich mit Reflexion befassen

VolkerK
quelle
1

Für den Fall, dass jemand anderes eine tiefe Eigenschaft unbekannter Tiefe finden möchte, habe ich mir das Folgende ausgedacht, ohne alle bekannten Eigenschaften aller Kinder durchlaufen zu müssen.

Zum Beispiel, um $ Foo-> Bar-> baz oder $ Foo-> baz oder $ Foo-> Bar-> Baz-> dave zu finden, wobei $ path eine Zeichenfolge wie 'foo / bar / baz' ist.

public function callModule($pathString, $delimiter = '/'){

    //split the string into an array
    $pathArray = explode($delimiter, $pathString);

    //get the first and last of the array
    $module = array_shift($pathArray);
    $property = array_pop($pathArray);

    //if the array is now empty, we can access simply without a loop
    if(count($pathArray) == 0){
        return $this->{$module}->{$property};
    }

    //we need to go deeper
    //$tmp = $this->Foo
    $tmp = $this->{$module};

    foreach($pathArray as $deeper){
        //re-assign $tmp to be the next level of the object
        // $tmp = $Foo->Bar --- then $tmp = $Bar->baz
        $tmp = $tmp->{$deeper};
    }

    //now we are at the level we need to be and can access the property
    return $tmp->{$property};

}

Und dann mit so etwas anrufen wie:

$propertyString = getXMLAttribute('string'); // '@Foo/Bar/baz'
$propertyString = substr($propertyString, 1);
$moduleCaller = new ModuleCaller();
echo $moduleCaller->callModule($propertyString);
Jordan Whitfield
quelle
0

Hier ist mein Versuch. Es sind einige allgemeine Dummheitsprüfungen integriert, die sicherstellen, dass Sie nicht versuchen, ein Mitglied zu setzen oder zu bekommen, das nicht verfügbar ist.

Sie können diese 'property_exists'-Prüfungen auf __set bzw. __get verschieben und sie direkt in magic () aufrufen.

<?php

class Foo {
    public $Name;

    public function magic($member, $value = NULL) {
        if ($value != NULL) {
            if (!property_exists($this, $member)) {
                trigger_error('Undefined property via magic(): ' .
                    $member, E_USER_ERROR);
                return NULL;
            }
            $this->$member = $value;
        } else {
            if (!property_exists($this, $member)) {
                trigger_error('Undefined property via magic(): ' .
                    $member, E_USER_ERROR);
                return NULL;
            }
            return $this->$member;
        }
    }
};

$f = new Foo();

$f->magic("Name", "Something");
echo $f->magic("Name") , "\n";

// error
$f->magic("Fame", "Something");
echo $f->magic("Fame") , "\n";

?>
Nick Presta
quelle
0

Diese Funktion prüft, ob die Eigenschaft für diese Klasse eines Kindes vorhanden ist, und erhält in diesem Fall den Wert, andernfalls wird null zurückgegeben. Jetzt sind die Eigenschaften optional und dynamisch.

/**
 * check if property is defined on this class or any of it's childes and return it
 *
 * @param $property
 *
 * @return bool
 */
private function getIfExist($property)
{
    $value = null;
    $propertiesArray = get_object_vars($this);

    if(array_has($propertiesArray, $property)){
        $value = $propertiesArray[$property];
    }

    return $value;
}

Verwendung:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';

$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);
Mahmoud Zalt
quelle
-6
$classname = "myclass";
$obj = new $classname($params);

$variable_name = "my_member_variable";
$val = $obj->$variable_name; //do care about the level(private,public,protected)

$func_name = "myFunction";
$val = $obj->$func_name($parameters);

warum bearbeiten: vorher: mit eval (böse) nachher: ​​überhaupt kein eval. in dieser Sprache alt sein.

r4ccoon
quelle
Dies ist ein sehr schlechter Rat, die eval () -Funktion ist ein sehr gefährliches Werkzeug und macht Sie äußerst anfällig für Injektionsangriffe. blog.highub.com/php/php-core/php-eval-is-evil sollte Ihnen einige Informationen geben.
Ridecar2
3
Löschen Sie diese Antwort und Sie erhalten ein Abzeichen!
Thermech