function foo () {
global $var;
// rest of code
}
ในโครงการ PHP ขนาดเล็กของฉันฉันมักจะทำตามขั้นตอน ฉันมักจะมีตัวแปรที่มีการกำหนดค่าระบบและเมื่อฉัน Nead global $var;
เข้าถึงตัวแปรนี้ในการทำงานที่ผมทำ
การปฏิบัติที่ไม่ดีนี้หรือไม่?
function foo () {
global $var;
// rest of code
}
ในโครงการ PHP ขนาดเล็กของฉันฉันมักจะทำตามขั้นตอน ฉันมักจะมีตัวแปรที่มีการกำหนดค่าระบบและเมื่อฉัน Nead global $var;
เข้าถึงตัวแปรนี้ในการทำงานที่ผมทำ
การปฏิบัติที่ไม่ดีนี้หรือไม่?
คำตอบ:
เมื่อผู้คนพูดถึงตัวแปรทั่วโลกในภาษาอื่น ๆ มันหมายถึงสิ่งที่แตกต่างจากสิ่งที่ทำใน PHP นั่นเป็นเพราะตัวแปรไม่ได้จริงๆสากลใน PHP ขอบเขตของโปรแกรม PHP ทั่วไปคือคำขอ HTTP หนึ่งรายการ ตัวแปรเซสชันมีขอบเขตกว้างกว่าตัวแปร "global" ของ PHP เนื่องจากโดยทั่วไปแล้วตัวแปรเหล่านี้จะครอบคลุมคำขอ HTTP จำนวนมาก
บ่อยครั้ง (เสมอ?) คุณสามารถเรียกใช้ฟังก์ชันสมาชิกด้วยวิธีpreg_replace_callback()
การดังนี้:
preg_replace_callback('!pattern!', array($obj, 'method'), $str);
ดูการโทรกลับสำหรับข้อมูลเพิ่มเติม
ประเด็นคือวัตถุถูกยึดเข้ากับ PHP และในบางวิธีทำให้เกิดความอึดอัด
อย่ากังวลกับตัวเองมากเกินไปกับการนำมาตรฐานหรือโครงสร้างจากภาษาต่างๆไปใช้กับ PHP ข้อผิดพลาดที่พบบ่อยอีกประการหนึ่งคือการพยายามเปลี่ยน PHP ให้เป็นภาษา OOP ที่บริสุทธิ์โดยยึดโมเดลวัตถุไว้ด้านบนของทุกสิ่ง
เช่นเดียวกับสิ่งอื่น ๆ ให้ใช้ตัวแปร "global" รหัสขั้นตอนกรอบงานเฉพาะและ OOP เพราะมันสมเหตุสมผลแก้ปัญหาลดจำนวนรหัสที่คุณต้องเขียนหรือทำให้บำรุงรักษาได้มากขึ้นและเข้าใจง่ายขึ้นไม่ใช่เพราะคุณคิดว่า คุณควร.
array ($obj, 'callbackMethod')
ในการโทรได้preg_replace_callback()
หรือไม่ (ฉันรู้ฉันตกเป็นเหยื่อของข้อผิดพลาด OOP นี้ ... )
ตัวแปรส่วนกลางหากไม่ใช้อย่างระมัดระวังอาจทำให้พบปัญหาได้ยากขึ้น สมมติว่าคุณขอสคริปต์ php และคุณได้รับคำเตือนว่าคุณกำลังพยายามเข้าถึงดัชนีของอาร์เรย์ที่ไม่มีอยู่ในบางฟังก์ชัน
หากอาร์เรย์ที่คุณพยายามเข้าถึงเป็นฟังก์ชันเฉพาะที่คุณตรวจสอบฟังก์ชันเพื่อดูว่าคุณทำผิดพลาดหรือไม่ อาจมีปัญหากับอินพุตของฟังก์ชันดังนั้นคุณจึงตรวจสอบตำแหน่งที่ฟังก์ชันถูกเรียกใช้
แต่ถ้าอาร์เรย์นั้นเป็นแบบโกลบอลคุณต้องตรวจสอบตำแหน่งทั้งหมดที่คุณใช้ตัวแปรโกลบอลนั้นและไม่เพียงแค่นั้นคุณต้องเข้าใจว่าการอ้างอิงเหล่านั้นไปยังตัวแปรโกลบอลนั้นเป็นลำดับใด
หากคุณมีตัวแปรส่วนกลางในโค้ดส่วนหนึ่งจะทำให้ยากที่จะแยกการทำงานของโค้ดนั้น ทำไมคุณถึงต้องการแยกฟังก์ชันการทำงาน? ดังนั้นคุณสามารถทดสอบและใช้ซ้ำที่อื่นได้ หากคุณมีรหัสบางอย่างคุณไม่จำเป็นต้องทดสอบและไม่จำเป็นต้องใช้ซ้ำการใช้ตัวแปรส่วนกลางก็ใช้ได้
ฉันเห็นด้วยกับ cletus ฉันจะเพิ่มสองสิ่ง:
ขอแสดงความนับถือดอน
$DB = 'foo';
ใครสามารถโต้แย้งเกี่ยวกับประสบการณ์การศึกษาระดับวิทยาลัยและวิศวกรรมซอฟต์แวร์ได้ ไม่ใช่ฉัน. ฉันจะบอกแค่ว่าในการพัฒนาแอปพลิเคชั่น PHP แบบหน้าเดียวแบบเชิงวัตถุฉันสนุกมากขึ้นเมื่อฉันรู้ว่าฉันสามารถสร้างสิ่งทั้งหมดตั้งแต่เริ่มต้นโดยไม่ต้องกังวลเกี่ยวกับการชนกันของเนมสเปซ การสร้างจากศูนย์เป็นสิ่งที่หลายคนไม่ทำอีกต่อไป พวกเขามีงานกำหนดเวลาโบนัสหรือชื่อเสียงที่ต้องดูแล ประเภทเหล่านี้มักจะใช้โค้ดที่สร้างไว้ล่วงหน้าและมีเดิมพันสูงมากจนไม่สามารถเสี่ยงต่อการใช้ตัวแปรส่วนกลางได้เลย
การใช้ตัวแปรส่วนกลางอาจเป็นเรื่องไม่ดีแม้ว่าจะใช้เฉพาะในพื้นที่ทั่วโลกของโปรแกรม แต่อย่าลืมเกี่ยวกับผู้ที่ต้องการสนุกและทำบางสิ่งให้สำเร็จ
หากนั่นหมายถึงการใช้ตัวแปรสองสามตัว (<10) ในเนมสเปซส่วนกลางนั่นจะถูกใช้ในพื้นที่ส่วนกลางของโปรแกรมเท่านั้นดังนั้นไม่ว่าจะเป็น ใช่ใช่ MVC การฉีดพึ่งพารหัสภายนอก blah blah blah blah แต่ถ้าคุณมีโค้ด 99.99% ในเนมสเปซและคลาสและโค้ดภายนอกเป็นแซนด์บ็อกซ์โลกจะไม่สิ้นสุด (ขอย้ำโลกจะไม่จบ) หากคุณใช้ตัวแปรส่วนกลาง
โดยทั่วไปผมจะไม่บอกว่าใช้ตัวแปรทั่วโลกมีการปฏิบัติที่ไม่ดี ฉันจะบอกว่าการใช้ตัวแปรส่วนกลาง (แฟล็กและอื่น ๆ ) นอกพื้นที่ทั่วโลกของโปรแกรมกำลังขอปัญหาและ (ในระยะยาว) ไม่ได้รับคำแนะนำเพราะคุณสามารถสูญเสียการติดตามสถานะของพวกเขาได้ค่อนข้างง่าย นอกจากนี้ฉันจะบอกว่ายิ่งคุณเรียนรู้มากเท่าไหร่คุณก็จะยิ่งพึ่งพาตัวแปรระดับโลกน้อยลงเท่านั้นเพราะคุณจะได้สัมผัสกับ "ความสุข" ในการติดตามจุดบกพร่องที่เกี่ยวข้องกับการใช้งาน สิ่งนี้เพียงอย่างเดียวจะกระตุ้นให้คุณหาวิธีอื่นในการแก้ปัญหาเดียวกัน บังเอิญสิ่งนี้มีแนวโน้มที่จะผลักดันคน PHP ไปในทิศทางของการเรียนรู้วิธีใช้เนมสเปซและคลาส (สมาชิกแบบคงที่ ฯลฯ ... )
สาขาวิทยาการคอมพิวเตอร์มีมากมาย หากเราทำให้ทุกคนกลัวไม่ให้ทำอะไรบางอย่างเพราะเราติดป้ายว่ามันไม่ดีพวกเขาก็หมดความสนุกในการทำความเข้าใจเหตุผลเบื้องหลังฉลากอย่างแท้จริง
ใช้ตัวแปรส่วนกลางหากคุณต้องการ แต่ดูว่าคุณสามารถแก้ปัญหาได้หากไม่มีตัวแปรเหล่านี้ การชนการทดสอบและการดีบักมีความหมายมากขึ้นเมื่อคุณเข้าใจธรรมชาติที่แท้จริงของปัญหาอย่างใกล้ชิดไม่ใช่แค่คำอธิบายของปัญหาเท่านั้น
โพสต์ใหม่จาก SO Documentation Beta ที่สิ้นสุดแล้ว
เราสามารถอธิบายปัญหานี้ด้วยรหัสหลอกต่อไปนี้
function foo() {
global $bob;
$bob->doSomething();
}
คำถามแรกของคุณนี่เป็นคำถามที่ชัดเจน
ในกรณีที่ไม่
$bob
มาจากไหน?
คุณสับสนไหม? ดี. คุณเพิ่งได้เรียนรู้ว่าเหตุใดคนทั่วโลกจึงสับสนและถือเป็นการปฏิบัติที่ไม่ดี หากนี่เป็นโปรแกรมจริงความสนุกถัดไปของคุณคือการติดตามทุกกรณี$bob
และหวังว่าคุณจะพบสิ่งที่ใช่ (จะแย่ลงถ้า$bob
ใช้ทุกที่) แย่กว่านั้นถ้ามีคนอื่นไปกำหนด$bob
(หรือคุณลืมและใช้ตัวแปรนั้นซ้ำ) โค้ดของคุณอาจพังได้ (ในตัวอย่างโค้ดด้านบนการมีอ็อบเจ็กต์ที่ไม่ถูกต้องหรือไม่มีอ็อบเจ็กต์เลยจะทำให้เกิดข้อผิดพลาดร้ายแรง) เนื่องจากโปรแกรม PHP เกือบทั้งหมดใช้ประโยชน์จากรหัสเช่นinclude('file.php');
งานของคุณที่ดูแลรหัสเช่นนี้จะยากขึ้นเรื่อย ๆ เมื่อคุณเพิ่มไฟล์มากขึ้น
เราจะหลีกเลี่ยง Globals ได้อย่างไร?
วิธีที่ดีที่สุดเพื่อหลีกเลี่ยงการ Globals คือปรัชญาที่เรียกว่าการพึ่งพาการฉีด นี่คือที่ที่เราส่งผ่านเครื่องมือที่เราต้องการไปยังฟังก์ชันหรือคลาส
function foo(\Bar $bob) {
$bob->doSomething();
}
สิ่งนี้ง่ายกว่ามากในการทำความเข้าใจและดูแลรักษา ไม่มีการคาดเดาว่า$bob
ถูกตั้งค่าไว้ที่ใดเนื่องจากผู้โทรมีหน้าที่รับรู้สิ่งนั้น (กำลังส่งผ่านสิ่งที่เราต้องรู้) ยังดีกว่าเราสามารถใช้การประกาศประเภทเพื่อ จำกัด สิ่งที่กำลังส่งผ่าน ดังนั้นเราจึงรู้ว่านั่น$bob
เป็นตัวอย่างของBar
คลาสหรือตัวอย่างของเด็กBar
ซึ่งหมายความว่าเรารู้ว่าเราสามารถใช้วิธีการของคลาสนั้นได้ เมื่อรวมกับตัวโหลดอัตโนมัติมาตรฐาน (พร้อมใช้งานตั้งแต่ PHP 5.3) ตอนนี้เราสามารถติดตามตำแหน่งที่Bar
กำหนดไว้ได้ PHP 7.0 หรือใหม่กว่ามีการประกาศประเภทขยายซึ่งคุณสามารถใช้ประเภทสเกลาร์ (เช่นint
หรือstring
) ได้
$bob = Bar::instance();
ทุกเมื่อที่ต้องการ
เช่น:
global $my_global;
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']
เป็นการปฏิบัติที่ไม่ดี (เช่น Wordpress $pagenow
) ... อืม
พิจารณาสิ่งนี้:
$my-global = 'Transport me between functions';
เป็นข้อผิดพลาดของ PHPแต่:
$GLOBALS['my-global'] = 'Transport me between functions';
คือไม่ผิดพลาดhypens จะไม่ปะทะกับ "คนธรรมดา" $pagenow
ผู้ใช้ประกาศตัวแปรเช่น และการใช้ UPPERCASE บ่งบอกถึงการใช้งานระดับซูเปอร์โกลบอลจุดรหัสง่ายหรือติดตามด้วยการค้นหาในไฟล์
ฉันใช้ยัติภังค์ถ้าฉันขี้เกียจสร้างคลาสทุกอย่างสำหรับโซลูชันเดียวเช่น:
$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';
แต่ในกรณีของการใช้งานที่กว้างขึ้นฉันใช้ONE globals เป็นอาร์เรย์:
$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';
ข้อหลังนี้เป็นแนวทางปฏิบัติที่ดีเกี่ยวกับวัตถุประสงค์หรือการใช้ "cola light" แทนที่จะยุ่งกับคลาสซิงเกิลทุกครั้งเพื่อ "แคช" ข้อมูลบางอย่าง โปรดแสดงความคิดเห็นหากฉันผิดพลาดหรือพลาดอะไรโง่ ๆ ที่นี่ ...