Buggy CakePHP Code: 6 ข้อผิดพลาดที่พบบ่อยที่สุดสำหรับนักพัฒนา CakePHP

เผยแพร่แล้ว: 2022-03-11

CakePHP เป็นเฟรมเวิร์ก PHP ที่น่าทึ่ง แต่มีช่วงการเรียนรู้ที่สูงชัน! จำเป็นต้องมีการวิจัยและการฝึกอบรมเป็นจำนวนมากเพื่อที่จะเป็นผู้เชี่ยวชาญ

ฉันโชคดีที่ได้ใช้ CakePHP มานานกว่า 7 ปีแล้ว และในช่วงเวลานั้น ฉันได้รับเกียรติที่ได้ร่วมงานกับสมาชิกจำนวนมากในชุมชน CakePHP

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

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

บทแนะนำ CakePHP เริ่มต้นนี้จะช่วยให้คุณหลีกเลี่ยงการทอดรหัส 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 ก็ไม่ต่างกัน และหวังว่าคู่มือนี้จะช่วยแก้ไขนิสัยที่ไม่ดีบางอย่างได้