Obter propriedade da classe PHP por string

139

Como obtenho uma propriedade em um PHP com base em uma string? Eu ligo magic. Então o que é magic?

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

Seria como...

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

Respostas:

241

Como isso

<?php

$prop = 'Name';

echo $obj->$prop;

Ou, se você tiver controle sobre a classe, implemente a interface ArrayAccess e faça isso

echo $obj['Name'];
Peter Bailey
fonte
Algum benefício de usar a segunda opção sobre a primeira?
Clox
2
@Clox Geralmente, o principal benefício de usá-lo se você possui um sistema existente que consome uma variável de maneira semelhante a um array, mas deseja a flexibilidade e a energia oferecidas pelos objetos. Se uma classe implementa ArrayAccess, Countablee uma das interfaces de iterador, é principalmente indistinguível de um normaisarray()
Peter Bailey
158

Se você deseja acessar a propriedade sem criar uma variável intermediária, use a {}notação:

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

Isso também permite criar o nome da propriedade em um loop, por exemplo:

for ($i = 0; $i < 5; $i++) {
    $something = $object->{'something' . $i};
    // ...
}
Laurent
fonte
8
Esta é a única forma, se você quiser acessar um valor de array $this->{$property}[$name], caso contrário, $this->$property[$name]irá lançar um erro
goyote
@ goyote: Depende dos valores e da versão do PHP. Na versão 5.3, ele aciona um E_NOTICE porque a propriedade não pode ser encontrada, em vez de um "erro", pois ainda é uma sintaxe PHP válida. É possível que $this->$property[$name]tenha sucesso, embora isso provavelmente seja um bug. $nameé convertido silenciosamente em um número inteiro. No caso de uma sequência não numérica, é isso 0. Em seguida, este índice de sequência do valor de $propertyé usado como o nome da propriedade. Se $propertymantiver o valor "abc", isso se referirá à propriedade $this->a(índice 0). Se existir essa propriedade, isso será bem-sucedido.
MrWhite
@ goyote: No entanto, no PHP 5.4, um índice de string não numérico não é convertido silenciosamente no número inteiro 0, ele acionará um E_WARNING.
MrWhite
13

O que você está perguntando é chamado de Variáveis ​​variáveis . Tudo o que você precisa fazer é armazenar sua string em uma variável e acessá-la da seguinte forma:

$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
fonte
3
Variáveis ​​variáveis ​​são outra coisa.
Ólafur Waage
2
A questão é como obter uma propriedade de classe (variável) quando o nome está contido em uma string (variável). Ou interpretei mal a pergunta?
matpie
8

Algo assim? Ainda não testei, mas deve funcionar bem.

function magic($obj, $var, $value = NULL)
{
    if($value == NULL)
    {
        return $obj->$var;
    }
    else
    {
        $obj->$var = $value;
    }
}
Ólafur Waage
fonte
2
+1, não sabia que as propriedades do objeto poderiam ser acessadas usando seqüências de caracteres.
Marco Demaio 23/01
5

Apenas armazene o nome da propriedade em uma variável e use a variável para acessar a propriedade. Como isso:

$name = 'Name';

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

Pode haver respostas para esta pergunta, mas você pode querer ver essas migrações para o PHP 7

mudança incompatível com versões anteriores

fonte: php.net

Muhammad Maulana
fonte
4

É simples, $ obj -> {$ obj-> Name}, os colchetes enrolam a propriedade como uma variável variável.

Esta foi uma das principais pesquisas. Mas não resolvi minha pergunta, que estava usando $ this. No caso da minha circunstância, usar o suporte encaracolado também ajudou ...

exemplo com a instância get do Code Igniter

em uma classe de biblioteca de origem chamada algo com uma instância de classe pai

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

a classe da biblioteca que precisa originar de outra classe também com a instância dos pais

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

Apenas como uma adição: dessa forma, você pode acessar propriedades com nomes que, de outra forma, não poderiam ser utilizados

$ x = novo StdClass;

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

objeto (stdClass) nº 1 (2) {
  ["a b"] =>
  int (1)
  ["x y"] =>
  int (2)
}
(não que você deva, mas no caso de precisar).
Se você quiser fazer coisas ainda mais extravagantes, deve refletir

VolkerK
fonte
1

Caso alguém mais queira encontrar uma propriedade profunda de profundidade desconhecida, vim com o abaixo, sem precisar percorrer todas as propriedades conhecidas de todas as crianças.

Por exemplo, para encontrar $ Foo-> Bar-> baz, ou $ Foo-> baz, ou $ Foo-> Bar-> Baz-> dave, onde $ path é uma string como '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};

}

E depois chame com algo como:

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

Aqui está a minha tentativa. Possui algumas verificações comuns de 'estupidez', garantindo que você não tente definir ou obter um membro que não esteja disponível.

Você pode mover esses cheques 'property_exists' para __set e __get respectivamente e chamá-los diretamente em 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
fonte
0

O que essa função faz é verificar se a propriedade existe nesta classe de algum filho de seu filho e, se houver, obtém o valor, caso contrário, retorna nulo. Portanto, agora as propriedades são opcionais e dinâmicas.

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

Uso:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';

$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);
Mahmoud Zalt
fonte
-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: nenhum eval. sendo velho neste idioma.

r4ccoon
fonte
Este é um péssimo conselho, a função eval () é uma ferramenta muito perigosa e o deixará extremamente vulnerável a ataques de injeção. blog.highub.com/php/php-core/php-eval-is-evil deve fornecer algumas informações.
precisa saber é o seguinte
3
Exclua esta resposta e você terá um emblema!
Thermech