Criando objeto padrão a partir do valor vazio no PHP?


362

Eu vejo esse erro somente após atualizar meu ambiente PHP para o PHP 5.4 e além. O erro aponta para esta linha de código:

Erro:

Criando Objeto Padrão a partir do Valor Vazio

Código:

$res->success = false;

Preciso primeiro declarar meu $resobjeto?


11
Como / onde você está iniciando $res ?
Naveed

11
@NAVEED There .
7heo.tk

Respostas:


627

Seu novo ambiente pode ter E_STRICTavisos ativadoserror_reporting para versões do PHP <= 5.3.x, ou simplesmente ter error_reportingdefinido pelo menos E_WARNINGcom versões do PHP> = 5.4. Esse erro é acionado quando $resé NULLou ainda não foi inicializado:

$res = NULL;
$res->success = false; // Warning: Creating default object from empty value

O PHP reportará uma mensagem de erro diferente se $resjá estiver inicializado com algum valor, mas não for um objeto:

$res = 33;
$res->success = false; // Warning: Attempt to assign property of non-object

Para cumprir os E_STRICTpadrões anteriores ao PHP 5.4, ou o E_WARNINGnível de erro normal no PHP> = 5.4, supondo que você esteja tentando criar um objeto genérico e atribuir a propriedade success, você precisa declarar $rescomo um objeto stdClassno espaço para nome global:

$res = new \stdClass();
$res->success = false;

38
Que deviam verificar se o objeto já existe: if (!isset($res)) $res = new stdClass();. Caso contrário, esse código não será um substituto equivalente para a criação implícita de objetos "PHP antigo".
TMS

6
@ Tomas Precisamos fazer isso de novo? Os mods limparam o tópico de comentários da última vez porque agregaram pouco valor. Não há criação de objeto implícito "PHP antigo". Sempre foi um erro e sempre emitia um aviso, apenas que foi alterado de E_STRICT para E_WARNING na 5.4, para que algumas pessoas nunca o encontrassem sem prestar atenção no E_STRICT.
22813 Michael Berkowski

4
@ PeterAlfvin não foi definido nessa execução em particular ! Mas em uma execução diferente, exatamente no mesmo local do código , o objeto já pode estar definido! É um erro pensar que as pessoas cometem com frequência e é por isso que tento enfatizar isso.
TMS

2
Michael, a criação implícita de objetos sempre esteve e ainda está presente, mesmo na versão 5.4. E BTW No PHP <5.3, não era E_STRICT nem E_WARNING. E, BTW, os mods restauraram o comentário e me disseram para diminuí-lo, é por isso que o re-publiquei.
TMS

3
@tomas Oh, ok, acho que entendi o que você quer dizer. Parece estranho que você / Michael não consiga concluir isso. Aliás, essa troca me levou a perceber que itálico <bold <allcaps em termos de "força" e que, enquanto allcaps = shouting e itálico = politeEmphasis, bold está em um meio termo em que a aceitabilidade é questionável. :-)
Peter Alfvin

57

Esta mensagem foi E_STRICTpara PHP <= 5.3. Desde o PHP 5.4, ele foi alterado para E_WARNING. Como as E_WARNINGmensagens são úteis, você não deseja desativá-las completamente.

Para se livrar desse aviso, você deve usar este código:

if (!isset($res)) 
    $res = new stdClass();

$res->success = false;

Esta é uma substituição totalmente equivalente . Ele garante exatamente a mesma coisa que o PHP está fazendo silenciosamente - infelizmente com aviso agora - criação implícita de objetos. Você sempre deve verificar se o objeto já existe, a menos que tenha certeza absoluta de que não existe. O código fornecido por Michael não é bom em geral, porque em alguns contextos o objeto já pode estar definido no mesmo local do código, dependendo das circunstâncias.


2
@ carlosvini, isso vai te dar Undefined variable: res.
Pacerier 26/01

11
@ Pacerier Você está certo, o melhor que pode fazer é: $ res = isset ($ res)? $ res: novo stdClass (); - que foi o motivo pelo qual o E_NOTICE não foi ativado há 6 meses, pois é muito detalhado.
precisa saber é o seguinte

13

Simplesmente,

    $res = (object)array("success"=>false); // $res->success = bool(false);

Ou você pode instanciar classes com:

    $res = (object)array(); // object(stdClass) -> recommended

    $res = (object)[];      // object(stdClass) -> works too

    $res = new \stdClass(); // object(stdClass) -> old method

e preencha os valores com:

    $res->success = !!0;     // bool(false)

    $res->success = false;   // bool(false)

    $res->success = (bool)0; // bool(false)

Mais informações: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting


por que o novo stdClass () é considerado um método "antigo"? Os outros são de alguma forma melhores?
Aaron

É simplesmente a partir da versão antiga do php
pirs

no meu caso $this->route->uri = new stdClass();não está funcionando para mim, ainda tenho o aviso. Nota: $this->routeexiste.
Meloman 03/01

Talvez isso não seja compatível com novas versões do php? Qual versão você usou?
pirs 12/01

6

Se você colocar o caractere "@" no início da linha, o PHP não mostrará nenhum aviso / aviso para esta linha. Por exemplo:

$unknownVar[$someStringVariable]->totalcall = 10; // shows a warning message that contains: Creating default object from empty value

Para evitar esse aviso para esta linha, você deve colocar o caractere "@" da linha como esta:

@$unknownVar[$someStringVariable]->totalcall += 10; // no problem. created a stdClass object that name is $unknownVar[$someStringVariable] and created a properti that name is totalcall, and it's default value is 0.
$unknownVar[$someStringVariable]->totalcall += 10; // you don't need to @ character anymore.
echo $unknownVar[$someStringVariable]->totalcall; // 20

Estou usando esse truque ao desenvolver. Não gosto de desativar todas as mensagens de aviso porque se você não manipular os avisos corretamente, eles se tornarão um grande erro no futuro.


11
@ evita avisos suprimindo-o; fica bem enquanto você tiver um código gerenciável. Mas se o seu código crescer em algo maior e você tiver um problema, você se arrependerá de alguma forma. Você se encontrará procurando por todos esses "@" em busca de um aviso que gostaria de exibir porque temporariamente ele serviu a seu objetivo, pensando que você realmente corrigiu o problema quando, na realidade, ele estava falando com você e você simplesmente não queria ' não ouça.
Vincent Edward Gedaria Binua

Eu já sei. Esta é uma resposta curta e rápida. Existem muitas soluções para isso.
Kodmanyagha

2
impressionante! Posso educadamente implorar em discordar, porém, esconder o erro não está realmente resolvendo o problema (como também comentou Ramy Nasr).
Vincent Edward Gedaria Binua

Esta solução alternativa é a única solução para mim no php 7.2.
Meloman 03/01

3

Tente isso se você tiver uma matriz e adicione objetos a ela.

$product_details = array();

foreach ($products_in_store as $key => $objects) {
  $product_details[$key] = new stdClass(); //the magic
  $product_details[$key]->product_id = $objects->id; 
   //see new object member created on the fly without warning.
}

Isso envia ARRAY de objetos para uso posterior ~!


11
OBRIGADO!!!! Foi isso que ajudou a fazer o trabalho. Eu precisava dizer ao PHP passo a passo o que cada elemento era. Obrigado por me lembrar de não codificar lol preguiçoso.
yanike 11/06

2

Tente o seguinte:

ini_set('error_reporting', E_STRICT);

11
Obrigado. isso é usado quando você usa bibliotecas de terceiros, como nusoap, e não deseja / não pode alterar a fonte. Nesse caso, você pode alterar o error_reporting para o nível E_STRICT antes de exigir outros arquivos de origem.
mtoloo

Embora eu apenas tenha adicionado isso ao topo do nusoap para corrigir meu problema.
badweasel

11
Hã? O código aqui desativa todos os relatórios de E_STRICTerros, exceto erros, incluindo a supressão de mensagens para erros fatais. Essa não é uma sugestão razoável para resolver esse aviso específico, e o que é mais é algo que você quase nunca deseja fazer. Por que 5 pessoas votaram nisso, não faço ideia.
Mark Amery

11
Isso é super ruim! use ini_set('error_reporting', -1);durante a depuração, mas não use o acima, como sempre.
Kzqai

Ok, então você resolve um problema ocultando este? Não tenho certeza o seu código irá funcionar como esperado ...
pirs

1

Eu tive um problema semelhante e isso parece resolver o problema. Você só precisa inicializar o objeto $ res para uma classe. Suponha que aqui o nome da classe seja test.

class test
{
   //You can keep the class empty or declare your success variable here
}
$res = new test();
$res->success = false;

1

Este é um aviso que eu enfrentei no PHP 7, a solução mais fácil é inicializar a variável antes de usá-la

$myObj=new \stdClass();

Depois de inicializado, você poderá usá-lo para objetos

 $myObj->mesg ="Welcome back - ".$c_user;

0

Esse problema é causado porque você está atribuindo a uma instância de objeto que não foi iniciada. Por exemplo:

Seu caso:

$user->email = 'exy@gmail.com';

Solução:

$user = new User;
$user->email = 'exy@gmail.com';

você não está assumindo que a classe "Usuário" existe? o que pode não acontecer e agora gerará um erro diferente?
Christopher Thomas

11
Na verdade, eu não criei uma instância do objeto Usuário, então recebi um erro. Mas depois de criar uma instância. Funcionou .. é um problema genérico com OOPs conceito :)
Bastin Robin

6
Bem, na verdade o verdadeiro problema é que o seu exemplo assume a classe de usuário a ser definido, este não é um problema genérico de orientação a objetos, é um requisito fundamental;)
Christopher Thomas

11
Eu prefiro colocar um "stdClass" genérico substituindo a premissa que implica "Usuário".
TechNyquist

0

Uma maneira simples de obter esse erro é digitar (a) abaixo, ou seja, digitar (b)

(uma) $this->my->variable

b) $this->my_variable

Trivial, mas muito facilmente esquecido e difícil de detectar, se você não está procurando.


Como isso está relacionado à pergunta original? Não houve confusão entre _e->
Nico Haase

0

Pode ser necessário verificar se a variável foi declarada e tem o tipo correto.

if (!isset($res) || !is_object($res)) {
    $res = new \stdClass();
    // With php7 you also can create an object in several ways.
    // Object that implements some interface.
    $res = new class implements MyInterface {};
    // Object that extends some object.
    $res = new class extends MyClass {};
} 

$res->success = true;

Veja classes anônimas do PHP .


0

Eu tive um problema semelhante ao tentar adicionar uma variável a um objeto retornado de uma API. Eu estava percorrendo os dados com um loop foreach.

foreach ( $results as $data ) {
    $data->direction = 0;
}

Isso gerou a exceção "Criando objeto padrão a partir do valor vazio" no Laravel.

Corrigi-o com uma alteração muito pequena.

foreach ( $results as &$data ) {
    $data->direction = 0;
}

Simplesmente fazendo $ data uma referência.

Espero que isso ajude alguém e isso me chateou demais!


0
  1. Primeiro pense que você deve criar o objeto $ res = new \ stdClass ();

  2. em seguida, atribua um objeto com a chave e o valor thay $ res-> success = false;


(Eu não entendo thay.) Onde você quiser uma quebra de linha após algum conteúdo, acrescente dois espaços em branco ao conteúdo visível da linha antes da quebra futura.
greybeard 28/04

-1

não, você não o fará .. ele será criado quando você adicionar o valor de sucesso ao objeto. a classe padrão será herdada se você não especificar um.


4
Embora retorne a mensagem Strict standards ... é simplesmente uma boa prática criar o objeto manualmente primeiro e, embora o PHP seja relativamente tolerante à prática de codificação de má qualidade, você não deve ignorar as coisas corretamente.
Mark Baker

4
entendida, eu estava apenas respondendo à pergunta com um simples sim ou não, não definir ou defender melhores práticas :)
Silvertiger

-1

Tente usar:

$user = (object) null;

2
Geralmente, as respostas são muito mais úteis se incluem uma explicação sobre o que o código pretende fazer e por que isso resolve o problema sem a introdução de outros.
Lucascaro

-12

Coloquei o seguinte na parte superior do arquivo PHP com falha e o erro não era mais exibido:

error_reporting(E_ERROR | E_PARSE);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.