“ ข้อสังเกต: ตัวแปรที่ไม่ได้กำหนด”,“ ข้อสังเกต: ดัชนีที่ไม่ได้กำหนด” และ“ ข้อสังเกต: ออฟเซ็ตที่ไม่ได้กำหนด” โดยใช้ PHP
ฉันใช้สคริปต์ PHP และยังคงได้รับข้อผิดพลาดเช่น:
หมายเหตุ: ตัวแปรที่ไม่ได้กำหนด: my_variable_name ใน C: \ wamp \ www \ mypath \ index.php ในบรรทัดที่ 10
หมายเหตุ: ดัชนีที่ไม่ได้กำหนด: my_index C: \ wamp \ www \ mypath \ index.php ในบรรทัดที่ 11
บรรทัดที่ 10 และ 11 มีลักษณะดังนี้:
echo "My variable value is: " . $my_variable_name; echo "My index value is: " . $my_array["my_index"];
ความหมายของข้อความแสดงข้อผิดพลาดเหล่านี้คืออะไร?
ทำไมพวกเขาถึงปรากฏขึ้นในทันที? ฉันเคยใช้สคริปต์นี้เป็นเวลาหลายปีและไม่เคยมีปัญหาใด ๆ
ฉันจะแก้ไขได้อย่างไร
นี่เป็นคำถามอ้างอิงทั่วไปสำหรับผู้ที่จะเชื่อมโยงว่าซ้ำกันแทนที่จะต้องอธิบายปัญหาซ้ำแล้วซ้ำเล่า ฉันรู้สึกว่านี่เป็นสิ่งที่จำเป็นเพราะคำตอบในโลกแห่งความจริงส่วนใหญ่เกี่ยวกับปัญหานี้มีความเฉพาะเจาะจงมาก
การอภิปราย Meta ที่เกี่ยวข้อง:
- คำถามซ้ำซากทำอะไรได้บ้าง?
- "คำถามอ้างอิง" เหมาะสมหรือไม่?
คำตอบ
หมายเหตุ: ตัวแปรที่ไม่ได้กำหนด
จากภูมิปัญญามากมายของคู่มือ PHP :
การใช้ค่าเริ่มต้นของตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้นเป็นปัญหาในกรณีของการรวมไฟล์หนึ่งไปยังอีกไฟล์หนึ่งซึ่งใช้ชื่อตัวแปรเดียวกัน นอกจากนี้ยังเป็นที่สำคัญเสี่ยงด้านความปลอดภัยที่มีregister_globalsเปิด ข้อผิดพลาดระดับE_NOTICE เกิดขึ้นในกรณีที่ทำงานกับตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้นอย่างไรก็ตามไม่ใช่ในกรณีของการต่อท้ายองค์ประกอบเข้ากับอาร์เรย์ที่ไม่ได้กำหนดค่าเริ่มต้น โครงสร้างภาษาisset ()สามารถใช้เพื่อตรวจสอบว่าตัวแปรถูกเตรียมใช้งานแล้วหรือไม่ นอกจากนี้และในอุดมคติมากขึ้นคือการแก้ปัญหาของempty ()เนื่องจากไม่สร้างคำเตือนหรือข้อความแสดงข้อผิดพลาดหากตัวแปรไม่ได้ถูกเตรียมใช้งาน
จากเอกสาร PHP :
ไม่มีการสร้างคำเตือนหากไม่มีตัวแปร นั่นหมายความว่าว่างเปล่า ()มีความกระชับเทียบเท่ากับ! isset ($var) || $var == เท็จ
ซึ่งหมายความว่าคุณสามารถใช้เพียงempty()
เพื่อตรวจสอบว่าตัวแปรที่มีการตั้งค่าและนอกจากมันจะตรวจสอบตัวแปรกับต่อไปนี้0
, 0.0
, ""
, "0"
, null
, หรือfalse
[]
ตัวอย่าง:
$o = []; @$var = ["",0,null,1,2,3,$foo,$o['myIndex']];
array_walk($var, function($v) {
echo (!isset($v) || $v == false) ? 'true ' : 'false';
echo ' ' . (empty($v) ? 'true' : 'false');
echo "\n";
});
ทดสอบตัวอย่างด้านบนในตัวแก้ไข PHP ออนไลน์ของ 3v4l.org
แม้ว่า PHP จะไม่ต้องการการประกาศตัวแปร แต่ก็แนะนำให้ใช้เพื่อหลีกเลี่ยงช่องโหว่ด้านความปลอดภัยหรือจุดบกพร่องที่ใครจะลืมให้ค่าตัวแปรที่จะใช้ในสคริปต์ในภายหลัง สิ่งที่ PHP ทำในกรณีของตัวแปรที่ไม่ได้ประกาศนั้นมีข้อผิดพลาดระดับต่ำมากซึ่งเป็นข้อผิดพลาดE_NOTICE
ที่ไม่ได้รับการรายงานตามค่าเริ่มต้น แต่คู่มือแนะนำให้อนุญาตในระหว่างการพัฒนา
วิธีจัดการกับปัญหา:
แนะนำ:ประกาศตัวแปรของคุณเช่นเมื่อคุณพยายามต่อท้ายสตริงเข้ากับตัวแปรที่ไม่ได้กำหนด หรือใช้isset()/ !empty()เพื่อตรวจสอบว่ามีการประกาศก่อนที่จะอ้างอิงหรือไม่ดังใน:
//Initializing variable $value = ""; //Initialization value; Examples //"" When you want to append stuff later //0 When you want to add numbers later //isset() $value = isset($_POST['value']) ? $_POST['value'] : ''; //empty() $value = !empty($_POST['value']) ? $_POST['value'] : '';
สิ่งนี้สะอาดขึ้นมากเมื่อ PHP 7.0 ตอนนี้คุณสามารถใช้โอเปอเรเตอร์ null coalesce :
// Null coalesce operator - No need to explicitly initialize the variable. $value = $_POST['value'] ?? '';
ตั้งค่าตัวจัดการข้อผิดพลาดที่กำหนดเองสำหรับ E_NOTICE และเปลี่ยนเส้นทางข้อความออกจากเอาต์พุตมาตรฐาน (อาจเป็นไฟล์บันทึก):
set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
ปิดใช้งาน E_NOTICE จากการรายงาน วิธีที่รวดเร็วในการยกเว้น
E_NOTICE
คือ:error_reporting( error_reporting() & ~E_NOTICE )
ปราบปรามข้อผิดพลาดที่มีผู้ประกอบการ @
หมายเหตุ:ขอแนะนำอย่างยิ่งให้ใช้เพียงจุดที่ 1
หมายเหตุ: ดัชนีที่ไม่ได้กำหนด / ออฟเซ็ตที่ไม่ได้กำหนด
ประกาศนี้จะปรากฏขึ้นเมื่อคุณ (หรือ PHP) พยายามเข้าถึงดัชนีที่ไม่ได้กำหนดของอาร์เรย์
วิธีจัดการกับปัญหา:
ตรวจสอบว่ามีดัชนีอยู่หรือไม่ก่อนที่คุณจะเข้าถึง สำหรับสิ่งนี้คุณสามารถใช้isset()หรือarray_key_exists():
//isset() $value = isset($array['my_index']) ? $array['my_index'] : ''; //array_key_exists() $value = array_key_exists('my_index', $array) ? $array['my_index'] : '';
โครงสร้างภาษาlist()อาจสร้างสิ่งนี้เมื่อพยายามเข้าถึงดัชนีอาร์เรย์ที่ไม่มีอยู่:
list($a, $b) = array(0 => 'a'); //or list($one, $two) = explode(',', 'test string');
ใช้ตัวแปรสองตัวเพื่อเข้าถึงองค์ประกอบอาร์เรย์สององค์ประกอบ แต่มีเพียงองค์ประกอบอาร์เรย์ดัชนี0
เดียวดังนั้นสิ่งนี้จะสร้าง:
หมายเหตุ: ออฟเซ็ตที่ไม่ได้กำหนด: 1
$_POST
/ $_GET
/ $_SESSION
ตัวแปร
ประกาศดังกล่าวข้างต้นปรากฏบ่อยเมื่อทำงานร่วมกับ$_POST
, หรือ$_GET
$_SESSION
สำหรับ$_POST
และ$_GET
คุณต้องตรวจสอบว่ามีดัชนีอยู่หรือไม่ก่อนที่จะใช้ สำหรับ$_SESSION
คุณต้องแน่ใจว่าคุณได้เริ่มเซสชันsession_start()และมีดัชนีอยู่ด้วย
โปรดทราบว่าตัวแปรทั้ง 3 ตัวคือsuperglobalsและเป็นตัวพิมพ์ใหญ่
ที่เกี่ยวข้อง:
- หมายเหตุ: ตัวแปรที่ไม่ได้กำหนด
- หมายเหตุ: ดัชนีที่ไม่ได้กำหนด
ลองสิ่งเหล่านี้
Q1: การแจ้งเตือนนี้หมายความว่า $ varname ไม่ได้กำหนดไว้ที่ขอบเขตปัจจุบันของสคริปต์
Q2: การใช้เงื่อนไข isset () ว่าง () ก่อนใช้ตัวแปรที่น่าสงสัยจะทำงานได้ดี
// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? ''; // pre-7 PHP versions $user_name = '';
if (!empty($_SESSION['user_name'])) { $user_name = $_SESSION['user_name'];
}
หรือเป็นวิธีแก้ปัญหาที่รวดเร็วและสกปรก:
// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);
หมายเหตุเกี่ยวกับเซสชัน:
เมื่อใช้เซสชัน
session_start();
จำเป็นต้องวางไว้ในไฟล์ทั้งหมดโดยใช้เซสชันhttp://php.net/manual/en/features.sessions.php
ตัวดำเนินการแสดงข้อผิดพลาด@
สำหรับการแจ้งเตือนที่ไม่ต้องการและซ้ำซ้อนเราสามารถใช้ตัว@ดำเนินการเฉพาะเพื่อ» ซ่อน «ข้อความตัวแปร / ดัชนีที่ไม่ได้กำหนด
$var = @($_GET["optional_param"]);
- สิ่งนี้มักจะหมดกำลังใจ ผู้มาใหม่มักจะใช้มันมากเกินไป
- ไม่เหมาะสมอย่างยิ่งสำหรับโค้ดที่อยู่ในตรรกะของแอปพลิเคชัน (ละเว้นตัวแปรที่ไม่ได้ประกาศซึ่งคุณไม่ควร) เช่นสำหรับพารามิเตอร์ฟังก์ชันหรือในลูป
- อย่างไรก็ตามมีสิ่งหนึ่งที่กลับหัวเหนือกว่า
isset?:
หรือการกดทับ??
มากเกินไป การแจ้งเตือนยังคงสามารถบันทึกได้ และอาจมีการรื้อฟื้นการ@
แจ้งเตือนที่ถูกซ่อนด้วย:set_error_handler("var_dump");
- นอกจากนี้คุณไม่ควรใช้ / แนะนำเป็นประจำ
if (isset($_POST["shubmit"]))
ในรหัสเริ่มต้นของคุณ - ผู้มาใหม่จะไม่สังเกตเห็นการพิมพ์ผิดดังกล่าว มันเป็นเพียงการกีดกันการแจ้งเตือน PHPs สำหรับกรณีเหล่านั้น เพิ่ม
@
หรือisset
เฉพาะหลังจากการตรวจสอบการทำงาน -
แก้ไขสาเหตุก่อน. ไม่ใช่ประกาศ
- นอกจากนี้คุณไม่ควรใช้ / แนะนำเป็นประจำ
- @ส่วนใหญ่เป็นที่ยอมรับสำหรับ
$_GET
/$_POST
ป้อนพารามิเตอร์เฉพาะถ้าพวกเขาไม่จำเป็นกำลัง
และเนื่องจากสิ่งนี้ครอบคลุมคำถามส่วนใหญ่ดังกล่าวเรามาขยายสาเหตุที่พบบ่อยที่สุด:
$_GET
/ $_POST
/ $_REQUEST
อินพุตที่ไม่ได้กำหนด
สิ่งแรกที่คุณต้องทำเมื่อพบดัชนี / ออฟเซ็ตที่ไม่ได้กำหนดคือตรวจสอบการพิมพ์ผิด:
$count = $_GET["whatnow?"];
- นี่คือชื่อคีย์ที่คาดหวังและแสดงในคำขอแต่ละหน้าหรือไม่
- ชื่อตัวแปรและตัวบ่งชี้อาร์เรย์เป็นกรณีที่คำนึงถึงใน PHP
ประการที่สองหากการแจ้งเตือนไม่มีสาเหตุที่ชัดเจนให้ใช้var_dumpหรือprint_rเพื่อตรวจสอบอาร์เรย์อินพุตทั้งหมดสำหรับเนื้อหาที่ไม่ได้รับการรักษา:
var_dump($_GET); var_dump($_POST); //print_r($_REQUEST);
ทั้งสองอย่างจะเปิดเผยว่าสคริปต์ของคุณถูกเรียกใช้ด้วยสิทธิหรือพารามิเตอร์ใด ๆ เลย
ทางเลือกอื่นหรือใช้devtools เบราว์เซอร์F12ของคุณ( ) เพิ่มเติมและตรวจสอบแท็บเครือข่ายสำหรับคำขอและพารามิเตอร์:
พารามิเตอร์ POST และ GET input จะแสดงแยกกัน
สำหรับ
$_GET
พารามิเตอร์คุณสามารถดูQUERY_STRINGในprint_r($_SERVER);
PHP มีกฎบางประการในการรวมชื่อพารามิเตอร์ที่ไม่ได้มาตรฐานเข้ากับ superglobals Apache อาจทำการเขียนใหม่ด้วยเช่นกัน คุณยังสามารถดูที่
$_COOKIES
ส่วนหัวของคำขอ HTTP ที่ให้มาและอื่น ๆ ด้วยวิธีนั้นดูที่แถบที่อยู่เบราว์เซอร์ของคุณอย่างชัดเจนยิ่งขึ้นสำหรับพารามิเตอร์ GET :
http://example.org/script.php?id=5&sort=desc
name=value
คู่หลังจากที่?
เครื่องหมายคำถามมีคำค้นหาของคุณ (GET) พารามิเตอร์ ดังนั้น URL นี้สามารถให้ผลตอบแทน$_GET["id"]
และ$_GET["sort"]
.สุดท้ายตรวจสอบ
<form>
และ<input>
ประกาศของคุณหากคุณคาดหวังว่าจะได้รับพารามิเตอร์ แต่ไม่ได้รับ- ตรวจสอบว่าอินพุตที่ต้องการแต่ละรายการมีไฟล์
<input name=FOO>
id=
หรือtitle=
แอตทริบิวต์ไม่พอเพียง- รูปแบบควรจะเติม
method=POST
$_POST
- ในขณะที่
method=GET
(หรือปล่อยทิ้งไว้) จะให้$_GET
ตัวแปร - นอกจากนี้ยังสามารถจัดหาแบบฟอร์ม
action=script.php?get=param
ผ่าน $ _GET และmethod=POST
ช่องที่เหลือใน $ _POST ควบคู่ไปด้วย - ด้วยการกำหนดค่า PHP ที่ทันสมัย (≥ 5.6) จึงเป็นไปได้ (ไม่ทันสมัย) ที่จะใช้$_REQUEST['vars']อีกครั้งซึ่งจะผสมผสานพารามิเตอร์ GET และ POST
- ตรวจสอบว่าอินพุตที่ต้องการแต่ละรายการมีไฟล์
หากคุณใช้ mod_rewrite คุณควรตรวจสอบทั้งสอง
access.log
อย่างรวมทั้งเปิดใช้งานRewriteLogเพื่อหาพารามิเตอร์ที่ขาด
$_FILES
$_FILES["formname"]
ตรวจสอบสติเดียวกันนำไปใช้กับการอัปโหลดไฟล์และ- นอกจากนี้ตรวจสอบ
enctype=multipart/form-data
- เช่นเดียวกับ
method=POST
ใน<form>
คำประกาศของคุณ - ดูเพิ่มเติม: PHP Undefined index error $ _FILES?
$_COOKIE
$_COOKIE
อาร์เรย์ไม่เคยมีประชากรขวาหลังจากsetcookie()
แต่เมื่อขอติดตาม HTTP ใด ๆ- นอกจากนี้ความถูกต้องหมดเวลาอาจเป็นข้อ จำกัด ของโดเมนย่อยหรือแต่ละเส้นทางและผู้ใช้และเบราว์เซอร์สามารถปฏิเสธหรือลบออกได้
โดยทั่วไปเป็นเพราะ "การเขียนโปรแกรมที่ไม่ดี" และมีความเป็นไปได้ที่จะเกิดข้อผิดพลาดในขณะนี้หรือภายหลัง
- หากเป็นข้อผิดพลาดให้ทำการกำหนดตัวแปรที่เหมาะสมก่อน: $ varname = 0;
- หากมีการกำหนดไว้เป็นบางครั้งเท่านั้นให้ทดสอบ:
if (isset($varname))
ก่อนใช้งาน - หากเป็นเพราะคุณสะกดผิดให้แก้ไข
- อาจถึงขั้นเปลี่ยนคำเตือนในการตั้งค่า PHP ของคุณ
หมายความว่าคุณกำลังทดสอบประเมินหรือพิมพ์ตัวแปรที่คุณยังไม่ได้กำหนดอะไรให้ หมายความว่าคุณพิมพ์ผิดหรือคุณต้องตรวจสอบว่าตัวแปรได้รับการเตรียมใช้งานก่อน ตรวจสอบเส้นทางลอจิกของคุณอาจถูกตั้งค่าในเส้นทางเดียว แต่ไม่ใช่ในอีกเส้นทางหนึ่ง
ฉันไม่ต้องการปิดการใช้งานการแจ้งเตือนเนื่องจากมีประโยชน์ แต่ต้องการหลีกเลี่ยงการพิมพ์มากเกินไป
ทางออกของฉันคือฟังก์ชันนี้:
function ifexists($varname) { return(isset($$varname)?$varname:null);
}
ดังนั้นหากฉันต้องการอ้างอิงถึง $ name และ echo หากมีอยู่ฉันเพียงแค่เขียน:
<?=ifexists('name')?>
สำหรับองค์ประกอบอาร์เรย์:
function ifexistsidx($var,$index)
{
return(isset($var[$index])?$var[$index]:null);
}
ในหน้าถ้าฉันต้องการอ้างถึง $ _REQUEST ['name']:
<?=ifexistsidx($_REQUEST,'name')?>
วิธีที่ดีที่สุดในการรับสตริงอินพุตคือ:
$value = filter_input(INPUT_POST, 'value');
ซับเดียวนี้เกือบจะเทียบเท่ากับ:
if (!isset($_POST['value'])) {
$value = null; } elseif (is_array($_POST['value'])) {
$value = false; } else { $value = $_POST['value'];
}
หากคุณต้องการค่าสตริงเช่นเดียวกับ:
$value = (string)filter_input(INPUT_POST, 'value');
เป็นเพราะตัวแปร '$user_location' is not getting defined. If you are using any if loop inside which you are declaring the '$user_location 'จากนั้นคุณต้องมีลูปอื่นและกำหนดเหมือนกัน ตัวอย่างเช่น:
$a=10; if($a==5) { $user_location='Paris';} else { } echo $user_location;
โค้ดด้านบนจะสร้างข้อผิดพลาดเนื่องจากไม่พอใจ if loop และใน else loop '$ user_location' ไม่ได้กำหนดไว้ PHP ยังคงถูกขอให้สะท้อนตัวแปรออกมา ดังนั้นในการแก้ไขโค้ดคุณต้องทำสิ่งต่อไปนี้:
$a=10;
if($a==5) { $user_location='Paris';} else { $user_location='SOMETHING OR BLANK'; } echo $user_location;
ตอบกลับ "" ทำไมพวกเขาถึงปรากฏขึ้นในทันที? ฉันเคยใช้สคริปต์นี้มาหลายปีแล้วและฉันไม่เคยมีปัญหาใด ๆ "
เป็นเรื่องปกติมากที่ไซต์ส่วนใหญ่จะดำเนินการภายใต้การรายงานข้อผิดพลาด "ค่าเริ่มต้น" ของ "แสดงข้อผิดพลาดทั้งหมด แต่ไม่ใช่" การแจ้งเตือน "และ" เลิกใช้งาน "" สิ่งนี้จะถูกตั้งค่าใน php.ini และใช้กับไซต์ทั้งหมดบนเซิร์ฟเวอร์ ซึ่งหมายความว่า "ประกาศ" ที่ใช้ในตัวอย่างจะถูกระงับ (ซ่อนไว้) ในขณะที่ข้อผิดพลาดอื่น ๆ ซึ่งถือว่าสำคัญกว่าจะแสดง / บันทึก
การตั้งค่าที่สำคัญอื่น ๆ คือข้อผิดพลาดที่สามารถซ่อนได้ (เช่นdisplay_errors
ตั้งค่าเป็น "ปิด" หรือ "syslog")
สิ่งที่จะเกิดขึ้นในกรณีนี้คือมีการerror_reporting
เปลี่ยนแปลงเพื่อแสดงการแจ้งเตือนด้วย (ตามตัวอย่าง) และ / หรือการตั้งค่าถูกเปลี่ยนเป็นdisplay_errors
บนหน้าจอ (ตรงข้ามกับการระงับ / บันทึก)
ทำไมพวกเขาถึงเปลี่ยนไป?
คำตอบที่ชัดเจน / ง่ายที่สุดคือมีคนปรับการตั้งค่าเหล่านี้ใน php.ini หรือ PHP เวอร์ชันอัปเกรดตอนนี้ใช้ php.ini ที่แตกต่างจากเมื่อก่อน นั่นคือที่แรกที่มอง
อย่างไรก็ตามคุณสามารถลบล้างการตั้งค่าเหล่านี้ในไฟล์
- .htconf (การกำหนดค่าเว็บเซิร์ฟเวอร์รวมถึง vhosts และการกำหนดค่าย่อย) *
- .htaccess
- ในโค้ด php เอง
และสิ่งเหล่านี้อาจเปลี่ยนแปลงได้
นอกจากนี้ยังมีความซับซ้อนเพิ่มเติมที่การกำหนดค่าเว็บเซิร์ฟเวอร์สามารถเปิด / ปิดคำสั่ง. htaccess ได้ดังนั้นหากคุณมีคำสั่งใน. htaccess ที่เริ่ม / หยุดทำงานกะทันหันคุณต้องตรวจสอบสิ่งนั้น
(.htconf / .htaccess สมมติว่าคุณกำลังเรียกใช้เป็น apache หากเรียกใช้บรรทัดคำสั่งจะไม่มีผลหากใช้ IIS หรือเว็บเซิร์ฟเวอร์อื่นคุณจะต้องตรวจสอบการกำหนดค่าเหล่านั้นตามนั้น)
สรุป
- คำสั่งตรวจสอบ
error_reporting
และdisplay_errors
php ใน php.ini ไม่มีการเปลี่ยนแปลงหรือคุณไม่ได้ใช้ php.ini ที่แตกต่างจากเมื่อก่อน - คำสั่งตรวจสอบ
error_reporting
และdisplay_errors
php ใน. htconf (หรือ vhosts ฯลฯ ) ไม่มีการเปลี่ยนแปลง - คำสั่งcheck
error_reporting
และdisplay_errors
php ใน. htaccess ไม่มีการเปลี่ยนแปลง - หากคุณมีคำสั่งใน. htaccess ให้ตรวจสอบว่ายังได้รับอนุญาตในไฟล์. htconf หรือไม่
- สุดท้ายตรวจสอบรหัสของคุณ อาจเป็นห้องสมุดที่ไม่เกี่ยวข้อง เพื่อดูว่า
error_reporting
และdisplay_errors
PHP คำสั่งที่ได้รับการตั้งอยู่ที่นั่น
การแก้ไขด่วนคือการกำหนดตัวแปรของคุณให้เป็นโมฆะที่ด้านบนของโค้ดของคุณ
$user_location = null;
ฉันเคยสาปแช่งข้อผิดพลาดนี้ แต่การเตือนให้คุณหลีกเลี่ยงการป้อนข้อมูลของผู้ใช้อาจเป็นประโยชน์
ตัวอย่างเช่นหากคุณคิดว่านี่เป็นรหัสชวเลขที่ชาญฉลาด:
// Echo whatever the hell this is
<?=$_POST['something']?>
...คิดใหม่! ทางออกที่ดีกว่าคือ:
// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>
(ฉันใช้html()
ฟังก์ชันที่กำหนดเองเพื่อหลีกหนีอักขระระยะทางของคุณอาจแตกต่างกันไป)
ฉันใช้ฟังก์ชันที่เป็นประโยชน์ของตัวเองตลอดเวลาexst ()ซึ่งจะประกาศตัวแปรโดยอัตโนมัติ
รหัสของคุณจะเป็น -
$greeting = "Hello, ".exst($user_name, 'Visitor')." from ".exst($user_location); /** * Function exst() - Checks if the variable has been set * (copy/paste it in any place of your code) * * If the variable is set and not empty returns the variable (no transformation) * If the variable is not set or empty, returns the $default value
*
* @param mixed $var * @param mixed $default
*
* @return mixed
*/
function exst( & $var, $default = "")
{
$t = ""; if ( !isset($var) || !$var ) { if (isset($default) && $default != "") $t = $default; } else { $t = $var; } if (is_string($t)) $t = trim($t);
return $t;
}
ใน PHP 7.0 ตอนนี้สามารถใช้ Null coalescing operator ได้แล้ว:
echo "My index value is: " . ($my_array["my_index"] ?? '');
เท่ากับ:
echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');
PHP คู่มือ PHP 7.0.2
ในมากภาษาที่เรียบง่าย
ข้อผิดพลาดคือคุณกำลังใช้ตัวแปร$user_location
ที่คุณไม่ได้กำหนดไว้ก่อนหน้านี้และไม่มีค่าใด ๆ ดังนั้นฉันขอแนะนำให้คุณโปรดประกาศตัวแปรนี้ก่อน ใช้งานตัวอย่างเช่น:
$user_location = '';
หรือ
$user_location = 'Los Angles';
นี่คือความผิดพลาดที่พบบ่อยมากที่คุณสามารถ face.So ไม่ต้องกังวลเพียงแค่ประกาศตัวแปรและ เพลิดเพลินไปกับการเข้ารหัส
เหตุใดจึงเกิดขึ้น
เมื่อเวลาผ่านไป PHP กลายเป็นภาษาที่เน้นความปลอดภัยมากขึ้น การตั้งค่าที่เคยถูกปิดโดยค่าเริ่มต้นจะถูกเปิดโดยค่าเริ่มต้น ตัวอย่างที่สมบูรณ์แบบนี้อยู่E_STRICT
ซึ่งกลายเป็นที่เปิดโดยเริ่มต้น ณPHP 5.4.0
นอกจากนี้ตามเอกสารประกอบของ PHP โดยค่าเริ่มต้นE_NOTICE
จะปิดใช้งานใน php.ini เอกสาร PHP ขอแนะนำให้เปลี่ยนมันสำหรับแก้จุดบกพร่องเพื่อ อย่างไรก็ตามเมื่อฉันดาวน์โหลด PHP จากที่เก็บ Ubuntu และจาก Windows stack ของ BitNami ฉันเห็นอย่างอื่น
; Common Values:
; E_ALL (Show all errors, warnings and notices including coding standards.)
; E_ALL & ~E_NOTICE (Show all errors, except for notices)
; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.)
; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
สังเกตว่าerror_reporting
ถูกตั้งค่าเป็นมูลค่าการผลิตตามค่าเริ่มต้นไม่ใช่ค่า "ค่าเริ่มต้น" ตามค่าเริ่มต้น สิ่งนี้ค่อนข้างสับสนและไม่มีการบันทึกไว้นอก php.ini ดังนั้นฉันจึงไม่ได้ตรวจสอบความถูกต้องนี้กับการแจกแจงอื่น ๆ
อย่างไรก็ตามเพื่อตอบคำถามของคุณข้อผิดพลาดนี้จะปรากฏขึ้นในตอนนี้เมื่อไม่ปรากฏขึ้นมาก่อนเนื่องจาก:
คุณติดตั้ง PHP และตั้งค่าเริ่มต้นใหม่จะค่อนข้างเอกสารไม่ดี
E_NOTICE
แต่ไม่ได้ยกเว้นE_NOTICE
คำเตือนเช่นตัวแปรที่ไม่ได้กำหนดและดัชนีที่ไม่ได้กำหนดจะช่วยทำให้โค้ดของคุณสะอาดและปลอดภัยยิ่งขึ้น ฉันบอกคุณได้ว่าเมื่อหลายปีก่อนการE_NOTICE
เปิดใช้งานทำให้ฉันต้องประกาศตัวแปรของฉัน มันทำให้การเรียนรู้ C ง่ายขึ้นมากการไม่ประกาศตัวแปรนั้นยิ่งใหญ่กว่าความรำคาญ
ฉันจะทำอะไรได้บ้างเกี่ยวกับเรื่องนี้
ปิด
E_NOTICE
โดยการคัดลอก "ค่าเริ่มต้น"E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
และแทนที่ด้วยสิ่งที่ uncommentederror_reporting =
ขณะนี้หลังจากที่เท่ากับใน รีสตาร์ท Apache หรือ PHP หากใช้ CGI หรือ FPM ตรวจสอบว่าคุณกำลังแก้ไข php.ini "ถูกต้อง" อันที่ถูกต้องจะเป็น Apache ถ้าคุณใช้ PHP กับ Apache, fpm หรือ php-fpm ถ้าใช้ PHP-FPM, cgi ถ้าใช้ PHP-CGI เป็นต้นนี่ไม่ใช่วิธีที่แนะนำ แต่ถ้าคุณมีโค้ดดั้งเดิมที่จะ แก้ไขได้ยากมากดังนั้นอาจเป็นทางออกที่ดีที่สุดของคุณปิด
E_NOTICE
ระดับไฟล์หรือโฟลเดอร์ วิธีนี้อาจดีกว่าหากคุณมีรหัสเดิม แต่ต้องการทำสิ่งที่ "ถูกต้อง" เป็นอย่างอื่น ในการดำเนินการนี้คุณควรปรึกษา Apache2, Nginx หรือเซิร์ฟเวอร์ที่คุณเลือก ใน Apache คุณจะใช้php_value
ภายใน<Directory>
ไฟล์.เขียนโค้ดใหม่ให้สะอาดขึ้น หากคุณจำเป็นต้องดำเนินการนี้ในขณะที่ย้ายไปยังสภาพแวดล้อมการใช้งานจริงหรือไม่ต้องการให้ใครบางคนเห็นข้อผิดพลาดของคุณตรวจสอบให้แน่ใจว่าคุณได้ปิดการแสดงข้อผิดพลาดใด ๆ และบันทึกเฉพาะข้อผิดพลาดของคุณเท่านั้น(ดู
display_errors
และlog_errors
ใน php.ini และการตั้งค่าเซิร์ฟเวอร์ของคุณ) .
หากต้องการขยายตัวเลือกที่ 3: นี่คืออุดมคติ ถ้าคุณสามารถไปเส้นทางนี้คุณควร หากคุณไม่ได้ไปเส้นทางนี้ในตอนแรกให้พิจารณาย้ายเส้นทางนี้ในที่สุดโดยทดสอบโค้ดของคุณในสภาพแวดล้อมการพัฒนา ในขณะที่คุณทำอยู่ให้กำจัด~E_STRICT
และ~E_DEPRECATED
ดูสิ่งที่อาจผิดพลาดในอนาคต คุณจะเห็นข้อผิดพลาดที่ไม่คุ้นเคยมากมาย แต่มันจะหยุดคุณจากปัญหาที่ไม่พึงประสงค์เมื่อคุณต้องการอัปเกรด PHP ในอนาคต
ข้อผิดพลาดหมายถึงอะไร?
Undefined variable: my_variable_name
- สิ่งนี้เกิดขึ้นเมื่อไม่ได้กำหนดตัวแปรก่อนใช้งาน เมื่อสคริปต์ PHP ถูกเรียกใช้งานภายในจะถือว่าเป็นค่าว่าง อย่างไรก็ตามคุณต้องตรวจสอบตัวแปรก่อนกำหนดในสถานการณ์ใด ท้ายที่สุดนี่เป็นข้อโต้แย้งสำหรับ "โค้ดที่ไม่สมบูรณ์" ในฐานะนักพัฒนาฉันสามารถบอกคุณได้ว่าฉันชอบมากเมื่อได้เห็นโครงการโอเพนซอร์สที่มีการกำหนดตัวแปรไว้ในขอบเขตที่สูงที่สุดเท่าที่จะกำหนดได้ ช่วยให้บอกได้ง่ายขึ้นว่าตัวแปรใดจะปรากฏขึ้นในอนาคตและช่วยให้อ่าน / เรียนรู้โค้ดได้ง่ายขึ้น
function foo()
{
$my_variable_name = ''; //.... if ($my_variable_name) {
// perform some logic
}
}
Undefined index: my_index
- เกิดขึ้นเมื่อคุณพยายามเข้าถึงค่าในอาร์เรย์และไม่มีอยู่ เพื่อป้องกันข้อผิดพลาดนี้ให้ทำการตรวจสอบตามเงื่อนไข
// verbose way - generally better
if (isset($my_array['my_index'])) { echo "My index value is: " . $my_array['my_index'];
}
// non-verbose ternary example - I use this sometimes for small rules.
$my_index_val = isset($my_array['my_index'])?$my_array['my_index']:'(undefined)'; echo "My index value is: " . $my_index_val;
อีกทางเลือกหนึ่งคือการประกาศอาร์เรย์ว่างที่ด้านบนสุดของฟังก์ชันของคุณ นี่เป็นไปไม่ได้เสมอไป
$my_array = array( 'my_index' => '' ); //... $my_array['my_index'] = 'new string';
(เคล็ดลับเพิ่มเติม)
- เมื่อฉันพบปัญหาเหล่านี้และปัญหาอื่น ๆ ฉันใช้NetBeans IDE (ฟรี) และให้คำเตือนและประกาศต่างๆแก่ฉัน บางคนมีคำแนะนำที่เป็นประโยชน์มาก นี่ไม่ใช่ข้อกำหนดและฉันไม่ใช้ IDE อีกต่อไปยกเว้นโครงการขนาดใหญ่
vim
วันนี้ฉันเป็นคนมากขึ้น:)
ทำไมไม่ทำอะไรง่ายๆ
<?php
error_reporting(E_ALL); // making sure all notices are on
function idxVal(&$var, $default = null) {
return empty($var) ? $var = $default : $var;
}
echo idxVal($arr['test']); // returns null without any notice echo idxVal($arr['hey ho'], 'yo'); // returns yo and assigns it to array index, nice
?>
ดัชนีที่ไม่ได้กำหนดหมายถึงในอาร์เรย์ที่คุณร้องขอสำหรับดัชนีอาร์เรย์ที่ไม่พร้อมใช้งานเช่น
<?php
$newArray[] = {1,2,3,4,5}; print_r($newArray[5]);
?>
ตัวแปรที่ไม่ได้กำหนดหมายถึงคุณได้ใช้ตัวแปรที่ไม่มีอยู่อย่างสมบูรณ์หรือไม่ได้กำหนดหรือเริ่มต้นด้วยชื่อนั้นเป็นต้น
<?php print_r($myvar); ?>
ออฟเซ็ตที่ไม่ได้กำหนดหมายถึงในอาร์เรย์ที่คุณขอคีย์ที่ไม่มีอยู่ และวิธีแก้ไขคือตรวจสอบก่อนใช้งาน
php> echo array_key_exists(1, $myarray);
เกี่ยวกับส่วนนี้ของคำถาม:
ทำไมพวกเขาถึงปรากฏขึ้นในทันที? ฉันเคยใช้สคริปต์นี้เป็นเวลาหลายปีและไม่เคยมีปัญหาใด ๆ
ไม่มีคำตอบที่ชัดเจน แต่ต่อไปนี้เป็นคำอธิบายที่เป็นไปได้บางส่วนว่าเหตุใดการตั้งค่าจึงสามารถเปลี่ยนแปลงได้
คุณได้อัปเกรด PHP เป็นเวอร์ชันที่ใหม่กว่าซึ่งสามารถมีค่าเริ่มต้นอื่น ๆ สำหรับ error_reporting, display_errors หรือการตั้งค่าอื่น ๆ ที่เกี่ยวข้อง
คุณได้ลบหรือแนะนำโค้ดบางส่วน (อาจอยู่ในการอ้างอิง) ที่ตั้งค่าการตั้งค่าที่เกี่ยวข้องในรันไทม์โดยใช้
ini_set()
หรือerror_reporting()
(ค้นหาสิ่งเหล่านี้ในโค้ด)คุณเปลี่ยนการกำหนดค่าเว็บเซิร์ฟเวอร์ (สมมติว่ามี apache ที่นี่):
.htaccess
ไฟล์และการกำหนดค่า vhost สามารถจัดการการตั้งค่า php ได้โดยปกติแล้วการแจ้งเตือนจะไม่แสดง / รายงาน (ดูคู่มือ PHP ) ดังนั้นจึงเป็นไปได้ว่าเมื่อตั้งค่าเซิร์ฟเวอร์ไฟล์ php.ini ไม่สามารถโหลดได้ด้วยเหตุผลบางประการ (การอนุญาตไฟล์ ??) และคุณใช้การตั้งค่าเริ่มต้น . ต่อมา 'ข้อผิดพลาด' ได้รับการแก้ไขแล้ว (โดยไม่ได้ตั้งใจ) และตอนนี้สามารถโหลดไฟล์ php.ini ที่ถูกต้องพร้อมชุด error_reporting เพื่อแสดงการแจ้งเตือน
การใช้ternaryนั้นง่ายอ่านง่ายและสะอาด:
Pre PHP 7
กำหนดตัวแปรให้กับค่าของตัวแปรอื่นหากมีการตั้งค่าอื่นกำหนดnull
(หรือค่าเริ่มต้นที่คุณต้องการ):
$newVariable = isset($thePotentialData) ? $thePotentialData : null;
PHP 7+
เดียวกันยกเว้นใช้Null หลอมรวมผู้ประกอบการ ไม่จำเป็นต้องเรียกอีกต่อไปisset()
เนื่องจากสิ่งนี้มีอยู่แล้วและไม่จำเป็นต้องระบุตัวแปรเพื่อส่งคืนเนื่องจากถือว่าส่งคืนค่าของตัวแปรที่กำลังตรวจสอบ:
$newVariable = $thePotentialData ?? null;
ทั้งสองจะหยุดการแจ้งเตือนจากคำถาม OP และทั้งคู่เทียบเท่ากันทุกประการของ:
if (isset($thePotentialData)) {
$newVariable = $thePotentialData;
} else {
$newVariable = null;
}
หากคุณไม่ต้องการตั้งค่าตัวแปรใหม่คุณสามารถใช้ค่าที่ส่งคืนของ ternary ได้โดยตรงเช่น with echo
, function arguments เป็นต้น:
เสียงสะท้อน:
echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';
ฟังก์ชัน:
$foreName = getForeName(isset($userId) ? $userId : null);
function getForeName($userId) { if ($userId === null) {
// Etc
}
}
ข้างต้นจะทำงานเหมือนกันกับอาร์เรย์รวมถึงเซสชันและอื่น ๆ แทนที่ตัวแปรที่กำลังตรวจสอบเช่น:
$_SESSION['checkMe']
หรือกี่ระดับที่คุณต้องการเช่น:
$clients['personal']['address']['postcode']
การปราบปราม:
เป็นไปได้ที่จะระงับการแจ้งเตือน PHP ด้วย@
หรือลดระดับการรายงานข้อผิดพลาดของคุณ แต่ไม่สามารถแก้ไขปัญหาได้เพียงแค่หยุดการรายงานในบันทึกข้อผิดพลาด ซึ่งหมายความว่าโค้ดของคุณยังคงพยายามใช้ตัวแปรที่ไม่ได้ตั้งค่าซึ่งอาจหมายความว่าบางอย่างไม่ทำงานตามที่ตั้งใจไว้หรือไม่ก็ได้ขึ้นอยู่กับว่าค่าที่ขาดหายไปนั้นสำคัญเพียงใด
คุณควรตรวจสอบปัญหานี้และจัดการอย่างเหมาะสมไม่ว่าจะเป็นการแสดงข้อความอื่นหรือแม้แต่ส่งคืนค่าว่างสำหรับทุกอย่างเพื่อระบุสถานะที่แม่นยำ
หากคุณสนใจแค่ว่าการแจ้งเตือนไม่ได้อยู่ในบันทึกข้อผิดพลาดคุณสามารถละเว้นบันทึกข้อผิดพลาดได้ในฐานะตัวเลือกหนึ่ง
หากทำงานกับคลาสคุณต้องแน่ใจว่าคุณอ้างอิงตัวแปรสมาชิกโดยใช้$this
:
class Person
{
protected $firstName;
protected $lastName; public function setFullName($first, $last) { // Correct $this->firstName = $first; // Incorrect $lastName = $last; // Incorrect $this->$lastName = $last;
}
}
อีกสาเหตุหนึ่งที่จะมีการแจ้งดัชนีที่ไม่ได้กำหนดก็คือคอลัมน์ถูกละเว้นจากการสืบค้นฐานข้อมูล
ได้แก่ :
$query = "SELECT col1 FROM table WHERE col_x = ?";
จากนั้นพยายามเข้าถึงคอลัมน์ / แถวเพิ่มเติมภายในลูป
ได้แก่ :
print_r($row['col1']);
print_r($row['col2']); // undefined index thrown
หรือwhile
วนซ้ำ:
while( $row = fetching_function($query) ) { echo $row['col1'];
echo "<br>";
echo $row['col2']; // undefined index thrown echo "<br>"; echo $row['col3']; // undefined index thrown
}
สิ่งอื่นที่ต้องสังเกตก็คือใน * NIX OS และ Mac OS X สิ่งต่างๆจะคำนึงถึงตัวพิมพ์เล็กและใหญ่
ดูคำถามและคำตอบต่อไปนี้ใน Stack:
ชื่อตารางใน MySQL case มีความละเอียดอ่อนหรือไม่
mysql ชื่อตารางที่คำนึงถึงตัวพิมพ์เล็กและใหญ่ในแบบสอบถาม
MySql - ปัญหาของตารางในเซิร์ฟเวอร์ที่แตกต่างกัน
ข้อผิดพลาดเหล่านี้เกิดขึ้นเมื่อใดก็ตามที่เราใช้ตัวแปรที่ไม่ได้ตั้งค่า
วิธีที่ดีที่สุดในการจัดการกับสิ่งเหล่านี้คือตั้งค่าการรายงานข้อผิดพลาดในขณะพัฒนา
ในการตั้งค่าการรายงานข้อผิดพลาดใน:
ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');
error_reporting(E_ALL);
บนเซิร์ฟเวอร์ที่ใช้งานจริงการรายงานข้อผิดพลาดจะปิดอยู่ดังนั้นเราจึงไม่ได้รับข้อผิดพลาดเหล่านี้
อย่างไรก็ตามบนเซิร์ฟเวอร์การพัฒนาเราสามารถตั้งค่าการรายงานข้อผิดพลาดได้
เพื่อกำจัดข้อผิดพลาดนี้เราเห็นตัวอย่างต่อไปนี้:
if ($my == 9) { $test = 'yes'; // Will produce error as $my is not 9. } echo $test;
เราสามารถNULL
กำหนดค่าเริ่มต้นให้กับตัวแปรก่อนกำหนดค่าหรือใช้งานได้
ดังนั้นเราสามารถแก้ไขรหัสเป็น:
$test = NULL; if ($my == 9) {
$test = 'yes'; // Will produce error as $my is not 9.
}
echo $test;
สิ่งนี้จะไม่รบกวนตรรกะของโปรแกรมใด ๆ และจะไม่แสดงการแจ้งเตือนแม้ว่า$test
จะไม่มีค่าก็ตาม
ดังนั้นโดยพื้นฐานแล้วการตั้งค่าการรายงานข้อผิดพลาดสำหรับการพัฒนาจะดีกว่าเสมอ
และแก้ไขข้อผิดพลาดทั้งหมด
และในการผลิตควรตั้งค่าการรายงานข้อผิดพลาดเป็นปิด
สาเหตุทั่วไปอย่างหนึ่งของตัวแปรที่ไม่มีอยู่หลังจากส่งแบบฟอร์มHTMLแล้วคือองค์ประกอบแบบฟอร์มไม่มีอยู่ใน<form>
แท็ก:
ตัวอย่าง: องค์ประกอบที่ไม่มีอยู่ในไฟล์ <form>
<form action="example.php" method="post">
<p>
<input type="text" name="name" />
<input type="submit" value="Submit" />
</p>
</form>
<select name="choice">
<option value="choice1">choice 1</option>
<option value="choice2">choice 2</option>
<option value="choice3">choice 3</option>
<option value="choice4">choice 4</option>
</select>
ตัวอย่าง: องค์ประกอบที่มีอยู่ในไฟล์ <form>
<form action="example.php" method="post">
<select name="choice">
<option value="choice1">choice 1</option>
<option value="choice2">choice 2</option>
<option value="choice3">choice 3</option>
<option value="choice4">choice 4</option>
</select>
<p>
<input type="text" name="name" />
<input type="submit" value="Submit" />
</p>
</form>
อาจเป็นไปได้ว่าคุณใช้ PHP เวอร์ชันเก่าจนถึงตอนนี้และอัปเกรด PHP แล้วนั่นคือเหตุผลที่มันใช้งานได้โดยไม่มีข้อผิดพลาดใด ๆ จนถึงปัจจุบันนับจากปี จนกว่า PHP4 จะไม่มีข้อผิดพลาดหากคุณใช้ตัวแปรโดยไม่ได้กำหนด แต่ตั้งแต่ PHP5 เป็นต้นไปจะมีข้อผิดพลาดสำหรับรหัสดังที่กล่าวถึงในคำถาม
ฉันถามคำถามเกี่ยวกับเรื่องนี้และฉันถูกส่งถึงโพสต์นี้พร้อมข้อความ:
คำถามนี้มีคำตอบอยู่แล้วที่นี่:
“ ข้อสังเกต: ตัวแปรที่ไม่ได้กำหนด”,“ ข้อสังเกต: ดัชนีที่ไม่ได้กำหนด” และ“ ข้อสังเกต: ออฟเซ็ตที่ไม่ได้กำหนด” โดยใช้ PHP
ฉันกำลังแบ่งปันคำถามและวิธีแก้ปัญหาที่นี่:
นี่คือข้อผิดพลาด:
บรรทัด 154 คือปัญหา นี่คือสิ่งที่ฉันมีในบรรทัด 154:
153 foreach($cities as $key => $city){ 154 if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){
ฉันคิดว่าปัญหาคือฉันกำลังเขียน if เงื่อนไขสำหรับตัวแปร$city
ซึ่งไม่ใช่คีย์ แต่เป็นค่าใน$key => $city
. ขั้นแรกคุณสามารถยืนยันได้หรือไม่ว่านั่นคือสาเหตุของคำเตือนนี้ ประการที่สองถ้าเป็นปัญหาทำไมฉันจึงไม่สามารถเขียนเงื่อนไขตามค่าได้ ต้องมีคีย์ที่ต้องเขียนเงื่อนไขหรือไม่?
อัปเดต 1: ปัญหาคือเมื่อดำเนินการ$citiesCounterArray[$key]
บางครั้ง$key
คีย์จะตรงกับคีย์ที่ไม่มีอยู่ใน$citiesCounterArray
อาร์เรย์ แต่นั่นไม่ใช่กรณีเสมอไปตามข้อมูลของลูปของฉัน สิ่งที่ฉันต้องการคือการตั้งเงื่อนไขเพื่อที่ว่าหาก$key
มีอยู่ในอาร์เรย์ให้รันโค้ดมิฉะนั้นให้ข้ามไป
อัปเดต 2: นี่คือวิธีที่ฉันแก้ไขโดยใช้array_key_exists()
:
foreach($cities as $key => $city){
if(array_key_exists($key, $citiesCounterArray)){
if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){