Dapatkan properti kelas PHP dengan string

139

Bagaimana cara mendapatkan properti di PHP berdasarkan string? Saya akan menyebutnya magic. Jadi apa magic?

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

akan menjadi...

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

Jawaban:

241

Seperti ini

<?php

$prop = 'Name';

echo $obj->$prop;

Atau, jika Anda memiliki kendali atas kelas, terapkan antarmuka ArrayAccess dan lakukan saja ini

echo $obj['Name'];
Peter Bailey
sumber
Adakah manfaat menggunakan opsi kedua dari yang pertama?
Clox
2
@ Clox Secara umum, manfaat utama menggunakan yang terakhir jika jika Anda memiliki sistem yang sudah ada yang mengkonsumsi variabel dengan cara seperti array, tetapi Anda ingin fleksibilitas dan kekuatan yang ditawarkan oleh objek. Jika sebuah kelas mengimplementasikan ArrayAccess,, Countabledan salah satu antarmuka iterator, itu sebagian besar tidak dapat dibedakan dari normalarray()
Peter Bailey
158

Jika Anda ingin mengakses properti tanpa membuat variabel perantara, gunakan {}notasi:

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

Itu juga memungkinkan Anda untuk membangun nama properti dalam satu lingkaran misalnya:

for ($i = 0; $i < 5; $i++) {
    $something = $object->{'something' . $i};
    // ...
}
laurent
sumber
8
Ini adalah satu-satunya cara jika Anda ingin mengakses nilai array $this->{$property}[$name], jika tidak $this->$property[$name]akan menimbulkan kesalahan
goyote
@ goyote: Tergantung nilai dan versi PHP. Pada 5.3 ia memicu E_NOTICE karena properti tidak dapat ditemukan, bukan "kesalahan", karena masih sintaks PHP yang valid. Ada kemungkinan yang $this->$property[$name]mungkin benar-benar berhasil, meskipun ini kemungkinan merupakan bug. $namediam-diam dilemparkan ke bilangan bulat. Dalam kasus string non-numerik ini 0. Kemudian indeks string dari nilai $propertyini digunakan sebagai nama properti. Jika $propertymemegang nilai "abc", maka ini akan merujuk ke properti $this->a(indeks 0). Jika ada properti seperti itu maka ini akan berhasil.
MrWhite
@ goyote: Namun, dalam PHP 5.4, indeks string non-numerik tidak secara diam-diam dilemparkan ke integer 0, itu akan memicu E_WARNING.
MrWhite
13

Apa yang Anda tanyakan disebut Variabel Variabel . Yang perlu Anda lakukan adalah menyimpan string Anda dalam variabel dan mengaksesnya seperti ini:

$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
sumber
3
Variabel variabel adalah hal lain.
Ólafur Waage
2
Pertanyaannya adalah bagaimana cara mendapatkan properti kelas (variabel) ketika nama tersebut terkandung dalam string (variabel). Atau apakah saya salah membaca pertanyaan?
matpie
8

Sesuatu seperti ini? Belum mengujinya tetapi harus bekerja dengan baik.

function magic($obj, $var, $value = NULL)
{
    if($value == NULL)
    {
        return $obj->$var;
    }
    else
    {
        $obj->$var = $value;
    }
}
Ólafur Waage
sumber
2
+1, tidak tahu properti objek dapat diakses menggunakan string.
Marco Demaio
5

Cukup simpan nama properti dalam variabel, dan gunakan variabel untuk mengakses properti. Seperti ini:

$name = 'Name';

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

Mungkin ada jawaban untuk pertanyaan ini, tetapi Anda mungkin ingin melihat migrasi ini ke PHP 7

perubahan tidak kompatibel mundur

sumber: php.net

Muhammad Maulana
sumber
4

Sederhana, $ obj -> {$ obj-> Name} kurung keriting akan membungkus properti seperti variabel variabel.

Ini adalah pencarian teratas. Tetapi tidak menyelesaikan pertanyaan saya, yang menggunakan $ this. Dalam hal keadaan saya menggunakan braket keriting juga membantu ...

contoh dengan Code Igniter get instance

di kelas pustaka sumber yang disebut sesuatu dengan instance kelas induk

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

kelas perpustakaan yang perlu sumber dari kelas lain juga dengan contoh orang tua

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

Sama seperti tambahan: Dengan cara ini Anda dapat mengakses properti dengan nama yang tidak dapat digunakan

$ x = StdClass baru;

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

object (stdClass) # 1 (2) {
  ["a b"] =>
  int (1)
  ["x y"] =>
  int (2)
}
(bukan bahwa Anda harus, tetapi jika Anda harus).
Jika Anda ingin melakukan hal-hal yang lebih mewah, Anda harus melihat ke dalam refleksi

VolkerK
sumber
1

Seandainya ada orang lain yang ingin menemukan properti yang dalam dari kedalaman yang tidak diketahui, saya datang dengan yang di bawah ini tanpa perlu mengulang semua properti yang diketahui dari semua anak.

Misalnya, untuk menemukan $ Foo-> Bar-> baz, atau $ Foo-> baz, atau $ Foo-> Bar-> Baz-> dave, di mana $ path adalah string seperti 'foo / bar / baz'.

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

}

Dan kemudian panggil dengan sesuatu seperti:

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

Ini usahaku. Ini memiliki beberapa pemeriksaan 'kebodohan' yang umum, memastikan Anda tidak mencoba mengatur atau mendapatkan anggota yang tidak tersedia.

Anda dapat memindahkan cek 'property_exists' tersebut ke __set dan __get masing-masing dan memanggilnya langsung dalam magic ().

<?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
sumber
0

Apa fungsi ini adalah memeriksa apakah properti ada di kelas ini dari salah satu anaknya, dan jika demikian ia mendapat nilai sebaliknya mengembalikan nol. Jadi sekarang propertinya opsional dan dinamis.

/**
 * 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;
}

Pemakaian:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';

$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);
Mahmoud Zalt
sumber
-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);

why edit: before: using eval (evil) after: no eval at all. sudah tua dalam bahasa ini.

r4ccoon
sumber
Ini saran yang sangat buruk, fungsi eval () adalah alat yang sangat berbahaya dan akan membuat Anda sangat rentan terhadap serangan injeksi. blog.highub.com/php/php-core/php-eval-is-evil akan memberi Anda beberapa informasi.
ridecar2
3
Hapus jawaban ini dan Anda akan memiliki lencana!
Thermech