ข้อมูลอ้างอิง - ข้อผิดพลาดนี้หมายถึงอะไรใน PHP


1137

นี่คืออะไร?

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

ทำไมนี้

คำถามเช่น"ส่วนหัวที่ส่งไปแล้ว"หรือ"การโทรหาสมาชิกที่ไม่ใช่วัตถุ"ปรากฏขึ้นบ่อยครั้งใน Stack Overflow สาเหตุที่แท้จริงของคำถามเหล่านั้นเหมือนกันเสมอ ดังนั้นคำตอบสำหรับคำถามเหล่านั้นมักจะทำซ้ำแล้วแสดง OP ซึ่งบรรทัดที่จะเปลี่ยนแปลงในกรณีเฉพาะของพวกเขา คำตอบเหล่านี้ไม่ได้เพิ่มคุณค่าใด ๆ ให้กับเว็บไซต์เพราะพวกเขาจะใช้กับรหัสเฉพาะของ OP เท่านั้น ผู้ใช้รายอื่นที่มีข้อผิดพลาดเดียวกันไม่สามารถอ่านวิธีแก้ปัญหาได้ง่ายเนื่องจากมีการแปลเป็นภาษาท้องถิ่นมากเกินไป นั่นเป็นเรื่องน่าเศร้าเพราะเมื่อคุณเข้าใจสาเหตุของปัญหาการแก้ไขข้อผิดพลาดนั้นเป็นเรื่องเล็กน้อย ดังนั้นรายการนี้จะพยายามอธิบายวิธีแก้ปัญหาด้วยวิธีการทั่วไป

ฉันควรทำอะไรที่นี่

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

หากคุณต้องการมีส่วนร่วมโปรดเพิ่มข้อความแสดงข้อผิดพลาด "ที่ชื่นชอบ" คำเตือนหรือการแจ้งเตือนหนึ่งคำตอบคำอธิบายสั้น ๆ ว่ามันหมายถึงอะไร (แม้ว่าจะเป็นเพียงการไฮไลต์เทอมในหน้าคู่มือของพวกเขา) รายชื่อของคำถาม & คำตอบที่มีอยู่ซึ่งมีมูลค่า นอกจากนี้อย่าลังเลที่จะปรับปรุงคำตอบที่มีอยู่

รายการ

ดูเพิ่มเติมที่:


7
นอกจากนี้หากต้องการย้ายการอภิปรายออกจากความคิดเห็นโปรดไปที่คำถามเมตานี้
Earlz



คำตอบ:


275

คำเตือน: ไม่สามารถแก้ไขข้อมูลส่วนหัว - ส่งส่วนหัวแล้ว

เกิดขึ้นเมื่อสคริปต์ของคุณพยายามส่งส่วนหัว HTTP ไปยังลูกค้า แต่มีเอาต์พุตมาก่อนซึ่งส่งผลให้ส่วนหัวถูกส่งไปยังลูกค้าแล้ว

นี่คือE_WARNINGและจะไม่หยุดสคริปต์

ตัวอย่างทั่วไปจะเป็นไฟล์เทมเพลตดังนี้:

<html>
    <?php session_start(); ?>
    <head><title>My Page</title>
</html>
...

session_start()ฟังก์ชั่นจะพยายามที่จะส่งส่วนหัวกับคุกกี้เซสชั่นให้กับลูกค้า แต่ PHP ได้ส่งส่วนหัวเมื่อมันเขียน<html>องค์ประกอบไปยังกระแสข้อมูลขาออก คุณต้องย้ายsession_start()ไปด้านบน

คุณสามารถแก้ปัญหานี้ได้โดยเข้าไปที่บรรทัดก่อนที่รหัสจะเริ่มทำงานคำเตือนและตรวจสอบว่ามันอยู่ที่ใด ย้ายรหัสการส่งส่วนหัวใด ๆ ก่อนหน้ารหัสนั้น

?>การส่งออกมักจะมองข้ามคือสายใหม่หลังจากที่ปิดของ PHP มันถือว่าเป็นมาตรฐานการปฏิบัติที่จะละเว้น?>เมื่อมันเป็นสิ่งสุดท้ายในไฟล์ สาเหตุทั่วไปอีกประการสำหรับคำเตือนนี้คือเมื่อการเปิด<?phpมีช่องว่างบรรทัดหรืออักขระที่มองไม่เห็นก่อนหน้าทำให้เว็บเซิร์ฟเวอร์ส่งส่วนหัวและช่องว่าง / บรรทัดใหม่ดังนั้นเมื่อ PHP เริ่มการแยกวิเคราะห์จะไม่สามารถส่งได้ ส่วนหัวใด ๆ

หากไฟล์ของคุณมี<?php ... ?>บล็อกโค้ดมากกว่าหนึ่งบล็อกคุณไม่ควรเว้นวรรคระหว่างนั้น (หมายเหตุ: คุณอาจมีหลายช่วงตึกหากคุณมีรหัสที่สร้างขึ้นโดยอัตโนมัติ)

ตรวจสอบให้แน่ใจว่าคุณไม่มีเครื่องหมายคำสั่งซื้อไบต์ในรหัสของคุณเช่นเมื่อการเข้ารหัสของสคริปต์คือ UTF-8 พร้อม BOM

คำถามที่เกี่ยวข้อง:


2
หากคุณใช้งาน WordPress ให้ตรวจสอบไฟล์ธีม เมื่อฉันอัปเกรดไซต์เป็น WordPress เวอร์ชันใหม่ฉันไม่สามารถอัปเดตชุดรูปแบบได้เนื่องจากไม่ได้อัปเดตในหลายปี ปัญหานี้ถูกครอบตัด ปรากฎว่าไฟล์ functions.php มี <<มากกว่าหนึ่ง? ?> บล็อกด้วยช่องว่างระหว่าง
รอยเลบานอน

2
@RoyLeban "หากไฟล์ของคุณมีมากกว่าหนึ่งบล็อกใน ... " ฉันไม่แน่ใจว่าสิ่งนี้หมายความว่าอย่างไร "บล็อก" คืออะไร? หนึ่งบล็อกจะประกอบด้วย<?php ?>"มากกว่าหนึ่งบล็อก" <?php ?> <?php ?>หรือไม่
Andrew Fox

2
กรุณาเปิดคุณสมบัติ 'output buffering' ในไฟล์การกำหนดค่า PHP.ini ถ้าเป็นไปได้มันใช้เพื่อทำให้เกิดปัญหานี้มันจะส่งไฟล์ html ที่ถูกบันทึกในบัฟเฟอร์ผลลัพธ์และส่งไปยังไคลเอนต์หลังจากสคริปต์หยุดดังนั้นถ้าสอง ส่วนหัวจะออกในตำแหน่งที่แตกต่างจากนั้นส่วนหัวเก่าจะถูกแทนที่ส่วนหัวใหม่
Nidhin David

191

ข้อผิดพลาดร้ายแรง: การเรียกไปยังฟังก์ชันสมาชิก ... บนวัตถุที่ไม่ใช่

เกิดขึ้นกับรหัสคล้ายกับxyz->method()ที่xyzไม่ได้เป็นวัตถุและดังนั้นจึงmethodไม่สามารถเรียกว่า

นี่เป็นข้อผิดพลาดร้ายแรงที่จะหยุดสคริปต์ (การแจ้งเตือนความเข้ากันได้ไปข้างหน้า: มันจะกลายเป็นข้อผิดพลาดที่จับได้เริ่มต้นด้วย PHP 7)

ส่วนใหญ่มักจะเป็นสัญญาณว่ารหัสหายไปตรวจสอบเงื่อนไขข้อผิดพลาด ตรวจสอบว่าวัตถุเป็นวัตถุจริงก่อนที่จะเรียกวิธีการ

ทั่วไปตัวอย่างจะเป็น

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

ในตัวอย่างข้างต้นแบบสอบถามไม่สามารถเตรียมความพร้อมและprepare()จะกำหนดไปfalse $statementการพยายามเรียกใช้execute()เมธอดจะส่งผลให้เกิดข้อผิดพลาดร้ายแรงเนื่องจากfalseเป็น "ไม่ใช่วัตถุ" เนื่องจากค่าเป็นบูลีน

ลองคิดดูว่าทำไมฟังก์ชันของคุณส่งคืนบูลีนแทนที่จะเป็นวัตถุ ตัวอย่างเช่นตรวจสอบ$pdoวัตถุเพื่อหาข้อผิดพลาดล่าสุดที่เกิดขึ้น รายละเอียดเกี่ยวกับวิธีแก้ไขข้อบกพร่องนี้จะขึ้นอยู่กับวิธีจัดการข้อผิดพลาดสำหรับฟังก์ชัน / วัตถุ / คลาสที่ต้องการ

หากแม้->prepareจะล้มเหลวแล้วคุณ$pdoวัตถุจัดการฐานข้อมูลไม่ได้รับการผ่านเข้าไปในขอบเขตปัจจุบัน ค้นหาตำแหน่งที่กำหนดไว้ จากนั้นส่งผ่านเป็นพารามิเตอร์เก็บไว้เป็นคุณสมบัติหรือแชร์ผ่านขอบเขตทั่วโลก

ปัญหาอื่นอาจเป็นการสร้างวัตถุตามเงื่อนไขแล้วลองเรียกวิธีการภายนอกบล็อกเงื่อนไขนั้น ตัวอย่างเช่น

if ($someCondition) {
    $myObj = new MyObj();
}
// ...
$myObj->someMethod();

โดยพยายามที่จะดำเนินการวิธีการนอกบล็อกเงื่อนไขอาจไม่ได้กำหนดวัตถุของคุณ

คำถามที่เกี่ยวข้อง:


115

ไม่เห็นอะไรเลย หน้าว่างและสีขาว

หรือที่เรียกว่าหน้าขาว Of Deathหรือสีขาว Screen of Death สิ่งนี้จะเกิดขึ้นเมื่อการรายงานข้อผิดพลาดถูกปิดและเกิดข้อผิดพลาดร้ายแรง (มักเกิดจากข้อผิดพลาดทางไวยากรณ์)

หากคุณเปิดใช้งานการบันทึกข้อผิดพลาดคุณจะพบข้อความแสดงข้อผิดพลาดอย่างชัดเจนในบันทึกข้อผิดพลาดของคุณ โดยปกติจะอยู่ในไฟล์ชื่อ "php_errors.log" ไม่ว่าจะอยู่ในตำแหน่งศูนย์กลาง (เช่น/var/log/apache2ในสภาพแวดล้อม Linux จำนวนมาก) หรือในไดเรกทอรีของสคริปต์เอง (บางครั้งใช้ในสภาพแวดล้อมการโฮสต์ที่ใช้ร่วมกัน)

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

สามารถทำได้อย่างง่ายดายโดยเพิ่มที่ด้านบนสุดของสคริปต์ด้วยรหัส PHP ต่อไปนี้:

ini_set('display_errors', 1); error_reporting(~0);

รหัสจะเปิดการแสดงข้อผิดพลาดและตั้งค่าการรายงานในระดับสูงสุด

เนื่องจากini_set()ถูกเรียกใช้งาน ณ รันไทม์จึงไม่มีผลต่อข้อผิดพลาดในการวิเคราะห์คำ / ไวยากรณ์ ข้อผิดพลาดเหล่านั้นจะปรากฏในบันทึก หากคุณต้องการที่จะแสดงให้พวกเขาในการส่งออกเช่นกัน (เช่นในเบราว์เซอร์) ที่คุณต้องตั้งค่าคำสั่งเพื่อdisplay_startup_errors trueทำเช่นนี้ทั้งในphp.iniหรือใน.htaccessหรือโดยวิธีการอื่นใดที่มีผลต่อการกำหนดค่าก่อนรันไทม์

คุณสามารถใช้วิธีการเดียวกันเพื่อตั้งค่าคำสั่งlog_errorsและerror_logเพื่อเลือกตำแหน่งไฟล์บันทึกของคุณเอง

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

คำถามที่เกี่ยวข้อง:

ข้อผิดพลาดที่เกี่ยวข้อง:


3
error_reporting(~0);ทำไมไม่-1? นั่นคือสิ่งที่~0ประเมินและเป็นความลับที่น้อยกว่ามาก
FabrícioMatté

3
ฉันคิดว่าทั้งคู่มีความลับคล้ายกัน ~0มีความชัดเจนมากขึ้น IMO: ปฏิเสธการตั้งค่าบิตที่ว่างเปล่าเช่นเปิดใช้งานการตั้งค่าสถานะทั้งหมด -1 ไม่ได้หมายถึงการยืน«ไม่พบ»เช่นใน strpos () ใน C แต่เป็น1111'1111'1111'1111บิตเซ็ตที่มีการตั้งค่าสถานะทั้งหมดเนื่องจาก -1 เป็นไบนารี(สำหรับ 32 บิต)
nalply

2
อ๊ะ1111'1111'1111'1111เป็น 16 บิตจริง ๆ แต่ฉันหวังว่าคุณจะเข้าใจสิ่งที่ฉันหมายถึง
nalply

3
@IvanSolntsev ขอโทษไม่มีสำหรับรุ่นก่อน 5.4 ไม่รวมอยู่ในE_STRICT php.net/manual/en/errorfunc.constants.phpและเลื่อนลงไป E_ALLE_STRICT
nalply

102

แจ้งให้ทราบล่วงหน้า: ดัชนีที่ไม่ได้กำหนด

เกิดขึ้นเมื่อคุณพยายามเข้าถึงอาร์เรย์ด้วยคีย์ที่ไม่มีอยู่ในอาร์เรย์

ตัวอย่างทั่วไปของการUndefined Indexแจ้งเตือนคือ ( สาธิต )

$data = array('foo' => '42', 'bar');
echo $data['spinach'];
echo $data[1];

ทั้งสองspinachและ1ไม่มีอยู่ในอาร์เรย์ทำให้เกิดการทE_NOTICEริกเกอร์

วิธีแก้ไขคือทำให้แน่ใจว่ามีดัชนีหรือออฟเซ็ตอยู่ก่อนที่จะเข้าถึงดัชนีนั้น นี่อาจหมายความว่าคุณต้องแก้ไขข้อบกพร่องในโปรแกรมของคุณเพื่อให้แน่ใจว่าดัชนีเหล่านั้นมีอยู่เมื่อคุณคาดหวัง หรืออาจหมายความว่าคุณต้องทดสอบว่ามีดัชนีอยู่array_key_existsหรือไม่isset:

$data = array('foo' => '42', 'bar');
if (array_key_exists('spinach', $data)) {
    echo $data['spinach'];
}
else {
    echo 'No key spinach in the array';
}

หากคุณมีรหัสเช่น:

<?php echo $_POST['message']; ?>
<form method="post" action="">
    <input type="text" name="message">
    ...

จากนั้น$_POST['message']จะไม่ถูกตั้งค่าเมื่อมีการโหลดหน้าแรกและคุณจะได้รับข้อผิดพลาดด้านบน เฉพาะเมื่อมีการส่งแบบฟอร์มและรหัสนี้จะทำงานเป็นครั้งที่สองที่จะมีดัชนีอาร์เรย์ คุณมักจะตรวจสอบเรื่องนี้ด้วย:

if ($_POST)  ..  // if the $_POST array is not empty
// or
if ($_SERVER['REQUEST_METHOD'] == 'POST') ..  // page was requested with POST

คำถามที่เกี่ยวข้อง:


ฉันมักจะใช้if(!empty($_POST['message'])){ //do stuff }
kurdtpage

85

คำเตือน: mysql_fetch_array () คาดว่าพารามิเตอร์ 1 จะเป็นทรัพยากรกำหนดบูลีน

ก่อนอื่น:

กรุณาอย่าใช้mysql_*ฟังก์ชั่นในรหัสใหม่ พวกเขาจะไม่เก็บรักษาไว้และมีการยกเลิกอย่างเป็นทางการ เห็นกล่องสีแดง ? เรียนรู้เกี่ยวกับงบที่เตรียมไว้และใช้ PDOหรือ MySQLi -บทความนี้จะช่วยให้คุณตัดสินใจได้ว่า หากคุณเลือกที่ PDO,นี่คือการสอนที่ดี


สิ่งนี้จะเกิดขึ้นเมื่อคุณพยายามดึงข้อมูลจากผลลัพธ์mysql_queryแต่แบบสอบถามล้มเหลว

นี่เป็นคำเตือนและจะไม่หยุดสคริปต์ แต่จะทำให้โปรแกรมของคุณผิด

คุณต้องตรวจสอบผลลัพธ์ที่ส่งคืนโดยmysql_queryภายใน

$res = mysql_query($sql);
if (!$res) {
   die(mysql_error());
}
// after checking, do the fetch

คำถามที่เกี่ยวข้อง:

ข้อผิดพลาดที่เกี่ยวข้อง:

mysql*ฟังก์ชั่นอื่น ๆที่คาดว่าทรัพยากรผลลัพธ์ MySQL เป็นพารามิเตอร์จะผลิตข้อผิดพลาดเดียวกันด้วยเหตุผลเดียวกัน


5
เพียงแค่ทราบ หากmysql_queryไม่ดีพอการเพิ่มที่or dieอยู่ด้านบนเป็นการเพิ่มการดูถูกการบาดเจ็บ
Madara's Ghost

ปัญหาที่ฉันพบคือ$res = mysql_query($query)1 ถ้าแบบสอบถามประสบความสำเร็จจึงถือว่าเป็นจริง ดังนั้นเมื่อผ่านผลจากการ mysql_query ที่จะ mysql_fetch_array() แสดงให้เห็นแจ้งให้ทราบล่วงหน้า
mboy

@mboy สำหรับ SELECT, SHOW, DESCRIBE, EXPLAIN และข้อความอื่น ๆ ที่ส่งคืน resultset, mysql_query () ส่งคืนทรัพยากรที่ประสบความสำเร็จหรือ FALSE จากข้อผิดพลาด สำหรับคำสั่ง SQL ประเภทอื่น, INSERT, UPDATE, DELETE, DROP, ฯลฯ , mysql_query () จะส่งกลับค่า TRUE จากความสำเร็จหรือ FALSE จากข้อผิดพลาด
xdazz

@xdazz นั่นคือปัญหาที่ฉันเผชิญแทรกการปรับปรุงส่งกลับ TRUE ดังนั้นฉันไม่สามารถกำจัดข้อผิดพลาดนี้mysql_fetch_array() expects parameter 1 to be resource, boolean given in select โปรดดู - gist.github.com/romelemperado/93af4cdbd44ebf3a07cbfa0e3fc539d7 ข้อเสนอแนะเพื่อ git กำจัดข้อผิดพลาดนี้?
mboy

2
@mboy mysql_fetch_array()มีไว้สำหรับแบบสอบถามแบบใช้เลือกข้อมูลสำหรับแทรกและอัปเดตคุณไม่จำเป็นต้องดึงข้อมูลชุดผลลัพธ์ (และไม่มีชุดผลลัพธ์ให้คุณดึงข้อมูล)
xdazz

79

ข้อผิดพลาดร้ายแรง: ใช้ $ นี่เมื่อไม่ได้อยู่ในบริบทของวัตถุ

$thisเป็นตัวแปรพิเศษใน PHPซึ่งไม่สามารถกำหนดได้ หากมีการเข้าถึงในบริบทที่ไม่มีอยู่ข้อผิดพลาดร้ายแรงนี้จะได้รับ

ข้อผิดพลาดนี้สามารถเกิดขึ้นได้:

  1. หากวิธีการไม่คงที่เรียกว่าแบบคงที่ ตัวอย่าง:

    class Foo {
       protected $var;
       public function __construct($var) {
           $this->var = $var;
       }
    
       public static function bar () {
           // ^^^^^^
           echo $this->var;
           //   ^^^^^
       }
    }
    
    Foo::bar();

    วิธีแก้ไข:ตรวจสอบรหัสของคุณอีกครั้ง$thisสามารถใช้ในบริบทวัตถุเท่านั้นและไม่ควรใช้ในวิธีการคงที่ นอกจากนี้วิธีการคงที่ไม่ควรเข้าถึงคุณสมบัติไม่คงที่ ใช้self::$static_propertyเพื่อเข้าถึงคุณสมบัติคงที่

  2. หากรหัสจากวิธีการเรียนได้รับการคัดลอกไปยังฟังก์ชั่นปกติหรือเพียงแค่ขอบเขตทั่วโลกและรักษา$thisตัวแปรพิเศษ
    วิธีแก้ไข:ตรวจสอบรหัสและแทนที่$thisด้วยตัวแปรการแทนที่ที่แตกต่างกัน

คำถามที่เกี่ยวข้อง:

  1. เรียกใช้วิธีการที่ไม่คงที่เป็นแบบคงที่: ข้อผิดพลาดร้ายแรงของ PHP: ใช้ $ นี้เมื่อไม่ได้อยู่ในบริบทของวัตถุ
  2. คัดลอกรหัส: ข้อผิดพลาดร้ายแรง: ใช้ $ นี่เมื่อไม่ได้อยู่ในบริบทของวัตถุ
  3. คำถามทั้งหมด "การใช้ $ นี้เมื่อไม่ได้อยู่ในบริบทของวัตถุ" ใน Stackoverflow

2
คุณอาจต้องการพูดถึงวิธีการทำงานของ w / การปิด (แม้ในวิธีที่ไม่คงที่) และวิธีที่ "คงที่" ใน 5.4
เคนดัลล์ฮอปกินส์

2
@ ฮาเครฉันกำลังพูดถึงสายคงที่ในการปิด กด$closure = function() { self::method(); }ไลค์
เคนดัลล์ฮอปกินส์

2
@KendallHopkins: นั่นเป็นข้อผิดพลาดที่แตกต่างกัน: "ข้อผิดพลาดร้ายแรง: ไม่สามารถเข้าถึงตัวเอง :: เมื่อไม่มีขอบเขตระดับการใช้งาน"แต่กับ$thisคุณสามารถเรียก bespoken "ข้อผิดพลาดร้ายแรง: การใช้ $ นี้เมื่อไม่ได้อยู่ในบริบทของวัตถุ" :$closure = function() { $this->method(); };
hakre

75

ข้อผิดพลาดร้ายแรง: การเรียกไปยังฟังก์ชัน XXX ที่ไม่ได้กำหนด

เกิดขึ้นเมื่อคุณพยายามเรียกใช้ฟังก์ชันที่ยังไม่ได้กำหนด สาเหตุทั่วไปรวมถึงส่วนขยายที่ขาดหายไปและรวมถึงการประกาศฟังก์ชันตามเงื่อนไขฟังก์ชันในการประกาศฟังก์ชันหรือการพิมพ์ผิดปกติ

ตัวอย่างที่ 1 - การประกาศฟังก์ชันตามเงื่อนไข

$someCondition = false;
if ($someCondition === true) {
    function fn() {
        return 1;
    }
}
echo fn(); // triggers error

ในกรณีนี้fn()จะไม่ถูกประกาศเพราะ$someConditionไม่เป็นความจริง

ตัวอย่างที่ 2 - ฟังก์ชั่นในการประกาศฟังก์ชั่น

function createFn() 
{
    function fn() {
        return 1;
    }
}
echo fn(); // triggers error

ในกรณีนี้fnจะมีการประกาศเมื่อcreateFn()ได้รับการเรียกเท่านั้น โปรดทราบว่าการเรียกที่ตามมาcreateFn()จะทำให้เกิดข้อผิดพลาดเกี่ยวกับการประกาศซ้ำของฟังก์ชันที่มีอยู่

คุณอาจเห็นสิ่งนี้สำหรับฟังก์ชั่น PHP ในตัว ลองค้นหาฟังก์ชั่นในคู่มืออย่างเป็นทางการและตรวจสอบว่า "ส่วนขยาย" (โมดูล PHP) มันเป็นของอะไรและ PHP รุ่นใดบ้างที่รองรับ

ในกรณีที่ส่วนขยายหายไปให้ติดตั้งส่วนขยายนั้นและเปิดใช้งานใน php.ini อ้างถึงคำแนะนำในการติดตั้งในคู่มือ PHP สำหรับส่วนขยายที่ฟังก์ชั่นของคุณปรากฏขึ้นนอกจากนี้คุณยังสามารถเปิดใช้งานหรือติดตั้งส่วนขยายโดยใช้แพ็คเกจผู้จัดการของคุณ (เช่นaptDebian หรือ Ubuntu, yumRed Hat หรือ CentOS) หรือแผงควบคุม ในสภาพแวดล้อมการโฮสต์ที่ใช้ร่วมกัน

หากฟังก์ชั่นนี้ได้รับการแนะนำใน PHP รุ่นใหม่กว่าจากสิ่งที่คุณใช้คุณอาจพบลิงก์ไปยังการใช้งานทางเลือกในคู่มือหรือส่วนความคิดเห็น หากถูกลบออกจาก PHP แล้วให้ค้นหาข้อมูลเกี่ยวกับสาเหตุเนื่องจากอาจไม่จำเป็นอีกต่อไป

ในกรณีที่สูญหายรวมถึงให้แน่ใจว่าได้รวมไฟล์ที่ประกาศฟังก์ชั่นก่อนที่จะเรียกใช้ฟังก์ชั่น

ในกรณีที่พิมพ์ผิดแก้ไขข้อผิดพลาด

คำถามที่เกี่ยวข้อง:


73

ข้อผิดพลาดในการแยกวิเคราะห์: ข้อผิดพลาดทางไวยากรณ์ T_XXX ที่ไม่คาดคิด

เกิดขึ้นเมื่อคุณมีT_XXXโทเค็นในสถานที่ที่ไม่คาดคิดวงเล็บที่ไม่สมดุล (ฟุ่มเฟือย) ใช้แท็กสั้น ๆ โดยไม่เปิดใช้งานใน php.ini และอีกมากมาย

คำถามที่เกี่ยวข้อง:

สำหรับความช่วยเหลือเพิ่มเติมดู:

  • http://phpcodechecker.com/ - ซึ่งให้คำอธิบายที่เป็นประโยชน์เพิ่มเติมเกี่ยวกับไวยากรณ์ของคุณ

70

ข้อผิดพลาดร้ายแรง: ไม่สามารถใช้ฟังก์ชันส่งคืนค่าในบริบทการเขียน

emptyนี้มักจะเกิดขึ้นเมื่อใช้ฟังก์ชั่นโดยตรงกับ

ตัวอย่าง:

if (empty(is_null(null))) {
  echo 'empty';
}

เนื่องจากemptyเป็นโครงสร้างภาษาและไม่ใช่ฟังก์ชันจึงไม่สามารถเรียกได้โดยมีนิพจน์เป็นอาร์กิวเมนต์ในเวอร์ชัน PHP ก่อนหน้า 5.5 ก่อนหน้า PHP 5.5 อาร์กิวเมนต์จะempty()ต้องเป็นตัวแปรแต่นิพจน์โดยพลการ (เช่นค่าส่งคืนของฟังก์ชัน) อนุญาตใน PHP 5.5+

emptyแม้จะมีชื่อแล้วก็ตามไม่ได้ตรวจสอบว่าตัวแปรว่างเปล่าหรือไม่ == falseแต่มันจะตรวจสอบว่าตัวแปรที่ไม่อยู่หรือ การแสดงออก (เช่นis_null(null)ในตัวอย่าง) จะถือว่ามีอยู่เสมอดังนั้นที่นี่emptyเป็นเพียงการตรวจสอบว่ามันเท่ากับเท็จ คุณสามารถใช้ทดแทนempty()ที่นี่ด้วย!เช่นหรืออย่างชัดเจนเมื่อเทียบกับเท็จเช่นif (!is_null(null))if (is_null(null) == false)

คำถามที่เกี่ยวข้อง:


64

MySQL: คุณมีข้อผิดพลาดในไวยากรณ์ SQL ของคุณ; ตรวจสอบคู่มือที่สอดคล้องกับรุ่นเซิร์ฟเวอร์ MySQL ของคุณสำหรับไวยากรณ์ที่ถูกต้องที่จะใช้ใกล้ ... ที่บรรทัด ...

ข้อผิดพลาดนี้มักเกิดขึ้นเนื่องจากคุณลืมที่จะหลีกเลี่ยงข้อมูลที่ส่งผ่านไปยังแบบสอบถาม MySQL อย่างถูกต้อง

ตัวอย่างของสิ่งที่ไม่ควรทำ ("แนวคิดที่ไม่ดี"):

$query = "UPDATE `posts` SET my_text='{$_POST['text']}' WHERE id={$_GET['id']}";
mysqli_query($db, $query);

รหัสนี้อาจรวมอยู่ในหน้าเว็บที่มีแบบฟอร์มที่จะส่งพร้อมกับ URL เช่นhttp://example.com/edit.php?id=10 (เพื่อแก้ไขการโพสต์ n ° 10)

จะเกิดอะไรขึ้นถ้าข้อความที่ส่งมีคำพูดเดียว? $queryจะจบลงด้วย:

$query = "UPDATE `posts` SET my_text='I'm a PHP newbie' WHERE id=10';

และเมื่อแบบสอบถามนี้ถูกส่งไปยัง MySQL มันจะบ่นว่าไวยากรณ์ผิดเพราะมีเครื่องหมายคำพูดพิเศษอยู่ตรงกลาง

เพื่อหลีกเลี่ยงข้อผิดพลาดดังกล่าวคุณต้องหลีกเลี่ยงข้อมูลก่อนใช้ในแบบสอบถาม

การหลีกเลี่ยงข้อมูลก่อนใช้งานในแบบสอบถาม SQL ก็มีความสำคัญเช่นกันเพราะหากคุณไม่ใช้สคริปต์ของคุณจะถูกเปิดให้ใช้งาน SQL injections การฉีด SQL อาจทำให้เกิดการเปลี่ยนแปลงการสูญเสียหรือการดัดแปลงของบันทึกตารางหรือฐานข้อมูลทั้งหมด นี่เป็นปัญหาด้านความปลอดภัยที่ร้ายแรงมาก!

เอกสารอ้างอิง:


3
นอกจากนี้หากคุณไม่ทำเว็บไซต์ของคุณจะถูกแฮ็กโดยบอตโดยอัตโนมัติ
apscience

2
@gladoscc คลิก "แก้ไข" และแก้ไขคำตอบ ฉันรู้ว่ามันสามารถปรับปรุงได้
โจเซลีน

2
หรือใช้แบบสอบถาม SQL ที่เตรียมไว้
Matej

53

ข้อผิดพลาดร้ายแรง: ขนาดหน่วยความจำที่อนุญาตของ XXX ไบต์หมดลง (พยายามจัดสรร XXX ไบต์)

มีหน่วยความจำไม่เพียงพอที่จะเรียกใช้สคริปต์ของคุณ PHP มีจำนวนหน่วยความจำถึงขีด จำกัด แล้วและหยุดดำเนินการ ข้อผิดพลาดนี้ร้ายแรงถึงขั้นหยุดสคริปต์ ค่าของขีด จำกัด หน่วยความจำสามารถกำหนดค่าได้ทั้งในphp.iniไฟล์หรือโดยใช้ini_set('memory_limit', '128 M');ในสคริปต์ (ซึ่งจะเขียนทับค่าที่กำหนดในphp.ini) วัตถุประสงค์ของการ จำกัด หน่วยความจำคือเพื่อป้องกันไม่ให้สคริปต์ PHP ตัวเดียวทำการกลืนหน่วยความจำที่มีอยู่ทั้งหมดและทำให้เว็บเซิร์ฟเวอร์ทั้งหมดหยุดทำงาน

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

หากข้อผิดพลาดนี้เกิดขึ้นเมื่อสคริปต์ของคุณไม่ทำงานหนักมากคุณต้องตรวจสอบรหัสของคุณเพื่อดูว่ามีหน่วยความจำรั่วหรือไม่ memory_get_usageฟังก์ชั่นเป็นเพื่อนของคุณ

คำถามที่เกี่ยวข้อง:


53

ข้อผิดพลาดในการแยกวิเคราะห์: ข้อผิดพลาดทางไวยากรณ์ T_ENCAPSED_AND_WHITESPACE ที่ไม่คาดคิด

ข้อผิดพลาดนี้ส่วนใหญ่มักจะพบเมื่อพยายามที่จะอ้างอิงค่าอาร์เรย์ที่มีคีย์ที่ยกมา{}สำหรับการแก้ไขภายในสตริงยกมาสองครั้งเมื่อทั้งสร้างตัวแปรที่ซับซ้อนไม่ได้ใส่

กรณีข้อผิดพลาด:

สิ่งนี้จะส่งผลให้Unexpected T_ENCAPSED_AND_WHITESPACE:

echo "This is a double-quoted string with a quoted array key in $array['key']";
//---------------------------------------------------------------------^^^^^

การแก้ไขที่เป็นไปได้:

ในสตริงยกมาสองครั้ง, PHP จะอนุญาตให้สายสำคัญอาร์เรย์จะใช้unquotedE_NOTICEและจะไม่เป็นปัญหา ดังนั้นข้างต้นสามารถเขียนเป็น:

echo "This is a double-quoted string with an un-quoted array key in $array[key]";
//------------------------------------------------------------------------^^^^^

ทั้งตัวแปรอาร์เรย์ที่ซับซ้อนและที่สำคัญ (s) สามารถใส่ไว้ใน{}ซึ่งในกรณีที่พวกเขาควรE_NOTICEจะยกมาเพื่อหลีกเลี่ยงการ เอกสารประกอบ PHPแนะนำไวยากรณ์นี้สำหรับตัวแปรที่ซับซ้อน

echo "This is a double-quoted string with a quoted array key in {$array['key']}";
//--------------------------------------------------------------^^^^^^^^^^^^^^^
// Or a complex array property of an object:
echo "This is a a double-quoted string with a complex {$object->property->array['key']}";

แน่นอนทางเลือกใด ๆข้างต้นคือการเชื่อมต่อตัวแปรอาเรย์เข้าด้วยกันแทนการแก้ไข:

echo "This is a double-quoted string with an array variable". $array['key'] . " concatenated inside.";
//----------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^

สำหรับการอ้างอิงให้ดูในส่วนการแยกวิเคราะห์ตัวแปรในหน้าคู่มือสตริง PHP


45

คำเตือน: [ฟังก์ชั่น] : ไม่สามารถเปิดสตรีม: [เหตุผล]

มันเกิดขึ้นเมื่อคุณเรียกไฟล์ตามปกติ include , requireหรือfopenPHP และไม่สามารถหาไฟล์หรือได้รับอนุญาตไม่เพียงพอที่จะโหลดไฟล์

สิ่งนี้สามารถเกิดขึ้นได้จากหลายสาเหตุ:

  • เส้นทางของไฟล์ผิด
  • เส้นทางของไฟล์สัมพันธ์กัน
  • เส้นทางรวมผิด
  • การอนุญาตนั้น จำกัด เกินไป
  • SELinux มีผลบังคับใช้
  • และอื่น ๆ อีกมากมาย ...

หนึ่งในข้อผิดพลาดทั่วไปคือการไม่ใช้เส้นทางที่แน่นอน สิ่งนี้สามารถแก้ไขได้อย่างง่ายดายโดยใช้เส้นทางแบบเต็มหรือค่าคงที่เวทมนตร์เช่น__DIR__หรือ dirname(__FILE__):

include __DIR__ . '/inc/globals.inc.php';

หรือ:

require dirname(__FILE__) . '/inc/globals.inc.php';

การใช้เส้นทางที่ถูกต้องเป็นขั้นตอนเดียวในการแก้ไขปัญหาเหล่านี้ซึ่งอาจเกี่ยวข้องกับไฟล์ที่ไม่มีอยู่สิทธิของระบบไฟล์ที่ป้องกันการเข้าถึงหรือการ จำกัด การเปิดใช้งานโดย PHP เอง

วิธีที่ดีที่สุดในการแก้ไขปัญหานี้อย่างรวดเร็วคือทำตามรายการตรวจสอบการแก้ไขปัญหาด้านล่าง

คำถามที่เกี่ยวข้อง:

ข้อผิดพลาดที่เกี่ยวข้อง:


44

ข้อผิดพลาดในการแยกวิเคราะห์: ข้อผิดพลาดทางไวยากรณ์ T_PAAMAYIM_NEKUDOTAYIM ที่ไม่คาดคิด

ตัวดำเนินการแก้ไขปัญหาขอบเขตเรียกอีกอย่างว่า "Paamayim Nekudotayim" จากภาษาฮีบรูפעמייםנקודתיים ซึ่งหมายถึง "ทวิภาคคู่"

ข้อผิดพลาดนี้มักจะเกิดขึ้นหากคุณใส่::รหัสของคุณโดยไม่ตั้งใจ

คำถามที่เกี่ยวข้อง:

เอกสารอ้างอิง:


วิธีที่ง่ายที่สุดที่จะเกิดข้อผิดพลาดนี้กำลังทำงานหรือa()::b; $a=::;
Ismael Miguel

43

ประกาศ: การใช้ค่าคงที่ XXX ที่ไม่ได้กำหนด - สันนิษฐานว่า 'XXX'

หรือใน PHP 7.2 หรือใหม่กว่า:

คำเตือน: การใช้ค่าคงที่ XXX ที่ไม่ได้กำหนด - สันนิษฐานว่า 'XXX' (ซึ่งจะทำให้เกิดข้อผิดพลาดใน PHP เวอร์ชันอนาคต)

การแจ้งเตือนนี้เกิดขึ้นเมื่อมีการใช้โทเค็นในรหัสและดูเหมือนจะเป็นค่าคงที่ แต่ไม่ได้กำหนดค่าคงที่ด้วยชื่อนั้น

หนึ่งในสาเหตุที่พบบ่อยที่สุดของการแจ้งเตือนนี้คือความล้มเหลวในการอ้างอิงสตริงที่ใช้เป็นคีย์อาร์เรย์ที่เชื่อมโยง

ตัวอย่างเช่น:

// Wrong
echo $array[key];

// Right
echo $array['key'];

อีกสาเหตุที่พบบ่อยคือเครื่องหมาย$(ดอลลาร์) ที่หายไปด้านหน้าชื่อตัวแปร:

// Wrong
echo varName;

// Right
echo $varName;

หรือบางทีคุณอาจสะกดผิดค่าคงที่หรือคำหลักอื่น ๆ :

// Wrong
$foo = fasle;

// Right
$foo = false;

นอกจากนี้ยังอาจเป็นสัญญาณว่าส่วนขยาย PHP หรือไลบรารีที่จำเป็นหายไปเมื่อคุณพยายามเข้าถึงค่าคงที่ที่กำหนดโดยไลบรารีนั้น

คำถามที่เกี่ยวข้อง:


2
ฉันจะบอกว่าสาเหตุที่พบบ่อยที่สุดคือการลืม $ ต่อหน้าตัวแปรไม่ใช่อาร์เรย์
โอเวอร์

42

ข้อผิดพลาดร้ายแรง: ไม่สามารถประกาศคลาสใหม่ได้[ชื่อคลาส]

ข้อผิดพลาดร้ายแรง: ไม่สามารถประกาศใหม่[ชื่อฟังก์ชัน]

ซึ่งหมายความว่าคุณกำลังใช้ชื่อฟังก์ชัน / คลาสเดียวกันสองครั้งและต้องเปลี่ยนชื่อหนึ่งในนั้นหรือเป็นเพราะคุณเคยใช้requireหรือincludeที่ที่คุณควรจะใช้require_onceหรือinclude_onceหรือ

เมื่อคลาสหรือฟังก์ชั่นมีการประกาศใน PHP มันจะไม่เปลี่ยนรูปและไม่สามารถประกาศในภายหลังด้วยค่าใหม่

พิจารณารหัสต่อไปนี้:

class.php

<?php

class MyClass
{
    public function doSomething()
    {
        // do stuff here
    }
}

index.php

<?php

function do_stuff()
{
   require 'class.php';
   $obj = new MyClass;
   $obj->doSomething();
}

do_stuff();
do_stuff();

การเรียกครั้งที่สองdo_stuff()จะทำให้เกิดข้อผิดพลาดด้านบน ด้วยการเปลี่ยนrequireเป็นrequire_onceเราสามารถมั่นใจได้ว่าไฟล์ที่มีคำจำกัดความของMyClassจะถูกโหลดเพียงครั้งเดียวและจะหลีกเลี่ยงข้อผิดพลาด


3
มันคุ้มค่าหรือไม่ที่พูดถึงการใช้การโหลดอัตโนมัติและมาตรฐานเช่นPSR-4หรือแม้กระทั่งPSR-0 ที่เลิกใช้แล้วในตอนนี้ก็สามารถกำจัดสิ่งนี้ได้โดยการช่วยให้คุณไม่จำเป็นต้องใช้ / รวมตัวคุณเอง
DanielM

39

แจ้งให้ทราบล่วงหน้า: ตัวแปรที่ไม่ได้กำหนด

เกิดขึ้นเมื่อคุณพยายามใช้ตัวแปรที่ไม่ได้กำหนดไว้ก่อนหน้านี้

ตัวอย่างทั่วไปจะเป็น

foreach ($items as $item) {
    // do something with item
    $counter++;
}

หากคุณไม่ได้กำหนด $counterก่อนหน้ารหัสด้านบนจะทริกเกอร์การแจ้งเตือน

วิธีที่ถูกต้องคือการตั้งค่าตัวแปรก่อนใช้งานแม้ว่าจะเป็นเพียงสตริงว่างเช่น

$counter = 0;
foreach ($items as $item) {
    // do something with item
    $counter++;
}

ประกาศ: คุณสมบัติที่ไม่ได้กำหนด

ข้อผิดพลาดนี้มีความหมายเหมือนกันมาก แต่หมายถึงคุณสมบัติของวัตถุ การใช้ตัวอย่างด้านบนcounterซ้ำรหัสนี้จะทำให้เกิดข้อผิดพลาดเนื่องจากยังไม่ได้ตั้งค่าคุณสมบัติ

$obj = new stdclass;
$obj->property = 2342;
foreach ($items as $item) {
    // do something with item
    $obj->counter++;
}

คำถามที่เกี่ยวข้อง:


35

ข้อผิดพลาดในการแยกวิเคราะห์: ข้อผิดพลาดทางไวยากรณ์ T_VARIABLE ที่ไม่คาดคิด

สถานการณ์ที่เป็นไปได้

ฉันดูเหมือนจะไม่พบรหัสของฉันผิดไป นี่คือข้อผิดพลาดเต็มของฉัน:

ข้อผิดพลาดในการแยกวิเคราะห์: ข้อผิดพลาดทางไวยากรณ์ T_VARIABLE ที่ไม่คาดคิดบนบรรทัด x

สิ่งที่ฉันพยายาม

$sql = 'SELECT * FROM dealer WHERE id="'$id.'"';

ตอบ

ข้อผิดพลาดในการแยกวิเคราะห์:ปัญหาเกี่ยวกับไวยากรณ์ของโปรแกรมของคุณเช่นการเว้นเครื่องหมายอัฒภาคออกจากท้ายคำสั่งหรือเช่นกรณีด้านบนขาดตัว.ดำเนินการ ล่ามหยุดทำงานโปรแกรมของคุณเมื่อพบข้อผิดพลาดในการแยกวิเคราะห์

กล่าวง่ายๆว่านี่เป็นข้อผิดพลาดทางไวยากรณ์หมายความว่ามีบางอย่างในรหัสของคุณที่จะหยุดการแยกวิเคราะห์อย่างถูกต้องและทำงานได้

สิ่งที่คุณควรทำคือตรวจสอบอย่างรอบคอบในบรรทัดที่มีข้อผิดพลาดสำหรับข้อผิดพลาดง่ายๆ

นั่นหมายความว่าข้อผิดพลาดที่ในสาย x ของไฟล์ล่าม PHP ได้รับการคาดหวังว่าจะเห็นวงเล็บเปิด T_VARIABLEแต่มันมีอะไรบางอย่างที่พบที่เรียกว่า ว่าสิ่งที่เรียกว่าT_VARIABLE tokenเป็นวิธีการล่าม PHP ในการแสดงส่วนพื้นฐานที่แตกต่างกันของโปรแกรม เมื่อล่ามอ่านในโปรแกรมแปลว่าสิ่งที่คุณเขียนลงในรายการโทเค็น เมื่อใดก็ตามที่คุณใส่ตัวแปรในโปรแกรมของคุณT_VARIABLEโทเค็นอยู่ในรายการของล่าม

อ่านดี: รายชื่อ Parser Tokens

ดังนั้นให้แน่ใจว่าคุณเปิดใช้งานอย่างน้อยE_PARSEในตัวคุณphp.iniในของคุณการแยกวิเคราะห์ไม่ควรมีอยู่ในสคริปต์การผลิต

ฉันแนะนำเสมอเพื่อเพิ่มคำสั่งต่อไปนี้ในขณะที่การเข้ารหัส:

error_reporting(E_ALL);

การรายงานข้อผิดพลาด PHP

นอกจากนี้ควรใช้ IDE ซึ่งจะช่วยให้คุณทราบข้อผิดพลาดในการแยกวิเคราะห์ในขณะที่พิมพ์ คุณสามารถใช้ได้:

  1. NetBeans (ชิ้นส่วนสวยงาม, ซอฟต์แวร์ฟรี) (ดีที่สุดในความคิดของฉัน)
  2. PhpStorm (ลุงกอร์ดอนชอบสิ่งนี้: P, แผนการจ่ายเงิน, มีซอฟต์แวร์ที่เป็นกรรมสิทธิ์และฟรี)
  3. Eclipse (ความงามและสัตว์ร้ายซอฟต์แวร์ฟรี)

คำถามที่เกี่ยวข้อง:


34

แจ้งให้ทราบล่วงหน้า: ชดเชยสตริง Uninitialized: *

ตามที่ระบุชื่อข้อผิดพลาดประเภทดังกล่าวเกิดขึ้นเมื่อคุณพยายามทำซ้ำหรือค้นหาค่าจากอาเรย์ด้วยคีย์ที่ไม่มีอยู่

พิจารณาคุณกำลังพยายามแสดงจดหมายทุกฉบับจาก $string

$string = 'ABCD'; 
for ($i=0, $len = strlen($string); $i <= $len; $i++){
    echo "$string[$i] \n"; 
}

ตัวอย่างข้างต้นจะสร้าง ( การสาธิตออนไลน์ ):

A
B
C
D
Notice: Uninitialized string offset: 4 in XXX on line X

และทันทีที่สคริปต์เสร็จสิ้นการสะท้อนDคุณจะได้รับข้อผิดพลาดเนื่องจากในfor()ลูปคุณได้บอกให้ PHP แสดงอักขระสตริงตัวแรกถึงตัวที่ห้าจาก'ABCD'ซึ่งมีอยู่ แต่เนื่องจากลูปเริ่มนับ0และสะท้อนกลับDเมื่อถึงเวลา4จะส่งข้อผิดพลาดออฟเซ็ต

ข้อผิดพลาดที่คล้ายกัน:


32

ประกาศ: พยายามหาคุณสมบัติของข้อผิดพลาดที่ไม่ใช่วัตถุ

เกิดขึ้นเมื่อคุณพยายามเข้าถึงคุณสมบัติของวัตถุในขณะที่ไม่มีวัตถุ

ตัวอย่างทั่วไปสำหรับการแจ้งให้ทราบที่ไม่ใช่วัตถุจะเป็น

$users = json_decode('[{"name": "hakre"}]');
echo $users->name; # Notice: Trying to get property of non-object

ในกรณีนี้, $usersคืออาร์เรย์ (ไม่ใช่วัตถุ) และไม่มีคุณสมบัติใด ๆ

สิ่งนี้คล้ายกับการเข้าถึงดัชนีหรือคีย์ของอาร์เรย์ที่ไม่มีอยู่ (ดูประกาศ: ดัชนีที่ไม่ได้กำหนด )

ตัวอย่างนี้ง่ายมาก การแจ้งเตือนดังกล่าวส่วนใหญ่ส่งสัญญาณการส่งคืนค่าที่ไม่ถูกตรวจสอบเช่นเมื่อไลบรารีส่งคืนNULLหากวัตถุไม่มีอยู่หรือเป็นเพียงค่าที่ไม่ใช่วัตถุที่ไม่คาดคิด (เช่นในผลลัพธ์ Xpath, โครงสร้าง JSON ที่มีรูปแบบที่ไม่คาดคิด แต่รหัสไม่ได้ตรวจสอบเงื่อนไขดังกล่าว

ในขณะที่ไม่ใช่วัตถุเหล่านั้นจะถูกประมวลผลเพิ่มเติมบ่อยครั้งที่ข้อผิดพลาดร้ายแรงเกิดขึ้นต่อไปเมื่อเรียกวิธีวัตถุบนวัตถุที่ไม่ใช่วัตถุ (ดู: ข้อผิดพลาดร้ายแรง: เรียกใช้ฟังก์ชันสมาชิก ... ในวัตถุที่ไม่ใช่ ) หยุดการทำงาน ต้นฉบับ

สามารถป้องกันได้อย่างง่ายดายโดยตรวจสอบเงื่อนไขข้อผิดพลาดและ / หรือว่าตัวแปรตรงกับความคาดหวัง นี่คือการแจ้งเตือนพร้อมกับตัวอย่างDOMXPath :

$result  = $xpath->query("//*[@id='detail-sections']/div[1]");
$divText = $result->item(0)->nodeValue; # Notice: Trying to get property of non-object

ปัญหาคือการเข้าถึงnodeValueคุณสมบัติ (เขตข้อมูล) ของรายการแรกในขณะที่ยังไม่ได้รับการตรวจสอบว่ามีอยู่หรือไม่อยู่ใน$resultคอลเลกชัน แต่จะจ่ายให้โค้ดชัดเจนยิ่งขึ้นโดยการกำหนดตัวแปรให้กับออบเจ็กต์ที่รหัสทำงาน:

$result  = $xpath->query("//*[@id='detail-sections']/div[1]");
$div     = $result->item(0);
$divText = "-/-";
if (is_object($div)) {
    $divText = $div->nodeValue;
}
echo $divText;

ข้อผิดพลาดที่เกี่ยวข้อง:


1
json_decodeตอนนี้จะส่งคืนอินสแตนซ์ของstdclassโดยค่าเริ่มต้นดังนั้นโค้ดตัวอย่างจะใช้งานได้จริง
Hugo Zink

@HugoZink: จริง ๆ แล้วมัน (และทำเสมอ) คืนค่าอาร์เรย์สำหรับตัวอย่างนั้น: 3v4l.org/SUDe0 - คุณสามารถให้การอ้างอิงสำหรับการเขียนของคุณที่" json_decodeตอนนี้ส่งกลับstdclassค่าเริ่มต้นของอินสแตนซ์" ? ฉันไม่พบสิ่งนั้นในการเปลี่ยนแปลง
hakre

ตามหน้าคู่มือ PHP บนjson_decodeโดยค่าเริ่มต้นassocพารามิเตอร์ถูกตั้งค่าเป็นเท็จ พารามิเตอร์นี้ตัดสินใจว่าจะส่งคืนฟังก์ชันstdclassแทนที่จะเป็นอาเรย์แบบเชื่อมโยงหรือไม่
Hugo Zink

json_decode('[{"name": "hakre"}]', true)จะคืนค่าอาร์เรย์มิฉะนั้นเป็นstdclassวัตถุ
zanderwar

29

คำเตือน: มีผลบังคับใช้ข้อ จำกัด open_basedir

คำเตือนนี้สามารถปรากฏขึ้นพร้อมกับฟังก์ชั่นต่าง ๆ ที่เกี่ยวข้องกับการเข้าถึงไฟล์และไดเรกทอรี มันเตือนเกี่ยวกับปัญหาการกำหนดค่า

เมื่อปรากฏขึ้นแสดงว่ามีการห้ามการเข้าถึงไฟล์บางไฟล์

คำเตือนนั้นไม่ได้ทำลายอะไรเลย แต่ส่วนใหญ่สคริปต์มักจะทำงานไม่ถูกต้องหากป้องกันการเข้าถึงไฟล์

โดยปกติการแก้ไขจะเปลี่ยนการกำหนดค่า PHP การตั้งค่าที่เกี่ยวข้องเรียกว่าopen_basedirการตั้งค่าที่เกี่ยวข้องจะเรียกว่า

บางครั้งมีการใช้ชื่อไฟล์หรือไดเรกทอรีผิดการแก้ไขคือการใช้ชื่อที่ถูกต้อง

คำถามที่เกี่ยวข้อง:


1
ปัญหานี้เกิดขึ้นบ่อยที่สุดในโฮสต์ที่ใช้ร่วมกันโดยทั่วไปคนมักจะไม่ล็อคตัวเองจากไดเรกทอรี :-)
2012

28

ข้อผิดพลาดในการแยกวิเคราะห์: ข้อผิดพลาดทางไวยากรณ์, '[' ที่ไม่คาดคิด

ข้อผิดพลาดนี้มีสองรูปแบบ:

รูปแบบที่ 1

$arr = [1, 2, 3];

ไวยากรณ์เริ่มต้นของอาร์เรย์นี้ถูกนำมาใช้ใน PHP 5.4 เท่านั้น มันจะเพิ่มข้อผิดพลาดในการแยกวิเคราะห์ในรุ่นก่อนหน้านั้น ถ้าเป็นไปได้อัพเกรดการติดตั้งของคุณหรือใช้ไวยากรณ์เก่า:

$arr = array(1, 2, 3);

ดูตัวอย่างนี้จากคู่มือ

รูปแบบที่ 2

$suffix = explode(',', 'foo,bar')[1];

ผลการทำงานของฟังก์ชั่นการกระจายสัญญาณอาเรย์ยังถูกนำมาใช้ใน PHP 5.4 หากไม่สามารถอัพเกรดได้คุณต้องใช้ตัวแปร (ชั่วคราว):

$parts = explode(',', 'foo,bar');
$suffix = $parts[1];

ดูตัวอย่างนี้จากคู่มือ


23

คำเตือน: [ฟังก์ชั่น]คาดว่าพารามิเตอร์ 1 จะเป็นทรัพยากรกำหนดบูลีน

(รูปแบบทั่วไปเพิ่มเติมของคำเตือน: mysql_fetch_array () คาดว่าพารามิเตอร์ 1 จะเป็นทรัพยากรกำหนดบูลีน )

ทรัพยากรเป็นประเภทใน PHP (เช่นสตริงจำนวนเต็มหรือวัตถุ) ทรัพยากรเป็นหยดทึบแสงที่ไม่มีคุณค่าที่มีความหมายโดยธรรมชาติของมันเอง ทรัพยากรมีความเฉพาะเจาะจงและกำหนดโดยฟังก์ชั่น PHP หรือส่วนขยายบางอย่าง ตัวอย่างเช่นส่วนขยาย Mysql กำหนดสองประเภททรัพยากร :

มีสองประเภททรัพยากรที่ใช้ในโมดูล MySQL ตัวแรกคือตัวระบุลิงก์สำหรับการเชื่อมต่อฐานข้อมูลส่วนที่สองคือทรัพยากรที่เก็บผลลัพธ์ของแบบสอบถาม

ส่วนขยาย cURL กำหนดประเภทของทรัพยากรอีกสองประเภท :

... ที่จับ cURL และที่จับหลาย cURL

เมื่อvar_dumped ค่าจะเป็นดังนี้:

$resource = curl_init();
var_dump($resource);

resource(1) of type (curl)

นั่นคือทรัพยากรส่วนใหญ่ทั้งหมดคือตัวระบุตัวเลข ( (1)) ของบางประเภท ( (curl))

คุณนำทรัพยากรเหล่านี้ไปรอบ ๆ และส่งต่อไปยังหน้าที่ต่างๆซึ่งทรัพยากรดังกล่าวหมายถึงบางสิ่ง โดยทั่วไปฟังก์ชั่นเหล่านี้จัดสรรข้อมูลบางอย่างในพื้นหลังและทรัพยากรเป็นเพียงการอ้างอิงที่พวกเขาใช้ในการติดตามข้อมูลนี้ภายใน


ข้อผิดพลาด" ... คาดว่าพารามิเตอร์ 1 เป็นทรัพยากรข้อผิดพลาดบูลีนที่กำหนด " โดยทั่วไปแล้วเป็นผลมาจากการดำเนินการที่ไม่ได้ตรวจสอบซึ่งควรจะสร้างทรัพยากร แต่ส่งคืนfalseแทน ตัวอย่างเช่นfopenฟังก์ชั่นมีคำอธิบายนี้:

คืนค่า

ส่งคืนทรัพยากรตัวชี้ไฟล์เมื่อสำเร็จหรือFALSEผิดพลาด

ดังนั้นในรหัสนี้$fpอาจจะเป็นresource(x) of type (stream)หรือfalse:

$fp = fopen(...);

หากคุณไม่ตรวจสอบว่าการfopenดำเนินการสำเร็จหรือล้มเหลวและด้วยเหตุนี้จึง$fpเป็นทรัพยากรที่ถูกต้องหรือfalseและส่ง$fpต่อไปยังฟังก์ชันอื่นซึ่งคาดว่าทรัพยากรคุณอาจได้รับข้อผิดพลาดด้านบน:

$fp   = fopen(...);
$data = fread($fp, 1024);

Warning: fread() expects parameter 1 to be resource, boolean given

คุณจำเป็นต้องตรวจสอบข้อผิดพลาดคืนค่าของฟังก์ชันที่พยายามจัดสรรทรัพยากรและอาจล้มเหลว :

$fp = fopen(...);

if (!$fp) {
    trigger_error('Failed to allocate resource');
    exit;
}

$data = fread($fp, 1024);

ข้อผิดพลาดที่เกี่ยวข้อง:


22

คำเตือน: การชดเชยสตริงที่ผิดกฎหมาย 'XXX'

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

ตัวอย่าง:

$var = "test";
echo $var["a_key"];

หากคุณคิดว่าตัวแปรควรเป็นอาเรย์ให้ดูว่ามันมาจากที่ใดและแก้ไขปัญหาที่นั่น


20

โค้ดไม่ทำงาน / ดูเหมือนว่าบางส่วนของโค้ด PHP ของฉันถูกส่งออก

หากคุณไม่เห็นผลลัพธ์ใด ๆ จากโค้ด PHP ของคุณ แต่อย่างใดและ / หรือคุณเห็นบางส่วนของผลลัพธ์ซอร์สโค้ด PHP ที่แท้จริงของคุณในเว็บเพจคุณสามารถมั่นใจได้ว่า PHP ของคุณไม่ได้ถูกเรียกใช้งาน หากคุณใช้ View Source ในเบราว์เซอร์ของคุณคุณอาจเห็นไฟล์ซอร์สโค้ด PHP ทั้งหมดตามที่เป็นอยู่ เนื่องจากโค้ด PHP ฝังอยู่ใน<?php ?>แท็กเบราว์เซอร์จะพยายามตีความว่าเป็นแท็ก HTML และผลลัพธ์อาจดูค่อนข้างสับสน

ในการใช้งานสคริปต์ PHP ของคุณคุณต้อง:

  • เว็บเซิร์ฟเวอร์ที่รันสคริปต์ของคุณ
  • เพื่อตั้งนามสกุลไฟล์เป็น. php มิฉะนั้นเว็บเซิร์ฟเวอร์จะไม่ตีความมัน *
  • เพื่อเข้าถึงไฟล์. php ของคุณผ่านเว็บเซิร์ฟเวอร์

* หากคุณไม่กำหนดค่าใหม่ทุกอย่างสามารถกำหนดค่าได้

อันสุดท้ายนี้มีความสำคัญอย่างยิ่ง เพียงคลิกสองครั้งที่ไฟล์จะเปิดในเบราว์เซอร์ของคุณโดยใช้ที่อยู่เช่น:

file://C:/path/to/my/file.php

นี่เป็นการข้ามเว็บเซิร์ฟเวอร์ใด ๆ ที่คุณอาจใช้งานอยู่และไฟล์ไม่ได้รับการตีความ คุณต้องไปที่ URL ของไฟล์บนเว็บเซิร์ฟเวอร์ของคุณซึ่งอาจเป็นไปได้ดังนี้:

http://localhost/my/file.php

คุณอาจต้องการตรวจสอบว่าคุณใช้แท็กเปิดสั้น ๆ<?แทน<?phpและการกำหนดค่า PHP ของคุณได้ปิดแท็กเปิดสั้น ๆ หรือไม่

ยังเห็นว่าไม่มีการใช้งานโค้ด PHP แต่จะแสดงรหัสในหน้าเพจแทน


18

คำเตือน: mysql_connect (): การเข้าถึงถูกปฏิเสธสำหรับผู้ใช้ 'ชื่อ' @ 'โฮสต์'

คำเตือนนี้จะปรากฏขึ้นเมื่อคุณเชื่อมต่อกับเซิร์ฟเวอร์ MySQL / MariaDB ที่มีข้อมูลประจำตัวที่ไม่ถูกต้องหรือหายไป (ชื่อผู้ใช้ / รหัสผ่าน) ดังนั้นนี่ไม่ใช่ปัญหารหัส แต่เป็นปัญหาการกำหนดค่าเซิร์ฟเวอร์

  • ดูหน้าคู่มือในmysql_connect("localhost", "user", "pw")ตัวอย่าง

  • ตรวจสอบว่าคุณใช้จริงและ $username$password

    • ไม่ใช่เรื่องแปลกที่คุณจะเข้าถึงโดยไม่ต้องใช้รหัสผ่านซึ่งเป็นสิ่งที่เกิดขึ้นเมื่อคำเตือน: กล่าวว่า (using password: NO)กล่าวว่า
    • เฉพาะเซิร์ฟเวอร์ทดสอบภายในเท่านั้นที่อนุญาตให้เชื่อมต่อกับชื่อผู้ใช้rootไม่มีรหัสผ่านและtestชื่อฐานข้อมูล

    • คุณสามารถทดสอบว่าพวกเขาถูกต้องจริงโดยใช้ไคลเอนต์บรรทัดคำสั่ง:
      mysql --user="username" --password="password" testdb

    • ชื่อผู้ใช้และรหัสผ่านคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่และช่องว่างไม่ได้ถูกละเว้น ถ้ารหัสผ่านของคุณมีอักขระเมตาเหมือน$หนีพวกเขาหรือใส่รหัสผ่านในราคาเดียว

    • ผู้ให้บริการโฮสต์ที่ใช้ร่วมกันส่วนใหญ่ประกาศบัญชี mysql ล่วงหน้าเกี่ยวกับบัญชีผู้ใช้ unix (บางครั้งก็เป็นเพียงคำนำหน้าหรือคำต่อท้ายที่เป็นตัวเลขเพิ่มเติม) ดูเอกสารสำหรับรูปแบบหรือเอกสารประกอบและ CPanel หรืออินเทอร์เฟซอะไรก็ได้สำหรับการตั้งรหัสผ่าน

    • ดูคู่มือ MySQL เกี่ยวกับการเพิ่มบัญชีผู้ใช้โดยใช้บรรทัดคำสั่ง เมื่อเชื่อมต่อในฐานะผู้ใช้ที่เป็นผู้ดูแลระบบคุณสามารถออกแบบสอบถามเช่น:
      CREATE USER 'username'@'localhost' IDENTIFIED BY 'newpassword';

    • หรือใช้Adminerหรือปรับแต่งหรือเครื่องมือกราฟิกอื่น ๆ เพื่อสร้างเช็คหรือบัญชีที่ถูกต้องรายละเอียด

    • หากคุณไม่สามารถแก้ไขข้อมูลประจำตัวของคุณได้ดังนั้นการขอให้อินเทอร์เน็ตเพื่อ "โปรดช่วย" จะไม่มีผลใด ๆ มีเพียงคุณและผู้ให้บริการโฮสต์ของคุณเท่านั้นที่มีสิทธิ์และการเข้าถึงที่เพียงพอในการวินิจฉัยและแก้ไขสิ่งต่าง ๆ

  • ตรวจสอบว่าคุณสามารถเข้าถึงเซิร์ฟเวอร์ฐานข้อมูลโดยใช้ชื่อโฮสต์ที่กำหนดโดยผู้ให้บริการของคุณ:
    ping dbserver.hoster.example.net

    • ตรวจสอบสิ่งนี้จากคอนโซล SSH โดยตรงบนเว็บเซิร์ฟเวอร์ของคุณ การทดสอบจากลูกค้าในพื้นที่ของคุณไปยังเซิร์ฟเวอร์โฮสต์ที่ใช้ร่วมกันนั้นไม่ค่อยมีความหมาย

    • บ่อยครั้งที่คุณต้องการให้ชื่อเซิร์ฟเวอร์เป็น"localhost"ปกติซึ่งโดยปกติจะใช้ซ็อกเก็ตที่มีชื่อโลคอลเมื่อมี ในบางครั้งคุณสามารถลองใช้"127.0.0.1"เป็นทางเลือก

    • เซิร์ฟเวอร์ MySQL / MariaDB "servername:3306"ของคุณควรจะฟังในพอร์ตที่แตกต่างกันแล้วการใช้งาน

    • หากล้มเหลวแสดงว่าอาจมีปัญหาไฟร์วอลล์ (นอกหัวข้อไม่ใช่คำถามเกี่ยวกับการเขียนโปรแกรมไม่มีการเดาจากระยะไกลที่เป็นไปได้)

  • เมื่อใช้ค่าคงที่เหมือนเช่นDB_USERหรือDB_PASSWORDตรวจสอบว่าพวกเขากำลังจริงที่กำหนดไว้

    • หากคุณได้รับ a "Warning: Access defined for 'DB_USER'@'host'"และ a แสดง"Notice: use of undefined constant 'DB_PASS'"ว่าเป็นปัญหาของคุณ

    • ตรวจสอบว่าเช่นของคุณxy/db-config.phpถูกรวมอยู่และอะไร

  • ตรวจสอบการตั้งอย่างถูกต้องสิทธิ์GRANT

    • มันไม่เพียงพอที่จะมีคู่username+password

    • บัญชี MySQL / MariaDB แต่ละบัญชีสามารถมีชุดของสิทธิ์ที่แนบมา

    • สิ่งเหล่านี้สามารถ จำกัด ฐานข้อมูลที่คุณได้รับอนุญาตให้เชื่อมต่อจากการเชื่อมต่อที่ไคลเอนต์ / เซิร์ฟเวอร์อาจเกิดขึ้นและอนุญาตการสืบค้นใด

    • คำเตือน "การเข้าถึงถูกปฏิเสธ" ดังนั้นอาจปรากฏขึ้นสำหรับการmysql_queryโทรหากคุณไม่ได้รับอนุญาตSELECTจากตารางที่เฉพาะเจาะจงหรือINSERT/ UPDATEและDELETEสิ่งอื่น ๆ

    • คุณสามารถปรับเปลี่ยนสิทธิ์ของบัญชีเมื่อเชื่อมต่อต่อไคลเอนต์บรรทัดคำสั่งโดยใช้บัญชีผู้ดูแลระบบด้วยแบบสอบถามเช่น:
      GRANT ALL ON yourdb.* TO 'username'@'localhost';

  • หากการแสดงคำเตือนขึ้นครั้งแรกกับWarning: mysql_query(): Access denied for user ''@'localhost'แล้วคุณอาจจะมีphp.ini-ที่กำหนดไว้ล่วงหน้าบัญชี / คู่รหัสผ่าน

    • ตรวจสอบmysql.default_user=และmysql.default_password=มีค่าที่มีความหมาย

    • บ่อยครั้งที่นี่คือการกำหนดค่าผู้ให้บริการ ดังนั้นติดต่อฝ่ายสนับสนุนของพวกเขาสำหรับความไม่ตรงกัน

  • ค้นหาเอกสารของผู้ให้บริการโฮสต์ที่ใช้ร่วมกันของคุณ:

  • โปรดทราบว่าคุณอาจจะหมดลงสระว่ายน้ำการเชื่อมต่อที่มีอยู่ คุณจะได้รับคำเตือนการเข้าถึงที่ถูกปฏิเสธสำหรับการเชื่อมต่อพร้อมกันมากเกินไป (คุณต้องตรวจสอบการตั้งค่านั่นเป็นปัญหาการกำหนดค่าเซิร์ฟเวอร์นอกหัวข้อไม่ใช่คำถามโปรแกรม)

  • เวอร์ชันไคลเอ็นต์ libmysql ของคุณอาจเข้ากันไม่ได้กับเซิร์ฟเวอร์ฐานข้อมูล โดยปกติแล้วเซิร์ฟเวอร์ MySQL และ MariaDB สามารถเข้าถึงได้ด้วย PHPs ที่คอมไพล์ในไดรเวอร์ หากคุณมีการตั้งค่าแบบกำหนดเองหรือรุ่น PHP ที่ล้าสมัยและเซิร์ฟเวอร์ฐานข้อมูลที่ใหม่กว่ามากหรือรุ่นเก่าอย่างมาก - รุ่นที่ไม่ตรงกันอาจป้องกันการเชื่อมต่อ (ไม่คุณต้องตรวจสอบด้วยตัวเองไม่มีใครสามารถคาดเดาการตั้งค่าของคุณได้)

การอ้างอิงเพิ่มเติม:

Btw คุณอาจไม่ต้องการที่จะใช้ฟังก์ชั่นอีกต่อไปmysql_* ผู้มาใหม่มักจะโยกย้ายไปยังmysqliซึ่งเป็นเรื่องน่าเบื่อ แทนที่จะอ่านPDO และงบที่เตรียมไว้แทน
$db = new PDO("mysql:host=localhost;dbname=testdb", "username", "password");


2
mysql อนุญาตให้เชื่อมต่ออัตโนมัติผ่านการตั้งค่า php-ini จากนั้นข้อความแสดงข้อผิดพลาดเดียวกันจะได้รับพร้อมคำสั่งต่าง ๆ เช่น"คำเตือน: mysql_query (): การเข้าถึงถูกปฏิเสธสำหรับผู้ใช้ '' @ 'localhost' (ใช้รหัสผ่าน: NO) .. " - แค่สังเกต
hakre

ฮาลืมเรื่องทั้งหมดโดยสิ้นเชิง! (อาจใช้งานครั้งสุดท้ายกับ PHP3 หรือดังนั้น .. )
มาริโอ

18

แจ้งให้ทราบล่วงหน้า: เรย์เป็นการแปลงสตริง

สิ่งนี้จะเกิดขึ้นถ้าคุณพยายามที่จะใช้อาร์เรย์เป็นสตริง:

$arr = array('foo', 'bar');

echo $arr;  // Notice: Array to string conversion
$str = 'Something, ' . $arr;  // Notice: Array to string conversion

อาเรย์ไม่สามารถecho'หรือต่อกับสตริงได้เนื่องจากผลลัพธ์ไม่ได้กำหนดไว้อย่างดี PHP จะใช้สตริง "Array" แทนอาร์เรย์และเรียกการแจ้งเตือนเพื่อชี้ให้เห็นว่านั่นอาจไม่ใช่สิ่งที่ตั้งใจไว้และคุณควรตรวจสอบรหัสของคุณที่นี่ คุณอาจต้องการสิ่งนี้แทน:

echo $arr[0];  // displays foo
$str = 'Something ' . join(', ', $arr); //displays Something, foo, bar

หรือวนรอบอาร์เรย์:

foreach($arr as $key => $value) {
    echo "array $key = $value";
    // displays first: array 0 = foo
    // displays next:  array 1 = bar
}

หากประกาศนี้ปรากฏที่ใดที่คุณไม่คาดคิดก็หมายความว่าตัวแปรที่คุณคิดว่าเป็นสตริงนั้นเป็นอาร์เรย์จริง นั่นหมายความว่าคุณมีข้อผิดพลาดในรหัสของคุณซึ่งทำให้ตัวแปรนี้เป็นอาร์เรย์แทนที่จะเป็นสตริงที่คุณคาดหวัง


12

คำเตือน: หารด้วยศูนย์

ข้อความเตือน 'หารด้วยศูนย์' เป็นหนึ่งในคำถามที่พบบ่อยที่สุดในบรรดานักพัฒนา PHP ใหม่ ข้อผิดพลาดนี้จะไม่ทำให้เกิดข้อยกเว้นดังนั้นนักพัฒนาบางคนจะระงับคำเตือนเป็นครั้งคราวโดยการเพิ่มตัวดำเนินการปราบปรามข้อผิดพลาด @ ก่อนนิพจน์ ตัวอย่างเช่น:

$value = @(2 / 0);

แต่เช่นเดียวกับการเตือนใด ๆ แนวทางที่ดีที่สุดคือการติดตามสาเหตุของการเตือนและแก้ไข สาเหตุของการเตือนจะมาจากอินสแตนซ์ใด ๆ ที่คุณพยายามหารด้วย 0 ตัวแปรเท่ากับ 0 หรือตัวแปรที่ไม่ได้รับมอบหมาย (เนื่องจาก NULL == 0) เนื่องจากผลลัพธ์จะเป็น 'ไม่ได้กำหนด'

หากต้องการแก้ไขคำเตือนนี้คุณควรเขียนนิพจน์ของคุณใหม่เพื่อตรวจสอบว่าค่าไม่ใช่ 0 ถ้าใช่ให้ทำอย่างอื่น หากค่าเป็นศูนย์คุณไม่ควรหารหรือคุณควรเปลี่ยนค่าเป็น 1 แล้วหารดังนั้นการหารจะให้ผลลัพธ์เท่ากับการหารด้วยตัวแปรเพิ่มเติมเท่านั้น

if ( $var1 == 0 ) { // check if var1 equals zero
    $var1 = 1; // var1 equaled zero so change var1 to equal one instead
    $var3 = ($var2 / $var1); // divide var1/var2 ie. 1/1
} else {
    $var3 = ($var2 / $var1); // if var1 does not equal zero, divide
}

คำถามที่เกี่ยวข้อง:


การตั้งค่าเป็น 1 หากเป็น 0 จะหยุดข้อผิดพลาด แต่นี่จะดีกว่าการปราบปรามที่คุณบอกว่าไม่ควรใช้ (ซึ่งฉันเห็นด้วย) ฉันขอแนะนำให้มากที่สุดเท่าที่จะเป็นไปได้ที่ข้อความหรือค่าอื่นจะถูกส่งคืน
James

ตัวอย่างเช่นนี้ถ้า$var1ไม่ == 0 แล้วคุณก็สามารถตั้งค่าการ$var3 $var2แม้ว่าจะไม่ได้ทำสิ่งนั้นไม่จำเป็นเลยเพราะการมอบหมายนั้นเหมือนกันในทั้งสองกรณีดังนั้นจึงไม่มีอย่างอื่นและมอบหมายนอกif
James

8

มาตรฐานที่เข้มงวด: วิธีการไม่คงที่[<class> :: <method>]ไม่ควรเรียกว่าแบบคงที่

เกิดขึ้นเมื่อคุณพยายามเรียกใช้วิธีการไม่คงที่ในคลาสที่เป็นแบบคงที่และคุณยังมีการE_STRICTตั้งค่าสถานะในerror_reporting()การตั้งค่าของคุณ

ตัวอย่าง:

class HTML {
   public function br() {
      echo '<br>';
   }
}

HTML::br() หรือ $html::br()

จริงๆคุณสามารถหลีกเลี่ยงข้อผิดพลาดนี้โดยไม่มีการเพิ่มE_STRICTการerror_reporting()เช่น

error_reporting(E_ALL & ~E_STRICT);

ตั้งแต่สำหรับ PHP 5.4.0 ขึ้นไปE_STRICTจะรวมอยู่ในE_ALL[ ref ] แต่นั่นไม่ใช่คำแนะนำ วิธีแก้ปัญหาคือการกำหนดฟังก์ชั่นแบบคงที่ที่คุณตั้งใจจะใช้จริงstatic:

public static function br() {
  echo '<br>';
}

หรือเรียกใช้ฟังก์ชันตามอัตภาพ:

$html = new HTML();
$html->br();

คำถามที่เกี่ยวข้อง:


7

เลิกใช้: ไวยากรณ์การเข้าถึงการชดเชยอาร์เรย์และอาร์เรย์ด้วยเครื่องหมายปีกกาจะถูกคัดค้าน

การปิดสตริงและองค์ประกอบอาร์เรย์สามารถเข้าถึงได้โดยการจัดฟันแบบโค้ง{}ก่อน PHP 7.4.0:

$string = 'abc';
echo $string{0};  // a

$array = [1, 2, 3];
echo $array{0};  // 1

สิ่งนี้เลิกใช้แล้วตั้งแต่ PHP 7.4.0 และสร้างคำเตือน:

เลิกใช้: ไวยากรณ์การเข้าถึงการชดเชยอาร์เรย์และอาร์เรย์ด้วยเครื่องหมายปีกกาจะถูกคัดค้าน

คุณต้องใช้วงเล็บเหลี่ยม[]เพื่อเข้าถึงการชดเชยสตริงและองค์ประกอบอาร์เรย์:

$string = 'abc';
echo $string[0];  // a

$array = [1, 2, 3];
echo $array[0];  // 1

RFC สำหรับการเปลี่ยนแปลงนี้การเชื่อมโยงไปยัง PHP สคริปต์ซึ่งพยายามที่จะแก้ไขปัญหานี้โดยอัตโนมัติ

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