Создание объекта по умолчанию из пустого значения в PHP?

362

Я вижу эту ошибку только после обновления моей среды PHP до PHP 5.4 и выше. Ошибка указывает на эту строку кода:

Ошибка:

Создание объекта по умолчанию из пустого значения

Код:

$res->success = false;

Должен ли я сначала объявить свой $resобъект?

Павел
источник
11
Как / Где вы начинаете $res ?
Навид
1
@ NAVEED Там .
7heo.tk

Ответы:

627

В вашей новой среде могут быть включеныE_STRICT предупреждения для версий PHP <= 5.3.x или просто установлено значение по крайней мере для версий PHP> = 5.4. Эта ошибка срабатывает , когда есть или еще не инициализированы:error_reportingerror_reportingE_WARNING$resNULL

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

PHP сообщит другое сообщение об ошибке, если $resоно уже инициализировано каким-либо значением, но не является объектом:

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

Чтобы соответствовать E_STRICTстандартам до PHP 5.4 или нормальному E_WARNINGуровню ошибок в PHP> = 5.4, при условии, что вы пытаетесь создать универсальный объект и назначить свойство success, вы должны объявить его $resкак объект stdClassв глобальном пространстве имен:

$res = new \stdClass();
$res->success = false;
Майкл Берковски
источник
38
Вы Шоуда проверить , существует ли уже объект: if (!isset($res)) $res = new stdClass();. В противном случае этот код не является эквивалентной заменой неявного создания объекта «старый PHP».
TMS
6
@ Томас Нам нужно сделать это снова? В прошлый раз моды очистили ветку комментариев, потому что это добавило мало пользы. Не существует "неявного" PHP неявного создания объекта. Это всегда было ошибкой и всегда выдавало предупреждение, просто оно было изменено с E_STRICT на E_WARNING в 5.4, поэтому некоторые люди никогда не сталкивались с этим, не обращая внимания на E_STRICT.
Майкл Берковски
4
@PeterAlfvin это не было определено в этом конкретном прогоне ! Но в другом случае, в одном и том же месте кода , объект может быть уже определен! Это ошибка в мысли, что люди часто делают, и именно поэтому я пытаюсь это подчеркнуть.
TMS
2
Майкл, создание неявного объекта всегда было и есть даже в 5.4. И кстати, в PHP <5.3 это не было ни E_STRICT, ни E_WARNING. И кстати, моды восстановили комментарий, и мне сказали, чтобы смягчить его, поэтому я опубликовал его.
TMS
3
@ Томас О, хорошо, я думаю, я понимаю, что вы имеете в виду. Кажется странным, что вы / Майкл не можете завершить это. Кстати, этот обмен привел меня к пониманию того, что курсив <bold <allcaps в терминах «сила» и что хотя allcaps = кричать и курсив = politeEmphasis, жирный шрифт находится на среднем уровне, где приемлемость сомнительна. :-)
Питер Альфвин
57

Это сообщение было E_STRICTдля PHP <= 5.3. Начиная с PHP 5.4, он был неудачно изменен на E_WARNING. Поскольку E_WARNINGсообщения полезны, вы не хотите полностью их отключать.

Чтобы избавиться от этого предупреждения, вы должны использовать этот код:

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

$res->success = false;

Это полностью эквивалентная замена . Это гарантирует то же самое, что PHP делает тихо - к сожалению, теперь с предупреждением - неявное создание объекта. Вы должны всегда проверять, существует ли объект уже, если вы не уверены, что это не так. Код, предоставленный Майклом, в целом не годится, потому что в некоторых контекстах объект может иногда уже определяться в одном и том же месте кода, в зависимости от обстоятельств.

TMS
источник
2
@carlosvini, это даст тебе Undefined variable: res.
Pacerier
1
@Pacerier Вы правы, лучшее, что вы можете сделать, это: $ res = isset ($ res)? $ res: new stdClass (); - по этой причине 6 месяцев назад я не включил E_NOTICE, так как он слишком чертовски многословен.
Карлосвини
13

Просто,

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

Или вы можете создавать экземпляры классов с помощью:

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

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

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

и заполните значения:

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

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

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

Дополнительная информация: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting

пиров
источник
почему новый stdClass () считается "старым" методом? Остальные как-то лучше?
Аарон
Его просто от старой версии PHP
пиры
в моем случае $this->route->uri = new stdClass();не работает для меня, у меня все еще есть предупреждение. Примечание: $this->routeсуществует.
Меломан
Может быть, это не совместимо с новыми версиями php? Какую версию вы использовали?
пирс
6

Если вы вставите символ «@» в начале строки, тогда PHP не показывает никаких предупреждений / уведомлений для этой строки. Например:

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

Для предотвращения этого предупреждения для этой строки вы должны поставить символ «@» в начале строки следующим образом:

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

Я использую этот трюк при разработке. Мне не нравится отключать все предупреждающие сообщения, потому что, если вы не обработаете предупреждения правильно, в будущем они станут большой ошибкой.

kodmanyagha
источник
1
@ предотвращает предупреждения, подавляя их, выглядит нормально, пока у вас есть управляемый код. Но если ваш код вырастет во что-то большее, и вы столкнулись с проблемой, вы почему-то пожалеете об этом. Вы обнаружите, что ищите все эти «@» для предупреждения, которое вы хотели бы показать, потому что временно оно выполнило свою задачу, думая, что вы на самом деле решили проблему, когда на самом деле он говорил с вами, и вы просто не захотели слушать
Винсент Эдвард Гедария Бинуа
Я уже знаю. Это короткий и быстрый ответ. Есть много решений для этого.
Кодманяга
2
классно! Могу ли я вежливо попросить не согласиться, хотя сокрытие ошибки на самом деле не решает проблему (как прокомментировал и Рами Наср).
Винсент Эдвард Гедария Бинуа
Этот обходной путь - единственная работа для меня на php 7.2.
Меломан
3

Попробуйте это, если у вас есть массив и добавить к нему объекты.

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

Это посылает ARRAY из объектов для дальнейшего использования ~!

Даниэль Аденью
источник
1
БЛАГОДАРЮ ВАС!!!! Это то, что помогло сделать работу. Мне нужно было шаг за шагом рассказать PHP, что представляет собой каждый элемент. Спасибо, что напомнили мне не кодировать ленивый LOL.
Янике
2

Попробуй это:

ini_set('error_reporting', E_STRICT);
Ирфан
источник
1
Спасибо. это полное использование, когда вы используете сторонние библиотеки, такие как nusoap, и не хотите / не можете изменить источник. В этом случае вы можете изменить error_reporting на уровень E_STRICT непосредственно перед тем, как требовать другие исходные файлы.
mtoloo
Хотя я только что добавил это в начало nusoap, чтобы исправить мою проблему.
Badweasel
11
А? Код здесь отключает все отчеты об E_STRICTошибках, кроме ошибок, включая подавление сообщений о фатальных ошибках. Это не разумное предложение, чтобы решить это конкретное предупреждение, и, более того, это то, что вы почти никогда не хотите делать. Почему 5 человек проголосовали за это, я понятия не имею.
Марк Амери
1
Это супер плохо! используйте ini_set('error_reporting', -1);при отладке, но не используйте вышеизложенное, как никогда.
Kzqai
Итак, вы решаете проблему, скрывая эту? Не уверен, что ваш код будет работать должным образом ...
pirs
1

У меня была похожая проблема, и это, кажется, решило проблему. Вам просто нужно инициализировать объект $ res для класса. Предположим, что здесь имя класса - test.

class test
{
   //You can keep the class empty or declare your success variable here
}
$res = new test();
$res->success = false;
Кевин Стивен Бисвас
источник
1

Это предупреждение, с которым я столкнулся в PHP 7, это легко исправить путем инициализации переменной перед ее использованием.

$myObj=new \stdClass();

Как только вы инициализировали его, вы можете использовать его для объектов

 $myObj->mesg ="Welcome back - ".$c_user;
Аян Бхаттачарджи
источник
0

Эта проблема вызвана тем, что вы присваиваете экземпляр объекта, который не инициирован. Например:

Ваш случай:

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

Решение:

$user = new User;
$user->email = 'exy@gmail.com';
Бастин Робин
источник
Вы не предполагаете, что класс "Пользователь" существует? что это может не так, и теперь он будет генерировать другую ошибку?
Кристофер Томас
1
На самом деле я не создал экземпляр объекта User, поэтому я получил ошибку. Но после создания экземпляра. Это сработало .. это общая проблема с концепцией ООП :)
Бастин Робин
6
ну, на самом деле настоящая проблема в том, что ваш пример предполагает, что пользовательский класс должен быть определен, это не общая проблема ориентации объекта, это ключевое требование;)
Кристофер Томас,
1
Я бы предпочел поставить универсальный «stdClass», заменяя предпосылку, подразумевающую «пользователя».
TechNyquist
0

Простой способ получить эту ошибку - напечатать (a) ниже, то есть напечатать (b)

(А) $this->my->variable

(Б) $this->my_variable

Тривиально, но очень легко упустить из виду и трудно заметить, если вы не ищете его.

танин
источник
Как это связано с первоначальным вопросом? Не было путаницы между _и->
Нико Хаас
0

Возможно, вам придется проверить, если переменная объявлена ​​и имеет правильный тип.

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;

Смотрите PHP анонимные классы .

Антон Пелых
источник
0

У меня была похожая проблема при попытке добавить переменную к объекту, возвращенному из API. Я перебирал данные с помощью цикла foreach.

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

Это бросило исключение «Создание объекта по умолчанию из пустого значения» в Laravel.

Я исправил это с очень маленьким изменением.

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

Просто сделав $ data ссылкой.

Я надеюсь, что это поможет кому-то, это чертовски раздражает меня!

Энди
источник
0
  1. Сначала подумайте, что вы должны создать объект $ res = new \ stdClass ();

  2. затем назначьте объект с ключом и значением thay $ res-> success = false;

Сукрон Мамун
источник
(Я не понимаю thay.) Если вы хотите разрыв строки после некоторого содержимого, добавьте два пробела к видимому содержимому строки перед переходом в будущее.
седобородый
-1

нет, вы не .. он создаст его, когда вы добавите в объект значение успеха. класс по умолчанию наследуется, если вы его не указали.

Silvertiger
источник
4
Хотя он вернет сообщение о строгих стандартах ... сначала рекомендуется создать объект вручную, и хотя PHP относительно терпимо относится к неаккуратной практике кодирования, вы не должны игнорировать правильные действия.
Марк Бейкер
4
понял, я просто отвечал на вопрос простым да или нет, не определяя и не защищая лучшие практики :)
Silvertiger
-1

Попробуйте использовать:

$user = (object) null;
Фишер Тирадо
источник
2
Как правило, ответы гораздо полезнее, если они включают в себя объяснение того, для чего предназначен код, и почему это решает проблему, не представляя других.
Лукаскаро
-12

Я поместил следующее в верхней части ошибочного файла PHP, и ошибка больше не отображалась:

error_reporting(E_ERROR | E_PARSE);
Doug
источник