Criando objeto padrão a partir de valor vazio em PHP?
On Dezembro 1, 2020 by adminConsidere o seguinte código.
$car = (object)[ "general" => [ "interior" => [ "seats" => "destroyed" ] ] ]; $exteriorProperties = [ "hood" => "shiny", "windows" => "dirty" ]; foreach($exteriorProperties as $key => $prop){ $car->{"other"}->{"exterior"}->{$key} = $prop; }
Este é um cenário onde eu “d gostam de adicionar propriedades a um objeto, algumas camadas de profundidade por vez, enquanto iterando por meio de alguns outros dados. Se não existir, ele apenas irá criá-lo; se existir, ele será substituído. PERFEITO!
Infelizmente, isso gerará o aviso:
Criando objeto padrão a partir do valor vazio
Eu poderia resolver o problema verificando primeiro se a propriedade existe assim:
foreach($exteriorProperties as $key => $prop){ if(!isset($car->other)) $car->other = (object)[]; if(!isset($car->other->exterior)) $car->other->exterior = (object)[]; $car->other->exterior->{$key} = $prop; }
Este não é o meu ideal solução. Estou me perguntando se há uma solução mais elegante. Atualmente, estou usando:
@$car->{"other"}->{"exterior"}->{$key} = $prop;
para suprimir os avisos, mas estou preocupado com a compatibilidade no futuro.
Será que alguém tem uma solução mais elegante para este cenário?
Comentários
- Não ' não use matrizes como a resposta abaixo sugere, use o objeto corretamente. Arrays são bons apenas para código local, compartilhado fora de um arquivo ou classe significa que você está escrevendo chaves manualmente, tendo que se lembrar delas, perder uma ou duas, erro de digitação. Um bom IDE com preenchimento automático e objetos com getter / setter são um feliz mundo de desenvolvimento.
Resposta
Sim, use arrays.
$car = [ "general" => [ "interior" => [ "seats" => "destroyed" ] ] ]; $exteriorProperties = [ "hood" => "shiny", "windows" => "dirty" ]; foreach($exteriorProperties as $key => $prop){ $car["other"]["exterior"][$key] = $prop; } $car = (object) $car;
De qualquer forma, a conversão do objeto converterá apenas o array mais externo. Os arrays aninhados ainda são arrays.
\is_array($car->general); // true
Por que você precisa que eles sejam objetos sem forma? Definir classes para esses objetos ou tratá-los como matrizes é a resposta simples.
A propósito $car->{"other"}
é uma maneira realmente estranha de escrever $car->other
…
Comentários
- Suponho que você ' está certo, eu apenas odeio ficar preso a matrizes o tempo todo. O
$car->{'other'}
é porque a maioria das minhas chaves de propriedade vêm de variáveis de string. como$car->{$var1}->{$var2}
Resposta
Sim, você pode evitar as operações condicionais iteradas processando todos os dados como matrizes.
Código: ( Demo )
$car = json_decode( json_encode( array_replace_recursive( (array)$car, ["other" => ["exterior" => $exteriorProperties]] ) ) );
Ao converter apenas o nível superior do tipo de objeto para o tipo de matriz, você pode apenas lançá-lo com (array)
. Se você precisar converter todos os níveis – json codificar o objeto inteiro, então decodifique essa string para um array. Quando você terminar o processamento, use as funções json_
para reverter os dados para o tipo de objeto.
Ainda acho isso um pouco desajeitado (talvez tão desajeitado quanto o seu abordagem condicional). O benefício acima está na recursão; se a profundidade de seus dados mudar, você não precisará alterar o script de processamento. Pergunte a si mesmo se você realmente precisa usar um objeto. Se a codificação for simplificada com um tipo de dados diferente, talvez tenha de repensar / refactor.
Ps DEFINITIVAMENTE não escreve o operador stfu (@
) em seu código. Em quase todas as implementações, a técnica é evitável (este é um dos casos) e projetos com essa sintaxe são categorizados / presumidos como de baixa qualidade por desenvolvedores experientes.
Comentários
- Obrigado, boa avaliação. Infelizmente não pude escolher nada além de objetos, pois um programador anterior o codificou como tal.
Deixe uma resposta