การสร้างวัตถุเริ่มต้นจากค่าว่างใน PHP?


362

ฉันเห็นข้อผิดพลาดนี้หลังจากอัปเกรดสภาพแวดล้อม PHP เป็น PHP 5.4 ขึ้นไป ข้อผิดพลาดชี้ไปที่รหัสบรรทัดนี้:

ข้อผิดพลาด:

การสร้างวัตถุเริ่มต้นจากค่าว่าง

รหัส:

$res->success = false;

ฉันต้องประกาศ$resวัตถุของฉันก่อน?


11
คุณกำลังเริ่มต้น$res อย่างไร
Naveed

1
@NAVEED มี
7heo.tk

คำตอบ:


627

สภาพแวดล้อมใหม่ของคุณอาจมีE_STRICTคำเตือนเปิดใช้งานในerror_reportingเวอร์ชัน PHP <= 5.3.x หรือerror_reportingตั้งอย่างน้อยE_WARNINGด้วยเวอร์ชัน PHP> = 5.4 ข้อผิดพลาดนั้นจะเริ่มทำงานเมื่อ$resมีการNULLเริ่มต้นหรือยัง:

$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
คุณ shoud 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
Michael การสร้างวัตถุโดยนัยมักจะเป็นและยังคงปรากฏอยู่ใน 5.4 และ BTW ใน PHP <5.3 มันไม่ใช่ทั้ง E_STRICT และ E_WARNING และ BTW, mods ได้เรียกคืนความคิดเห็นและฉันถูกบอกให้ลดระดับเสียงนั่นคือเหตุผลที่ฉันโพสต์มันอีกครั้ง
TMS

3
@ โทมัสโอเคฉันคิดว่าฉันเข้าใจในสิ่งที่คุณหมายถึง ดูเหมือนว่าคุณ / ไมเคิลจะไม่สามารถปิดเรื่องนี้ได้ BTW การแลกเปลี่ยนนี้ทำให้ฉันตระหนักว่าตัวเอียง <ตัวหนา <allcaps ในแง่ของ "ความแข็งแกร่ง" และในขณะที่ allcaps = ตะโกนและตัวเอียง = politeEmphasis ตัวหนาอยู่ในพื้นที่ตรงกลางที่การยอมรับเป็นที่น่าสงสัย :-)
Peter Alfvin

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 เดือนที่ผ่านมาเนื่องจากเป็น verbose ที่น่ารังเกียจเกินไป
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/th/language.types.object.php#language.types.object.casting


เหตุใด stdClass ใหม่ () จึงถือเป็นวิธี "เก่า" คนอื่นจะดีกว่าอย่างใด?
Aaron

มันเรียบง่ายจาก php version เก่า
pirs

ในกรณีของฉัน$this->route->uri = new stdClass();ไม่ทำงานสำหรับฉันฉันยังคงมีคำเตือน หมายเหตุ: $this->routeมีอยู่แล้ว
Meloman

บางทีนี่อาจเข้ากันไม่ได้กับ php เวอร์ชั่นใหม่? คุณใช้เวอร์ชั่นไหน
pirs

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
@ ป้องกันการเตือนโดยการยับยั้งมันดูดีตราบใดที่คุณมีรหัสที่สามารถจัดการได้ แต่ถ้ารหัสของคุณโตขึ้นเป็นสิ่งที่ใหญ่กว่าและคุณประสบปัญหาคุณจะต้องเสียใจกับการใช้สิ่งนี้ คุณจะพบว่าตัวเองกำลังมองหาคำเตือน "@" ทั้งหมดที่คุณต้องการยกเลิกการซ่อนเนื่องจากเป็นการทำหน้าที่ชั่วคราวโดยคิดว่าคุณได้แก้ไขปัญหาจริง ๆ แล้วในความเป็นจริงมันได้พูดคุยกับคุณและคุณไม่ต้องการ ' ไม่ฟัง
Vincent Edward Gedaria Binua

ฉันรู้แล้ว นี่เป็นคำตอบที่สั้นและรวดเร็ว มีวิธีแก้ไขปัญหานี้มากมาย
kodmanyagha

2
! น่ากลัว ฉันขออย่างสุภาพที่จะไม่เห็นด้วยแม้ว่าการซ่อนข้อผิดพลาดนั้นไม่ได้แก้ไขปัญหา (เช่นเดียวกับที่ Ramy Nasr แสดงความคิดเห็นด้วย)
Vincent Edward Gedaria Binua

วิธีแก้ปัญหานี้เป็นเพียง workin สำหรับฉันใน php 7.2
Meloman

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 of Objectsเพื่อใช้ในภายหลัง ~!


ขอบคุณ!!!! นี่คือสิ่งที่ช่วยให้งานสำเร็จลุล่วง ฉันต้องการบอก PHP ทีละขั้นตอนว่าแต่ละองค์ประกอบคืออะไร ขอบคุณที่เตือนฉันไม่ให้รหัสขี้เกียจฮ่า ๆ
yanike

2

ลองสิ่งนี้:

ini_set('error_reporting', E_STRICT);

1
ขอบคุณ สิ่งนี้ถูกใช้อย่างเต็มรูปแบบเมื่อคุณใช้ไลบรารีบุคคลที่สามเช่น nusoap และไม่ต้องการ / ไม่สามารถเปลี่ยนแหล่งที่มา ในกรณีนี้คุณสามารถเปลี่ยน error_reporting เป็นE_STRICTระดับก่อนที่จะต้องการไฟล์ต้นฉบับอื่น ๆ
mtoloo

แม้ว่าฉันเพิ่งเพิ่มสิ่งนี้ไปที่ด้านบนสุดของ nusoap เพื่อแก้ไขปัญหาของฉัน
badweasel

11
ฮะ? รหัสที่นี่ปิดการใช้งานการรายงานข้อผิดพลาดทั้งหมดยกเว้นE_STRICTข้อผิดพลาดรวมถึงการระงับข้อความสำหรับข้อผิดพลาดร้ายแรง นั่นไม่ใช่ข้อเสนอแนะที่สมเหตุสมผลในการแก้ไขคำเตือนนี้โดยเฉพาะและสิ่งที่มากกว่านั้นคือสิ่งที่คุณไม่อยากทำ ทำไม 5 คนโหวตขึ้นสิ่งนี้ฉันไม่มีเงื่อนงำ
Mark Amery

1
มันแย่มาก! ใช้ini_set('error_reporting', -1);ในขณะที่การดีบัก แต่ไม่ได้ใช้ข้างต้นเช่นเคย
Kzqai

ตกลงดังนั้นคุณแก้ไขปัญหาได้โดยซ่อนสิ่งนี้ไว้ใช่ไหม ไม่แน่ใจว่ารหัสของคุณจะทำงานได้ตามที่คาดไว้ ...
PIRS

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';

คุณไม่สมมติว่ามีคลาส "ผู้ใช้" อยู่หรือ สิ่งที่มันอาจไม่และตอนนี้มันจะสร้างข้อผิดพลาดที่แตกต่างกันอย่างไร
Christopher Thomas

1
ที่จริงฉันไม่ได้สร้างอินสแตนซ์ของวัตถุผู้ใช้ดังนั้นฉันได้รับข้อผิดพลาด แต่หลังจากสร้างตัวอย่าง มันทำงาน .. ปัญหาของทั่วไปกับแนวคิด OOPS :)
Bastin โรบิน

6
ดีจริงปัญหาที่แท้จริงคือตัวอย่างของคุณถือว่าระดับผู้ใช้จะกำหนดนี้จะไม่เป็นปัญหาทั่วไปของการปฐมนิเทศวัตถุเป็นข้อกำหนดที่สำคัญของ;)
คริสโทมัส

1
ฉันควรจะใส่ "stdClass" ทั่วไปแทนที่ "ผู้ใช้"
TechNyquist

0

วิธีง่ายๆในการรับข้อผิดพลาดนี้คือการพิมพ์ (a) ด้านล่างหมายถึงการพิมพ์ (b)

(ก) $this->my->variable

(ข) $this->my_variable

เล็กน้อย แต่มองข้ามได้ง่ายและมองเห็นได้ยากหากคุณไม่ได้มองหามัน


สิ่งนี้เกี่ยวข้องกับคำถามต้นฉบับอย่างไร ไม่มีการมั่วสุมระหว่าง_และ->
Nico Haase

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. จากนั้นกำหนดออบเจกต์ด้วยคีย์และค่า thay $ res-> success = false;


(ฉันไม่เข้าใจthay) ในกรณีที่คุณต้องการให้ตัวแบ่งบรรทัดหลังจากเนื้อหาบางส่วนให้ผนวกช่องว่างสองช่องเข้ากับเนื้อหาที่มองเห็นของบรรทัดก่อนถึงจุดพัก
greybeard

-1

ไม่คุณไม่ได้ .. มันจะสร้างมันขึ้นมาเมื่อคุณเพิ่มค่าความสำเร็จให้กับ object.the คลาสเริ่มต้นจะสืบทอดมาหากคุณไม่ได้ระบุไว้


4
แม้ว่ามันจะส่งคืนข้อความมาตรฐานที่เข้มงวด ... มันเป็นวิธีปฏิบัติที่ดีเพียงอย่างเดียวในการสร้างวัตถุด้วยตนเองก่อนและในขณะที่ PHP ค่อนข้างอดทนต่อการเขียนโค้ดแบบสุ่มต่ำ แต่คุณไม่ควรละเลยที่จะทำสิ่งต่าง ๆ อย่างถูกต้อง
มาร์คเบเกอร์

4
เข้าใจฉันเป็นเพียงการตอบคำถามด้วยใช่ง่ายหรือไม่มีไม่กำหนดหรือปกป้องปฏิบัติที่ดีที่สุด :)
Silvertiger

-1

ลองใช้:

$user = (object) null;

2
โดยทั่วไปแล้วคำตอบมีประโยชน์มากขึ้นหากพวกเขามีคำอธิบายว่ารหัสนี้มีจุดประสงค์เพื่ออะไรและเหตุใดจึงแก้ปัญหาได้โดยไม่ต้องแนะนำผู้อื่น
lucascaro

-12

ฉันใส่ต่อไปนี้ที่ด้านบนของไฟล์ PHP faulting และข้อผิดพลาดก็ไม่แสดง:

error_reporting(E_ERROR | E_PARSE);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.