¿Crear un objeto predeterminado a partir de un valor vacío en PHP?


362

Veo este error solo después de actualizar mi entorno PHP a PHP 5.4 y más allá. El error apunta a esta línea de código:

Error:

Crear objeto predeterminado a partir de valor vacío

Código:

$res->success = false;

¿Necesito primero declarar mi $resobjeto?


11
¿Cómo / dónde estás iniciando $res ?
Naveed

1
@NAVEED Allí .
7heo.tk

Respuestas:


627

Su nuevo entorno puede tener E_STRICTadvertencias habilitadaserror_reporting para versiones de PHP <= 5.3.x, o simplemente se ha error_reportingconfigurado al menos E_WARNINGcon versiones de PHP> = 5.4. Ese error se activa cuando $reses NULLo no inicializado:

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

PHP informará un mensaje de error diferente si $resya está inicializado a algún valor pero no es un objeto:

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

Para cumplir con los E_STRICTestándares anteriores a PHP 5.4, o el E_WARNINGnivel de error normal en PHP> = 5.4, suponiendo que está tratando de crear un objeto genérico y asignar la propiedad success, debe declarar $rescomo un objeto stdClassen el espacio de nombres global:

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

38
Usted shoud comprueba si el objeto ya existe: if (!isset($res)) $res = new stdClass();. De lo contrario, este código no es un reemplazo equivalente para la creación implícita de objetos "PHP antiguo".
TMS

66
@Tomas ¿Tenemos que hacer esto de nuevo? Los mods limpiaron el hilo de comentarios la última vez porque agregó poco valor. No hay creación de objeto implícito "PHP antiguo". Siempre fue un error y siempre emitió una advertencia, solo que se cambió de E_STRICT a E_WARNING en 5.4, por lo que algunas personas nunca lo encontraron sin haber prestado atención a E_STRICT.
Michael Berkowski el

44
¡@PeterAlfvin no se definió en esa ejecución en particular ! Pero en una ejecución diferente, exactamente en el mismo lugar en el código , ¡el objeto podría estar ya definido! Esto es un error al pensar que la gente suele hacer y esa es la razón por la que trato de enfatizar eso.
TMS

2
Michael, la creación implícita de objetos siempre estuvo y todavía está presente incluso en 5.4. Y, por cierto, en PHP <5.3 no era ni E_STRICT ni E_WARNING. Y, por cierto, los mods han restaurado el comentario y me dijeron que lo atenuara, por eso lo volví a publicar.
TMS

3
@tomas Oh, está bien, creo que entiendo lo que quieres decir. Parece extraño que usted / Michael no puedan llegar a un cierre sobre esto. Por cierto, este intercambio me ha llevado a darme cuenta de que la cursiva <negrita <todas las mayúsculas en términos de "fuerza" y que, mientras que todas las mayúsculas = gritos y cursivas = cursiva Énfasis, negrita está en un punto medio donde la aceptabilidad es cuestionable. :-)
Peter Alfvin

57

Este mensaje ha sido E_STRICTpara PHP <= 5.3. Desde PHP 5.4, desafortunadamente se cambió a E_WARNING. Como los E_WARNINGmensajes son útiles, no desea deshabilitarlos por completo.

Para deshacerse de esta advertencia, debe usar este código:

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

$res->success = false;

Este es un reemplazo totalmente equivalente . Asegura exactamente lo mismo que PHP está haciendo silenciosamente, desafortunadamente con advertencia ahora, la creación implícita de objetos. Siempre debe verificar si el objeto ya existe, a menos que esté absolutamente seguro de que no existe. El código proporcionado por Michael no es bueno en general, porque en algunos contextos el objeto a veces puede estar ya definido en el mismo lugar en el código, dependiendo de las circunstancias.


2
@carlosvini, esto te dará Undefined variable: res.
Pacerier

1
@Pacerier Tienes razón, lo mejor que puedes hacer es: $ res = isset ($ res)? $ res: new stdClass (); - esa fue la razón por la que no tenía E_NOTICE habilitado hace 6 meses, ya que es demasiado detallado.
carlosvini

13

Simplemente,

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

O podría crear instancias de clases con:

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

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

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

y rellena valores con:

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

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

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

Más información: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting


¿Por qué new stdClass () se considera un método "antiguo"? ¿Los demás son de alguna manera mejores?
Aaron

Es simplemente de la versión anterior de php
abre el

en mi caso $this->route->uri = new stdClass();no funciona para mí, todavía tengo la advertencia. Nota: $this->routees existente.
Meloman

¿Quizás esto no sea compatible con las nuevas versiones de php? ¿Qué versión usaste?
Pirs

6

Si coloca el carácter "@" al comienzo de la línea, PHP no muestra ninguna advertencia / aviso para esta línea. Por ejemplo:

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

Para evitar esta advertencia para esta línea, debe poner el carácter "@" al comienzo de la línea de esta manera:

@$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

Estoy usando este truco cuando estoy desarrollando. No me gusta deshabilitar todos los mensajes de advertencia porque si no maneja las advertencias correctamente, se convertirán en un gran error en el futuro.


1
@ previene advertencias al suprimirlo, se ve bien mientras tenga un código manejable. Pero si su código se convierte en algo más grande y se encuentra con un problema, de alguna manera lamentará usar esto. Te encontrarás buscando todas esas "@" para recibir una advertencia que quieras mostrar porque temporalmente ha cumplido su propósito pensando que realmente has solucionado el problema cuando en realidad te ha estado hablando y no lo harías. no escuches
Vincent Edward Gedaria Binua

Ya lo sabia. Esta es una respuesta corta y rápida. Hay mucha solución para esto.
kodmanyagha

2
¡increíble! Sin embargo, puedo rogar cortésmente que no esté de acuerdo, ocultar el error no es realmente solucionar el problema (como también comentó Ramy Nasr).
Vincent Edward Gedaria Binua

Esta solución es la única solución para mí en php 7.2.
Meloman

3

Pruebe esto si tiene una matriz y le agrega objetos.

$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.
}

Esto envía ARRAY de objetos para su uso posterior ~!


1
¡¡¡¡GRACIAS!!!! Esto es lo que ayudó a hacer el trabajo. Necesitaba decirle a PHP paso a paso qué era cada elemento. Gracias por recordarme que no codifique lazy lol.
Yanike

2

Prueba esto:

ini_set('error_reporting', E_STRICT);

1
Gracias. Esto se usa por completo cuando está utilizando bibliotecas de terceros como nusoap y no quiere / no puede cambiar la fuente. En ese caso, puede cambiar error_reporting al nivel E_STRICT justo antes de requerir otros archivos fuente.
mtoloo

Aunque acabo de agregar esto a la parte superior de nusoap para solucionar mi problema.
badweasel

11
¿Eh? El código aquí desactiva todos los informes de E_STRICTerrores, excepto los errores, incluida la supresión de mensajes por errores fatales. Esa no es una sugerencia razonable para resolver esta advertencia en particular, y lo que es más, es algo que nunca querrás hacer. Por qué 5 personas votaron por esto, no tengo idea.
Mark Amery

1
¡Esto es súper malo! use ini_set('error_reporting', -1);mientras se depura, pero no use lo anterior, como siempre.
Kzqai

Ok, ¿entonces arreglas un problema escondiendo este? No estoy seguro de que su código funcione como se esperaba ...
comienza el

1

Tuve un problema similar y esto parece resolver el problema. Solo necesita inicializar el objeto $ res en una clase. Supongamos aquí que el nombre de la clase es prueba.

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

1

Esta es una advertencia que enfrenté en PHP 7, la solución fácil a esto es inicializando la variable antes de usarla

$myObj=new \stdClass();

Una vez que lo hayas inicializado, puedes usarlo para objetos

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

0

Este problema se debe a que está asignando a una instancia de objeto que no se inició. Por ejemplo:

Tu caso:

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

Solución:

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

¿No estás suponiendo que existe la clase "Usuario"? que no puede y ahora generará un error diferente?
Christopher Thomas el

1
En realidad, no creé una instancia del objeto Usuario, así que recibí un error. Pero después de crear una instancia. Funcionó ... es un problema genérico con el concepto de OOP :)
Bastin Robin

66
bueno, en realidad el problema real es que su ejemplo asume que se define la clase de usuario, este no es un problema genérico de orientación a objetos, es un requisito clave;)
Christopher Thomas

1
Prefiero poner una genérica "stdClass" que reemplaza la premisa que implica "Usuario".
TechNyquist

0

Una forma simple de obtener este error es escribir (a) a continuación, lo que significa escribir (b)

(una) $this->my->variable

(si) $this->my_variable

Trivial, pero muy fácil de pasar por alto y difícil de detectar si no lo está buscando.


¿Cómo se relaciona esto con la pregunta original? No hubo confusión entre _y->
Nico Haase

0

Es posible que deba verificar si la variable se declaró y tiene el tipo correcto.

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;

Ver clases anónimas de PHP .


0

Tuve un problema similar al intentar agregar una variable a un objeto devuelto por una API. Estaba iterando a través de los datos con un bucle foreach.

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

Esto arrojó la excepción "Crear objeto predeterminado a partir de valor vacío" en Laravel.

Lo arreglé con un cambio muy pequeño.

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

Simplemente haciendo que $ data sea una referencia.

¡Espero que eso ayude a alguien y me haya molestado muchísimo!


0
  1. Primero piense que debe crear el objeto $ res = new \ stdClass ();

  2. luego asigne un objeto con clave y valor thay $ res-> success = false;


(No entiendo thay). Cuando desee un salto de línea después de algunos contenidos, agregue dos espacios en blanco a los contenidos visibles de la línea antes del descanso.
barba gris

-1

no, no lo hace ... lo creará cuando agregue el valor de éxito al objeto. La clase predeterminada se hereda si no especifica uno.


44
Aunque devolverá el mensaje de estándares estrictos ... es simplemente una buena práctica crear primero el objeto manualmente, y aunque PHP es relativamente tolerante con la práctica de codificación de mala calidad, no debe ignorar hacer las cosas correctamente.
Mark Baker

44
entendido, solo estaba respondiendo la pregunta con un simple sí o no, sin definir o defender las mejores prácticas :)
Silvertiger

-1

Intenta usar:

$user = (object) null;

2
En general, las respuestas son mucho más útiles si incluyen una explicación de lo que se pretende que haga el código y por qué eso resuelve el problema sin introducir otros.
lucascaro

-12

Puse lo siguiente en la parte superior del archivo PHP defectuoso y el error ya no se muestra:

error_reporting(E_ERROR | E_PARSE);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.