ถ้าต้องการศึกษา Laravel framework ซึ่งเป็นสิ่งใหม่สำหรับผม
คำถามที่น่าสนใจก็คือ จะทำการศึกษา และ เรียนรู้ ฝึกทำอย่างไรดีล่ะ ?
คำตอบนั้นมีอยู่หลายแบบ
แต่สำหรับผมแล้ว ขอเริ่มจากการเขียน test หรือ ชุดการทดสอบดีกว่า !!
ดังนั้นมาเริ่มกันเลย
ปล. ไม่พูดถึงการสร้าง project และเตรียม environment นะครับ
มีเป้าหมายหลักเพื่อ
เรียนรู้การพัฒนาระบบด้วย Laravel framework เรียนรู้โครงสร้างการทำงานพื้นฐานของ Laravel framework เช่น- Factory
- Model ซึ่งมี ORM มาให้
- Database migration
- Routing
- Controller
- View
เริ่มด้วยการเขียนชุดการทดสอบในระดับ Acceptance Test
โดยสิ่งที่ต้องการคือ ขั้นตอนการสร้างบัญชีธนาคารของผู้ใช้งาน ดังนั้นการทำงานมีขั้นตอนดังนี้- สร้างผู้ใช้งาน
- สร้างบัญชีธนาคารใหม่
- ตรวจสอบผลการสร้างบัญชีใหม่ ว่าแสดงผลหมายเลขบัญชีใหม่ถูกต้องหรือไม่
คำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่รู้จัก User ใน Factory !!! แต่ประเด็นหลักคือ Factory ของ Model คืออะไร ? และมันอยู่ตรงไหนล่ะ ? ตอบง่าย ๆ คือ โรงงานผลิต Model ไงล่ะ ใครอยากจะจัดการข้อมูลผ่าน database ก็มาหาจากที่นี่ได้เลย เมื่อลองไปค้นหาใน project พบว่าอยู่ในไฟล์ database/factories/ModelFactory.php นั่นเอง แสดงดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="ModelFactory.php"] จาก code ดังกล่าว จะเห็นได้ว่าใน factory มี User อยู่แล้ว แต่ว่า User มันอยู่ใน namspace ชื่อว่า App ดังนั้นสิ่งที่เราควรทำคือ ในชุดการทดสอบ ให้ทำการ import หรือ use App\User สิครับ ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="testcase_02.php"] จากนั้นทำการทดสอบรอบที่สอง จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่สามารถติดต่อ MySQL database ได้ไง แสดงว่า default database ของ Laravel framework คือ MySQL นั่นเอง ได้ความรู้ใหม่กันอีกแล้ว คำถามต่อมาคือ จะทำการแก้ไขอย่างไรดี ? เมื่อไปค้นหาดูพบว่าอยู่ในไฟล์ config/database.php จะพบว่ามีการ configuration ไว้ให้ 3 ตัวคือ SQLite, MySQL และ PostgreSQL ดังนั้นเพื่อความรวดเร็ว ผมจึงเปลี่ยนไปใช้ SQLite ดีกว่า ซึ่งเป็น In-memory database จะได้ไม่ต้องติดตั้ง database อะไรเพิ่มอีก ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="config_database.php"] จากนั้นทำการทดสอบรอบที่สาม จะพบว่าข้อผิดพลาดแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่พบ database ใน SQLite ทำอย่างไรดี ? ให้ทำการกำหนด environment ชื่อว่า DB_DATABASE ในไฟล์ phpunit.xml สิ กำหนดค่าเป็น :memory: ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="phpunit.xml"] จากนั้นทำการทดสอบรอบที่สี่ จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่พบตาราง users ใน database แล้วเราจะสร้างตาราง users ขึ้นมาอย่างไรดี ? หลังจากที่ไปค้นหาและศึกษาพบว่า Laravel framework มี migration tool ให้ใช้งาน แบบนี้ก็สบายเลย ดังนั้นสั่งให้ทำการ migrate database ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="testcase_03.php"] คำถามคือ แล้ว Laravel framework รู้ได้อย่างไรว่าจะสร้างอะไร ? คำตอบคือ ลองไปดูในไฟล์ database/factories/ModelFactory.php และไฟล์ database/migrations/yyyy_mm_dd_create_users_table.php แล้วจะถึงบางอ้อ จากนั้นทำการทดสอบรอบที่ห้า จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ class Account ไม่มีใน Factory นั่นเอง ดังนั้นให้ทำการเพิ่มเข้าไปซะ ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="ModelFactory_02.php"] จากนั้นทำการทดสอบรอบที่หก จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ หา class Account ไม่เจอ ดังนั้นสร้างซะ แต่ถ้าจะสร้างแบบ manual มันดูไม่งามนัก เนื่องจาก Laravel framework ได้เตรียม command line ในการสร้าง model ได้ให้ ดังนั้นมาใช้กันหน่อยสิ <pre> [code] $php artisan make:model Account [/code] จากนั้นทำการทดสอบรอบที่เจ็ด จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ใน class Users ไม่มี function ชื่อว่า accounts() นั่นเอง ดังนั้นให้ทำการเพิ่มเข้าไปในสิ รออะไร อีกอย่างที่ห้ามลืมก็คือ user แต่ละคนสามารถมา back account ได้มากกว่า 1 account นะ เขียน code ได้ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="User_02.php"] จากนั้นทำการทดสอบรอบที่แปด จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่มีตารางชื่อว่า accounts ใน database ดังนั้นให้ทำการสร้างตารางด้วย migration tool กันเลย ด้วยคำสั่งดังนี้ [code] $php artisan make:migration create_accounts_table --create=accounts [/code] จะทำการสร้างไฟล์ใหม่ใน folder database/migration นะครับ จากนั้นทำการทดสอบรอบที่เก้า จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่มี column ชื่อว่า account_no ในตาราง accounts ด้วยการแก้ไขไฟล์ที่อยู่ใน folder database/migrations ชื่อว่า create_accounts_table.php ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="create_accounts_table_01.php"] จากนั้นทำการทดสอบรอบที่สิบ จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่มี column ชื่อว่า user_id ในตาราง accounts ใช้สำหรับการอ้างอิงไปยังตาราง user นั่นเอง ดังนั้นเพิ่มสิครับ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="create_accounts_table_02.php"] จากนั้นทำการทดสอบรอบที่สิบเอ็ด จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ 404 not found คือหา url ดังกล่าวไปเจอ เห็นไหมว่า ปัญหามันวิ่งไปในส่วนของ View แล้วนะ ก็แน่ล่ะ เพราะว่า เรายังไม่สร้างส่วนการแสดงผล และ url ดังกล่าวก็ยังไม่สร้าง !! คำถามที่น่าสนใจคือ จะสร้างอย่างไรดีล่ะ ? เมื่อไปอ่านเอกสารของ Laravel framework ก็พบว่า ก่อนอื่นให้ทำการสร้าง Routing ของ url ที่เราต้องการขึ้นมาก่อน รวมทั้งต้องระบุไปด้วยว่า จะจับคู่กับ class Controller อะไร และ function อะไร และทำงานผ่าน HTTP GET ด้วย โดยทำการเพิ่มในไฟล์ app/HTTP/route.php ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="route.php"] จากนั้นทำการทดสอบรอบที่สิบสอง จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ถ้าสังเกตจะเห็นว่า class UsersController ไม่มีนั่นเอง ดังนั้นให้ทำการสร้างผ่าน command line อีกแล้ว ดังนี้ [code] $php artisan make:controller UsersController [/code] จากนั้นทำการทดสอบรอบที่สิบสาม จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ใน class UsersController ไม่มี function ชื่อว่า show() ดังนั้นให้ทำการเพิ่มดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="UsersController.php"] จากนั้นทำการทดสอบรอบที่สิบสี่ จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ผลการแสดงผลไม่ตรงตามที่ต้องการ ดังนั้น สิ่งที่ต้องทำต่อไปคือ การสร้างส่วนของ view หรือ การแสดงผล โดยต้องทำการดึงข้อมูลผู้ใช้งานจากตาราง User เพื่อส่งไปแสดงผลใน view ต่อไป ซึ่งต้องไปเปิดเอกสารของ Laravel framework ทำต่อไป ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="UsersController_02.php"] จากนั้นทำการทดสอบรอบที่สิบห้า จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูปคำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ เห็นไหมว่า Laravel framework หา view ไม่เจอ ดังนั้นทำการสร้าง folder ชื่อง users ใน resources/views โดย view นั้นจะใช้ Blade template ทำการสร้างไฟล์ชื่อ show.blade.php ขึ้นมาดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="show.blade.php"] จากนั้นทำการทดสอบรอบที่สิบหก ผลที่ได้คือ ผ่านแล้ววววววววว แสดงดังรูปมาถึงตรงนี้ สิ่งที่ต้องถามตัวเราเองก็คือ เราได้เรียนรู้อะไรเกี่ยวกับ Laravel framework กันบ้าง ?แต่ยังไม่จบนะ ลองกลับไปดู code ใน UsersController ดูสิ มันแย่นะ !! นั่นคือบรรทัดนี้ [code] $user = User::where('name', $name)->first(); [/code] มันอ่านไม่ค่อยรู้เรื่องนะ !! รวมทั้งมันใช่หน้าที่ของ controller ที่ต้องมาทำแบบนี้หรือ ? น่าจะต้องย้ายไปอยู่ใน class User หรือ model นะ ดังนั้นเราจึงเข้าสู่การ refactor code สังเกตไหมว่า จะทำการ refactoring code เมื่อชุดการทดสอบผ่านหมดแล้วเท่านั้น
เริ่มต้นการ Refactor code กันเถอะ
[gist id="6148dee2f9b64255a9d49575e0c1f612" file="UsersController_03.php"] แน่นอนว่าถ้า run ต้องเกิด error อย่างแน่นอน เนื่องจากเรายังไม่เคยมี function findByName() ใน class User เลย ดังนั้นมาเพิ่ม function นี้กันเถอะแต่ช้าก่อน !! หยุดคิดหน่อยสิว่า เราพลาดอะไรไป ?คำตอบคือ เรามาเขียน unit test สำหรับ class User กันดีกว่า เพื่อทำให้มั่นใจว่า สิ่งที่เรากำลังจะสร้างมันถูกต้องตามที่คาดหวัง โดยสร้าง unit test ชื่อว่า UserTest.php ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="UserTest.php"] จากนั้นทำการทดสอบรอบที่สิบเจ็ด ทำการทดสอบเฉพาะ class UserTest.php เท่านั้น [code] $./vendor/bin/phpunit tests/unit/UserTest.php [/code] จะพบว่าข้อผิดพลาดมันแตกต่างออกไป แสดงดังรูป
คำถามคือ ปัญหาของข้อผิดพลาดนี้คืออะไร ?
คำตอบคือ ไม่เจอ function findByName() ใน class User ดังนั้นสร้างสิครับ ดังนี้ [gist id="6148dee2f9b64255a9d49575e0c1f612" file="User.php"] จากนั้นทำการทดสอบรอบที่สิบแปด ทำการทดสอบเฉพาะ class UserTest.php เท่านั้น ผลที่ได้คือ ผ่านอีกแล้ววววววเมื่อทุกอย่างพร้อมแล้ว เราก็ทำการทดสอบทั้งหมดอีกครั้งสิ
มันคือ Regression testing นั่นเอง ซึ่งเรามีทั้งหมด 2 test case คือ Acceptance test และ Unit test ได้ผลการทดสอบดังนี้สำหรับใครที่เดินทางมาถึงตรงนี้ คิดอย่างไรกับวิธีการเรียนรู้ Laravel framework แบบนี้บ้าง ?โดยรวมแล้วโครงสร้างของ Laravel framework มันก็เป็นประมาณนี้ สำหรับ code ตัวอย่างทั้งหมดอยู่ที่ Github::Laravel with TDD Reference Websites http://adamwathan.me/2016/01/11/test-driven-laravel-from-scratch/ https://vimeo.com/152727171?from=outro-embed