Buggy CakePHP Code: 6 ข้อผิดพลาดที่พบบ่อยที่สุดสำหรับนักพัฒนา CakePHP
เผยแพร่แล้ว: 2022-03-11CakePHP เป็นเฟรมเวิร์ก PHP ที่น่าทึ่ง แต่มีช่วงการเรียนรู้ที่สูงชัน! จำเป็นต้องมีการวิจัยและการฝึกอบรมเป็นจำนวนมากเพื่อที่จะเป็นผู้เชี่ยวชาญ
ฉันโชคดีที่ได้ใช้ CakePHP มานานกว่า 7 ปีแล้ว และในช่วงเวลานั้น ฉันได้รับเกียรติที่ได้ร่วมงานกับสมาชิกจำนวนมากในชุมชน CakePHP
ในบทช่วยสอน CakePHP นี้ ฉันต้องการอธิบายแนวทางปฏิบัติที่ไม่ดีสองสามอย่างที่ฉันได้เห็นในช่วงหลายปีที่ผ่านมา และเสนอแนวทางที่ถูกต้องเพื่อหลีกเลี่ยงข้อผิดพลาดเหล่านี้ นี่ไม่ได้หมายความว่าโค้ดของฉันสมบูรณ์แบบ แต่ในฐานะโปรแกรมเมอร์ เราเรียนรู้อยู่เสมอ ดังนั้นการปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดและปรับเปลี่ยนในขณะที่คุณเรียนรู้จึงเป็นสิ่งสำคัญ!
เนื้อหาของบทความนี้ได้รับแรงบันดาลใจจากโพสต์จาก CakeCoded หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ CakePHP โปรดไปที่ส่วนการเรียนรู้ของเราที่นี่
ข้อผิดพลาดทั่วไป #1: ไม่ปฏิบัติตามข้อตกลงการเข้ารหัส CakePHP
สามารถดูข้อตกลงการเข้ารหัส CakePHP ได้ที่นี่ ฉันจะเน้นบางสิ่งที่ฉันมักจะสังเกตเห็นเมื่อดูรหัสโปรแกรมเมอร์คนอื่น
โครงสร้างการควบคุม บ่อยครั้งที่คุณเห็นว่าโปรแกรมเมอร์เข้าใจผิด และในบางกรณีก็นำแนวทางปฏิบัติจากภาษาการเขียนโปรแกรมอื่นๆ CakePHP ต้องการไวยากรณ์ต่อไปนี้:
if ((expr_1) || (expr_2)) { // action_1; } elseif (!(expr_3) && (expr_4)) { // action_2; } else { // default_action; }
ควรมีช่องว่าง 1 (หนึ่ง) ก่อนวงเล็บแรกและ 1 (หนึ่ง) ช่องว่างระหว่างวงเล็บสุดท้ายกับวงเล็บเปิด นี่หมายความว่าสิ่งต่อไปนี้ไม่ถูกต้อง:
if($this->request->data){ }
สังเกตระยะห่างระหว่าง if
และ (
, และ between )
และ {
ใช้วงเล็บปีกกาในโครงสร้างการควบคุมเสมอ แม้ว่าจะไม่จำเป็นก็ตาม ช่วยเพิ่มความสามารถในการอ่านโค้ด และให้ข้อผิดพลาดเชิงตรรกะน้อยลง
ตัวอย่างเช่น สิ่งต่อไปนี้ไม่ถูกต้อง:
if ($foo) $bar = true
ควรจัดรูปแบบดังนี้:
if ($foo) { $bar = true }
สุดท้าย ดูตำแหน่งที่คุณวางวงเล็บ วงเล็บเปิดไม่ควรขึ้นบรรทัดใหม่ และตรวจสอบให้แน่ใจว่าวงเล็บทั้งหมดของคุณอยู่ในแนวเดียวกันเพื่อให้วงเล็บใหม่แต่ละอันอยู่ในแนวเดียวกับวงเล็บปิด
ต่อไปนี้คือตัวอย่างที่ไม่ถูกต้อง:
if ($foo) { $bar = true; }
ไม่ถูกต้อง วงเล็บเปิดควรอยู่ในบรรทัดแรก:
if ($foo) { $bar = true; if ($action) { $to = false; } }
การเยื้องต้องเข้าแถวอย่างถูกต้อง
ฉันมักจะได้ยินโปรแกรมเมอร์พูดว่า “แต่ฉันยุ่งเกินกว่าจะทำให้โค้ดเรียบร้อย….” คำตอบของฉันคือ "เชื่อฉันเถอะ โค้ดที่เรียบร้อยจะทนทานเหนือกาลเวลา" การเขียนโค้ด CakePHP ซึ่งอ่านไม่ได้จะเป็นฝันร้ายที่คุณจะต้องกลับมาอีก หากคุณจำเป็นต้องทำการเปลี่ยนแปลงในอีกไม่กี่เดือนข้างหน้า
ข้อผิดพลาดทั่วไป #2: การใช้พฤติกรรมที่มีอยู่อย่างไม่เหมาะสมและระดับแบบเรียกซ้ำใน ORM
เมื่อเร็ว ๆ นี้ฉันโชคดีที่ได้สนทนาอย่างไม่เป็นทางการกับผู้พัฒนาฐานข้อมูลจาก Facebook เราเริ่มพูดถึง CakePHP แล้วเขาก็บอกฉันว่า "โอ้ นั่นมันใช้ ORM ใช่ไหม? นั่นอาจเป็นเรื่องที่น่ากลัว” ฉันถามเขาว่าเขาหมายถึงอะไร และเขาให้ความเห็นว่าด้วย Object-relational mapping (ORM) ทำให้การสืบค้น SQL มีขนาดใหญ่เกินความจำเป็นได้ง่าย
เขาพูดถูกในทาง ส่วนหนึ่งของความมหัศจรรย์ของ CakePHP คือการใช้ ORM และวิธีที่มันจัดกลุ่มความสัมพันธ์ของตารางฐานข้อมูลต่างๆ เข้าด้วยกัน ตามค่าเริ่มต้น CakePHP จะเลือกข้อมูล 'เป็นของ', 'มีหนึ่ง' และ 'มีจำนวนมาก' ที่เกี่ยวข้องโดยอัตโนมัติ และสิ่งนี้สามารถนำไปสู่การสืบค้น SQL ที่มีขนาดใหญ่มาก ข้อความค้นหาเหล่านี้อาจไม่เป็นปัญหาเมื่อคุณเริ่มพัฒนาแอปพลิเคชัน แต่หลังจากหกเดือนของการรวบรวมข้อมูลสด คุณอาจพบว่าแอปพลิเคชันทำงานช้ามาก และในบางกรณีอาจหยุดทำงานหากการสืบค้นไม่ได้รับการปรับให้เหมาะสม
ฉันมองหาสองสิ่งเมื่อตรวจสอบเว็บไซต์ที่มีอยู่ ประการแรก ระดับการเรียกซ้ำเริ่มต้นมีการเปลี่ยนแปลงหรือไม่ โดยค่าเริ่มต้น CakePHP จะกำหนดระดับแบบเรียกซ้ำเป็น 1 ซึ่งในความคิดของฉันสูงเกินไป ฉันตั้งค่าเป็น -1 เสมอ จากนั้นจึงใช้พฤติกรรมที่ควบคุมได้เพื่อรับโมเดลที่เกี่ยวข้อง
นั่นนำไปสู่สิ่งที่สองที่ฉันมองหา - พฤติกรรมที่กักเก็บได้ถูกนำมาใช้หรือไม่? ฉันมักจะมีลูกค้าใหม่มาหาฉันและบอกว่า CakePHP ช้า เหตุผลเกือบทุกครั้งเพราะ Containable ยังไม่ได้ใช้งาน! โปรแกรมเมอร์ CakePHP ที่ดีจะเพิ่มประสิทธิภาพการสืบค้น SQL ของพวกเขาโดยไม่คำนึงว่าเบื้องหลัง “auto-magic” จะทำมากแค่ไหน
พฤติกรรมที่ควบคุมได้ไม่ได้ถูกเพิ่มจนกระทั่ง CakePHP 1.2 แต่เด็กผู้ชายมันสร้างความแตกต่างหรือไม่! อย่าลืมใช้ Containable มากที่สุด เนื่องจากเป็นวิธีที่มีประสิทธิภาพในการเพิ่มประสิทธิภาพ SQL ของคุณ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการปรับใช้และใช้งานลักษณะการทำงานที่บรรจุได้ คลิกที่นี่
ข้อผิดพลาดทั่วไป #3: การรักษาตรรกะทางธุรกิจไว้ในตัวควบคุมแทนที่จะเป็นแบบจำลอง
รหัส CakePHP ที่ดีจะมีตรรกะในไฟล์โมเดล นี้ต้องใช้เวลาเล็กน้อยในการทำความคุ้นเคย แต่เมื่อเข้าใจแล้วจะไม่มีการมองย้อนกลับไป! ไฟล์คอนโทรลเลอร์ควรใช้สำหรับสิ่งที่มีไว้สำหรับในรูปแบบ MVC - การควบคุม! ดังนั้น ใช้ไฟล์คอนโทรลเลอร์ของคุณเพื่อจัดการกับการกระทำของผู้ใช้ ในขณะที่ปล่อยให้ตรรกะทางธุรกิจไปอยู่ในไฟล์โมเดล
ตัวอย่างที่ดีของสิ่งนี้คือ CRUD ง่ายๆ - การกระทำในชีวิตประจำวัน! ลองใช้ฟังก์ชันเพิ่มบทความจากบทแนะนำบล็อกเป็นตัวอย่าง ฟังก์ชันเพิ่มเริ่มต้นจะเป็นดังนี้:
public function add() { if ($this->request->is('post')) { $this->Post->create(); if ($this->Post->save($this->request->data)) { $this->Session->setFlash(__('Your post has been saved.')); return $this->redirect(array('action' => 'index')); } $this->Session->setFlash(__('Unable to add your post.')); } }
การกระทำของตัวควบคุมนี้ใช้ได้สำหรับการเพิ่มแบบธรรมดา แต่จะเกิดอะไรขึ้นหากคุณต้องการทำสิ่งต่างๆ เช่น ส่งอีเมลถึงผู้ดูแลระบบเมื่อมีการเพิ่มโพสต์ หรืออัปเดตการเชื่อมโยงแบบจำลองอื่นเมื่อมีการเพิ่มโพสต์ นี่เป็นตรรกะเพิ่มเติม แต่ตรรกะนี้ไม่ควรเข้าไปในไฟล์คอนโทรลเลอร์ของเรา
เราจะเขียนฟังก์ชันนี้ในโมเดล Post.php
ของเราแทน บางทีสิ่งนี้:
public function addPost($data = array(), $emailAdmin = true) { $this->create(); $this->save($data); // update any other tables // send the email to the admin user if ($emailAdmin) { } // if all is successful return true; }
ซึ่งจะส่งผลให้เกิดการเปลี่ยนแปลงเล็กน้อยในการดำเนินการควบคุมดังนี้:

public function add() { if ($this->request->is('post')) { if ($this->Post->addPost($this->request->data)) { $this->Session->setFlash(__('Your post has been saved.')); return $this->redirect(array('action' => 'index')); } $this->Session->setFlash(__('Unable to add your post.')); } }
อย่างที่คุณเห็น การดำเนินการใหม่นี้จริง ๆ แล้วน้อยกว่าหนึ่งบรรทัด เนื่องจาก $this->Post->create()
ถูกย้ายไปยังไฟล์โมเดลแล้ว
นี่เป็นตัวอย่างที่สมบูรณ์แบบในชีวิตประจำวันของการย้ายตรรกะไปยังไฟล์โมเดลเป็นความคิดที่ดี - และแน่นอนว่าจะทำให้ฐานโค้ดสะอาดขึ้นมาก!
ข้อผิดพลาดทั่วไป #4: เพิ่มความซับซ้อนมากเกินไปให้กับรหัส แทนที่จะกลับมาบ่อยและเร็ว
นี่เป็นการถกเถียงอย่างต่อเนื่องอยู่เสมอ แต่การกลับมาบ่อย และการกลับมาก่อนกำหนดจะทำให้โค้ดดูสะอาดตาขึ้น สิ่งนี้ใช้กับวิธีการของแบบจำลองมากกว่าสิ่งอื่นใด
แต่ฉันหมายความว่าอย่างไร มาดูวิธีที่เราเพิ่มในบทช่วยสอน CakePHP ด้านบน:
public function addPost($data = array(), $emailAdmin = true) { $this->create(); $this->save($data); // update any other tables // send the email to the admin user if ($emailAdmin) { } // if all is successful return true; }
การกลับมาบ่อยๆ และการกลับมาก่อนกำหนดหมายความว่าเมื่อเราดำเนินการตามหน้าที่ของเรา เราจะตรวจสอบเพื่อให้แน่ใจว่าทุกอย่างเรียบร้อยเป็นประจำ หากไม่เป็นเช่นนั้น เราจะคืนค่าเท็จ หรือส่งคืนข้อผิดพลาด CakePHP
มันอาจจะง่ายที่สุดที่จะแสดงสิ่งนี้ด้วยตัวอย่าง มีสองวิธีในการเขียนฟังก์ชันข้างต้น:
public function addPost($data = array(), $emailAdmin = true) { if ($data) { $this->create(); $result = $this->save($data); if ($result) { // update any other tables // send the email to the admin user if ($emailAdmin) { // send the admin email } } else { // problem saving the data return false; } // if all is successful return true; } else { // no data submitted return false; } }
ดูว่าโค้ดอ่านไม่ได้อย่างรวดเร็วได้อย่างไร มีอยู่ทุก if
และฟังก์ชันจะกลายเป็นการเยื้องครั้งใหญ่ else
รวดเร็ว อย่าเข้าใจฉันผิด ฉันชอบการเยื้องที่สะอาด แต่โปรดดูลักษณะการทำงานของฟังก์ชันถ้ามันเขียนด้วยการส่งคืนบ่อย ๆ ส่งคืนหลักการก่อน
public function addPost($data = array(), $emailAdmin = true) { if (!$data) { // no data submitted return false; } $this->create(); $result = $this->save($data); if (!$result) { // problem saving the data return false; } // update any other tables // send the email to the admin user if ($emailAdmin) { // send the admin email } // if all is successful return true; }
ในตัวอย่างเล็กๆ นี้ คุณจะเห็นว่าโค้ดมีการเยื้องเพียงครั้งเดียวและสามารถอ่านได้ง่ายกว่ามาก ตรรกะนั้นสมเหตุสมผลมากกว่า - ปล่อยให้ตรรกะทำงานทีละบรรทัด และหากมีปัญหาใดๆ ระหว่างทาง ให้ส่งคืนข้อผิดพลาดและอย่าไปต่อในบรรทัดถัดไป
วิธีนี้ช่วยให้โปรแกรมเมอร์ CakePHP เขียนแบบเดียวกับที่เราอ่าน - อ่านโค้ดจากซ้ายไปขวา บนลงล่าง แทนที่จะเขียนในบล็อกต่างๆ ซึ่งอาจทำให้สับสนได้อย่างรวดเร็ว!
ข้อผิดพลาดทั่วไป #5: ไม่ใช้หลักการ DRY
DRY ย่อมาจาก Don't Repeat Yourself และเป็นปรัชญาที่ควรปฏิบัติตามเมื่อเขียนโค้ดใน CakePHP ด้วยโค้ดเชิงวัตถุ จึงไม่มีข้อแก้ตัวใด ๆ ในการทำซ้ำบล็อกโค้ดเดิมสองครั้ง!
ต่อไปนี้เป็นเคล็ดลับ CakePHP บางส่วนเพื่อให้แน่ใจว่าคุณจะไม่ทำซ้ำ:
ดังที่กล่าวไว้ข้างต้น ตั้งเป้าที่จะใส่ตรรกะในไฟล์โมเดลเพื่อให้คุณสามารถแบ่งปันตรรกะได้
ในไฟล์มุมมองของคุณ หากคุณกำลังดูซ้ำ ให้สร้างโค้ดมุมมองเป็นองค์ประกอบ หรือแม้แต่ผู้ช่วยที่กำหนดเอง
ตั้งค่าการกำหนดค่าบางอย่าง - ไฟล์
app/Config/bootstrap.php
เป็นที่ที่เหมาะสำหรับสิ่งนี้ วิธีนี้ช่วยให้แน่ใจว่าคุณไม่ได้เข้ารหัสสิ่งต่างๆ อย่างหนัก เช่น ชื่อแอปพลิเคชันและที่อยู่อีเมลหลัก สิ่งสุดท้ายที่คุณต้องการทำคือดูไฟล์หลายร้อยไฟล์เพียงเพราะลูกค้าขอให้อัปเดตที่อยู่อีเมลในแอปพลิเคชันถามตัวเองเสมอว่า “ถ้าฉันใช้รหัสซ้ำ มีวิธีอื่นที่ดีกว่าในการเขียนรหัสนี้ไหม และฉันกำลังวางรหัสนี้ถูกที่หรือไม่” เป็นไปได้ว่าถ้าคุณต้องการเขียนโค้ดซ้ำ มันสามารถเขียนได้ดีขึ้น
ข้อผิดพลาดทั่วไป #6: ไม่แสดงความคิดเห็นรหัส
จุดสุดท้ายที่ฉันจะทำคือเกี่ยวกับความคิดเห็น ประการแรกการบล็อกเอกสาร บล็อกเอกสารคือเมื่อคุณบันทึกวิธีการหรือการดำเนินการ ใช้เวลาเพียงนาทีเดียวในการบันทึกเล็กน้อยเกี่ยวกับสิ่งที่ฟังก์ชันทำ แต่มันสร้างความแตกต่างในแง่ของความสามารถในการอ่านโค้ด
CakePHP Doc Blocks ต้องชิดขอบซ้ายของหน้า ตัวอย่างง่ายๆ โดยใช้โค้ดจากด้านบน
/** * Adds & saves a post as well as emails the admin to let them know the post has been added. * Also performs some saving to another table * * @param array $data The post data * @param bool $emailAdmin If set to true, will email the website admin * @return bool Returns true if successful */ public function addPost($data = array(), $emailAdmin = true) {
อย่างที่คุณเห็น การเขียนบล็อก doc ใช้เวลาไม่นาน แต่สร้างความแตกต่างอย่างมากในแง่ของอายุขัยของโค้ด ท้ายที่สุด มันหมายความว่าโค้ดสามารถคงอยู่ในอดีตคุณในฐานะนักพัฒนาซอฟต์แวร์ได้
ในทำนองเดียวกันกับความคิดเห็นในบรรทัด อย่ากลัวที่จะอธิบายว่าโค้ดของคุณทำอะไรและทำไม! มันทำให้เข้าใจโค้ดของคุณได้ง่ายขึ้นในระยะยาว โดยเฉพาะถ้านักพัฒนาคนอื่นกำลังมองหามันอยู่!
สรุป
CakePHP เป็นเฟรมเวิร์กที่กว้างขวางและมีคุณสมบัติครบถ้วน เนื่องจากเป็นไปตามหลักการของการกำหนดค่า CakePHP จึงเข้มงวดกว่าเฟรมเวิร์กที่ใช้ PHP อื่น ๆ ในแง่ที่ว่าผู้ใช้ถูก "บังคับ" ให้ทำตามวิธีการบางอย่างในการวางโค้ด สิ่งนี้อาจเป็นข้อโต้แย้ง แต่จากประสบการณ์ของผม มันนำไปสู่ฐานรหัสที่มีความสอดคล้อง อ่านง่าย และเข้าใจได้ง่ายกว่า แทนที่จะปล่อยให้นักพัฒนา "เลือก" ว่าจะเขียนโค้ดอย่างไร ทีมพัฒนาจะเขียนโค้ดที่สอดคล้องกันโดยทำตามแบบแผนของ Cake .
โดยทำตามบทช่วยสอน CakePHP นี้และตรวจดูให้แน่ใจว่าโค้ดของคุณเขียนได้ดี แอปพลิเคชันสามารถยืนหยัดการทดสอบของเวลา รหัสควรจะเขียนสำหรับวันพรุ่งนี้เสมอ - เพื่อที่ว่าถ้านักพัฒนาคนอื่นกำลังมองหาบล็อกรหัสเฉพาะในปีต่อมา เขาจะเข้าใจรหัสและปฏิบัติตามมาตรฐานที่คาดหวัง CakePHP ก็ไม่ต่างกัน และหวังว่าคู่มือนี้จะช่วยแก้ไขนิสัยที่ไม่ดีบางอย่างได้