Створення об'єкта за замовчуванням з порожнього значення в PHP?


362

Я бачу цю помилку лише після оновлення мого середовища PHP до PHP 5.4 і вище. Помилка вказує на цей рядок коду:

Помилка:

Створення об'єкта за замовчуванням з порожнього значення

Код:

$res->success = false;

Чи потрібно спочатку оголосити свій $resоб’єкт?


11
Як / де ви ініціюєте $res ?
Naveed

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
@Tomas Чи потрібно це робити ще раз? Модники очистили нитку коментарів востаннє, оскільки це мало значення. Немає створення неявного об’єкта "старого PHP". Це завжди була помилка і завжди видавали попередження, лише що вона була змінена з E_STRICT на E_WARNING в 5.4, тому деякі люди ніколи не стикалися з нею, не звертаючи уваги на E_STRICT.
Michael Berkowski

4
@PeterAlfvin не було визначено в одному конкретному виконанні ! Але при різному виконанні, в точно такому ж місці в коді , об'єкт може бути вже визначений! Це помилка в думці, яку люди часто роблять, і саме тому я намагаюся наголосити на цьому.
TMS

2
Майкл, неявне створення об'єкта завжди було і існує навіть у 5.4. І BTW в PHP <5.3 це не було ні E_STRICT, ні E_WARNING. І BTW, модники відновили коментар, і мені сказали, щоб його звучали, тому я його повторно розмістив.
TMS

3
@tomas О, добре, я думаю, я розумію, що ти маєш на увазі. Здається дивним, що ви / Майкл не можете з цим закритись. До речі, цей обмін змусив мене зрозуміти, що курсив <жирний <allcaps з точки зору "сили" і що, хоча allcaps = крик і курсив = ввічливий наголос, жирний перебуває в середині, де прийнятність сумнівна. :-)
Пітер Альфвін

57

Це повідомлення призначене E_STRICTдля PHP <= 5.3. Починаючи з PHP 5.4, він невдало змінився на E_WARNING. Оскільки E_WARNINGповідомлення корисні, ви не хочете їх повністю відключати.

Щоб позбутися цього попередження, потрібно скористатися цим кодом:

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

$res->success = false;

Це повністю еквівалентна заміна . Це запевняє саме те, що PHP мовчки робить - на жаль, з попередженням зараз - неявне створення об’єктів. Ви завжди повинні перевіряти, чи об'єкт вже існує, якщо ви абсолютно не впевнені, що його немає. Код, наданий Майклом, загалом не є корисним, оскільки в деяких контекстах об'єкт іноді може бути визначений на тому самому місці в коді залежно від обставин.


2
@carlosvini, Це дасть тобі Undefined variable: res.
Pacerier

1
@Pacerier Ви маєте рацію, найкраще, що ви можете зробити: $ res = isset ($ res)? $ res: новий stdClass (); - з-за чого я не включив E_NOTICE 6 місяців тому, оскільки це занадто проклятий багатослівний.
carlosvini

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
1717

у моєму випадку $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

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


1
@ запобігає попередженням, придушуючи його, виглядає нормально, поки у вас є керований код. Але якщо ваш код перетвориться на щось більше, і ви зіткнулися з проблемою, ви якось пошкодуєте про це. Ви виявите, що шукаєте всіх "@" за попередженням, яке хочете сховати, оскільки тимчасово воно виконало свою мету, думаючи, що ви фактично виправили цю проблему, коли насправді вона розмовляла з вами, і ви просто не хочете " не слухати.
Вінсент Едвард Гедарія Бінуа

Я вже знаю. Це коротка і швидка відповідь. Для цього існує багато рішень.
kodmanyagha

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 з об’єктів для подальшого використання ~!


ДЯКУЮ ТОБІ!!!! Саме це допомогло виконати роботу. Мені потрібно було покроково розповісти PHP, що таке кожен елемент. Дякуємо, що нагадали мені не кодувати ледачий лол.
yanike

2

Спробуйте це:

ini_set('error_reporting', E_STRICT);

1
Дякую. це повноцінне використання під час використання сторонніх бібліотек, таких як nusoap і не хочуть / не можуть змінити джерело. У такому випадку ви можете змінити повідомлення про помилку на рівень E_STRICT безпосередньо перед тим, як вимагати інших вихідних файлів.
mtoloo

Хоча я щойно додав це до вершини нусоапу, щоб виправити свою проблему.
badweasel

11
Так? Код тут вимикає всі повідомлення про E_STRICTпомилки, крім помилок, включаючи придушення повідомлень про фатальні помилки. Це не розумна пропозиція вирішити це особливе попередження, і більше того, що ви майже ніколи не хочете робити. Чому 5 людей висловилися за це, я не маю поняття.
Марк Амері

1
Це супер погано! використовувати ini_set('error_reporting', -1);під час налагодження, але не використовувати вищезазначене, як ніколи.
Kzqai

Гаразд, ви вирішите проблему, сховавши цю? Не впевнений, що ваш код буде працювати так, як очікувалося ...
пр.

1

У мене була подібна проблема, і це, здається, вирішує проблему. Вам просто потрібно ініціалізувати об’єкт $ res до класу. Припустимо, тут назва класу - тест.

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, тому я отримав помилку. Але після створення екземпляра. Це спрацювало .. його загальна проблема з концепцією OOPs :)
Бастін Робін

6
ну, насправді справжня проблема полягає в тому, що ваш приклад передбачає, що визначений клас користувача, це не загальна проблема орієнтації на об'єкт, його ключова вимога;)
Крістофер Томас

1
Я б швидше поставив загальний "stdClass", замінивши приміщення, що означає "Користувач".
TechNyquist

0

Простий спосіб отримати цю помилку - ввести (a) нижче, тобто набрати (b)

(а) $this->my->variable

(b) $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;
}

Просто зробивши $ дані посиланням.

Я сподіваюся, що хтось допомагає, це дратувало пекло від мене!


0
  1. Спочатку подумайте, що вам слід створити об’єкт $ res = new \ stdClass ();

  2. потім призначте об'єкт з ключем і значенням, ніж $ res-> success = false;


(Я не розумію thay.) Якщо потрібно розрив рядка після деякого вмісту, додайте два порожні пробіли до видимого вмісту рядка перед початком прориву.
сіра борода

-1

ні, ви цього не робите .. він створить його, коли ви додасте до об'єкта значення успіху. Клас за замовчуванням успадковується, якщо його не вказати.


4
Хоча воно поверне повідомлення суворих стандартів ... це просто хороша практика спочатку створити об’єкт вручну, і хоча PHP відносно толерантний до нерівномірної практики кодування, вам не слід ігнорувати, що робити речі правильно.
Марк Бейкер

4
зрозумів, я просто відповідав на питання простим "так" чи "ні", не визначаючи чи захищаючи найкращі практики :)
Silvertiger

-1

Спробуйте використовувати:

$user = (object) null;

2
Як правило, відповіді набагато корисніші, якщо вони включають пояснення того, що призначений для виконання коду та чому це вирішує проблему, не вводячи інших.
лукаскаро

-12

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

error_reporting(E_ERROR | E_PARSE);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.