วันนี้เมื่อเริ่มโครงการใหม่หนึ่งในการตัดสินใจที่สำคัญคือการเลือกกรอบงานที่เหมาะสม เป็นเรื่องยากที่จะจินตนาการถึงการสร้างเว็บแอปพลิเคชันที่ซับซ้อนตั้งแต่เริ่มต้นโดยไม่มีแอปพลิเคชัน
ภาษายอดนิยมหลายภาษาสำหรับการพัฒนาเว็บมีเฟรมเวิร์ก 'เริ่มต้น' เช่น Ruby on Rails for Ruby หรือ Django สำหรับ Python อย่างไรก็ตาม PHP ไม่มีค่าเริ่มต้นเดียวและมีตัวเลือกยอดนิยมมากมายให้เลือก
ตาม แนวโน้มของ Google และ GitHub เฟรมเวิร์ก PHP ที่ได้รับความนิยมมากที่สุดคือ Symfony ที่มี 13.7k ดาว และ Laravel ที่มีดาว 29k (ในขณะที่เขียนบทความนี้)
ในบทความนี้ฉันจะเปรียบเทียบกรอบทั้งสองนี้และแสดงวิธีการใช้งานคุณสมบัติที่เรียบง่ายในชีวิตประจำวันกับแต่ละเฟรม ด้วยวิธีนี้คุณสามารถเปรียบเทียบโค้ดของตัวอย่างในชีวิตจริงเคียงข้างกันได้
บทความนี้สันนิษฐานถึงทักษะ PHP ที่แข็งแกร่งและความเข้าใจในกระบวนทัศน์สถาปัตยกรรม MVC แต่ไม่จำเป็นต้องมีประสบการณ์ก่อนหน้านี้กับ Symfony หรือ Laravel
เมื่อพูดถึง Laravel เราหมายถึง Laravel เวอร์ชัน 4 ขึ้นไป Laravel 4 เปิดตัวในปี 2013 และเป็นตัวแทนของการเขียนเฟรมเวิร์กใหม่ทั้งหมด ฟังก์ชันการทำงานของเฟรมเวิร์กถูกแยกออกเป็นส่วนประกอบที่แยกจากกันซึ่งได้รับการจัดการด้วย Composer แทนที่จะเป็นทุกอย่างในที่เก็บโค้ดขนาดใหญ่เดียว
สถานการณ์ที่เป็นไปได้มากที่สุดในการวิเคราะห์งบประมาณทุน
Laravel ประกาศตัวเองว่าเป็นกรอบสำหรับการพัฒนาอย่างรวดเร็วด้วยไวยากรณ์ที่เรียบง่ายและสวยงามซึ่งง่ายต่อการเรียนรู้อ่านและบำรุงรักษา เป็นกรอบที่ได้รับความนิยมสูงสุดในปี 2559 อ้างอิงจาก แนวโน้มของ Google เป็นที่นิยมมากกว่าเฟรมเวิร์กอื่น ๆ สามเท่าและใน GitHub มีดาวมากกว่าคู่แข่งถึงสองเท่า
Symfony 2 เปิดตัวในปี 2554 แต่ต้องไม่สับสนกับ Symfony 1 ซึ่งเป็นกรอบงานที่แตกต่างกันโดยสิ้นเชิงกับหลักการพื้นฐานที่แตกต่างกัน Fabien Potencier ได้สร้าง Symfony 2 และเวอร์ชันปัจจุบันคือ 3.2 ซึ่งเป็นเวอร์ชันที่เพิ่มขึ้นของ Symfony 2 ดังนั้นจึงมักเรียกกันง่ายๆว่า Symfony2 / 3
เช่นเดียวกับ Laravel 4 Symfony 2 ได้รับการออกแบบให้เป็นชุดของส่วนประกอบที่แยกออกจากกัน มีประโยชน์สองประการที่นี่: เราสามารถแทนที่ส่วนประกอบใด ๆ ในโครงการ Symfony และเราสามารถรับและใช้ส่วนประกอบ Symfony ในโครงการที่ไม่ใช่ Symfony ได้ ส่วนประกอบ Symfony สามารถใช้เป็นตัวอย่างโค้ดที่ยอดเยี่ยมและมีการใช้งานในไฟล์ โครงการโอเพ่นซอร์ส เช่น Drupal, phpBB และ Codeception ในความเป็นจริง Laravel เองใช้ส่วนประกอบของ Symfony ไม่น้อยกว่า 14 ชิ้น การทำความเข้าใจ Symfony ทำให้คุณได้รับประโยชน์มากมายเมื่อทำงานกับโครงการอื่น ๆ
เฟรมเวิร์กทั้งสองมาพร้อมกับตัวติดตั้งและตัวห่อที่มีให้ผ่านไฟล์ PHP ในตัวเว็บเซิร์ฟเวอร์ .
การติดตั้ง Symfony ทำได้ง่ายดังต่อไปนี้:
# Downloading Symfony installer sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony # Granting permissions to execute installer sudo chmod a+x /usr/local/bin/symfony # Creating new Symfony project symfony new symfony_project # Launching built-in server cd symfony_project/ && php bin/console server:start
แค่นั้นแหละ! การติดตั้ง Symfony ของคุณพร้อมใช้งานบน URL http://localhost:8000
ขั้นตอนการติดตั้ง Laravel เกือบจะเหมือนกันและเรียบง่ายพอ ๆ กับ Symfony; ข้อแตกต่างเพียงอย่างเดียวคือคุณติดตั้งโปรแกรมติดตั้งของ Laravel ผ่าน Composer:
# Downloading Laravel installer using Composer composer global require 'laravel/installer' # Creating new Laravel project laravel new laravel_project # Launching built-in server cd laravel_project/ && php artisan serve
คุณสามารถเยี่ยมชม http://localhost:8000
และตรวจสอบการติดตั้ง Laravel ของคุณ
บันทึก: ทั้ง Laravel และ Symfony ใช้พอร์ต localhost เดียวกัน (8000) โดยค่าเริ่มต้นดังนั้นคุณจึงไม่สามารถให้อินสแตนซ์เริ่มต้นเหล่านี้ทำงานพร้อมกันได้ อย่าลืมหยุดเซิร์ฟเวอร์ Symfony ด้วยการเรียกใช้ php bin/console server:stop
ก่อนเปิดตัวเซิร์ฟเวอร์ Laravel
นี่คือตัวอย่างของการติดตั้งพื้นฐาน สำหรับตัวอย่างการใช้งานขั้นสูงเพิ่มเติมเช่นความสามารถในการกำหนดค่าโปรเจ็กต์ที่มีโดเมนท้องถิ่นหรือรันหลายโปรเจ็กต์พร้อมกันทั้งสองเฟรมเวิร์กจะมีกล่อง Vagrant:
Symfony ใช้ YAML เป็นไวยากรณ์สำหรับระบุการกำหนดค่า การกำหนดค่าเริ่มต้นจะอยู่ใน app/config/config.yml
ไฟล์และดูเหมือนตัวอย่างต่อไปนี้:
imports: - { resource: parameters.yml } - { resource: security.yml } - { resource: services.yml } framework: secret: '%secret%' router: { resource: '%kernel.root_dir%/config/routing.yml' } # ... # Twig Configuration twig: debug: '%kernel.debug%' strict_variables: '%kernel.debug%' # ...
ในการสร้างคอนฟิกูเรชันเฉพาะสภาพแวดล้อมให้สร้างไฟล์ app/config/config_ENV.yml
มีพารามิเตอร์การกำหนดค่าพื้นฐาน นี่คือตัวอย่างของ config_dev.yml
ไฟล์สำหรับสภาพแวดล้อมการพัฒนา:
imports: - { resource: config.yml } # ... web_profiler: toolbar: true # ...
ตัวอย่างนี้จะเปิดใช้งาน web_profiler
เครื่องมือ Symfony สำหรับสภาพแวดล้อมการพัฒนาเท่านั้น เครื่องมือนี้ช่วยให้คุณแก้ไขข้อบกพร่องและกำหนดโปรไฟล์แอปพลิเคชันของคุณได้จากหน้าต่างเบราว์เซอร์
ในไฟล์การกำหนดค่าคุณสามารถสังเกตเห็น %secret%
การก่อสร้าง ช่วยให้เราใส่ตัวแปรเฉพาะสภาพแวดล้อมใน parameters.yml
แยกต่างหาก ไฟล์. ไฟล์นี้อาจไม่ซ้ำกันในทุกเครื่องและไม่ได้จัดเก็บภายใต้การควบคุมเวอร์ชัน สำหรับการควบคุมเวอร์ชันเรามี parameters.yml.dist
ไฟล์ที่เป็นเทมเพลตสำหรับ parameters.yml
ไฟล์.
นี่คือตัวอย่างของ parameters.yml
ไฟล์:
parameters: database_host: 127.0.0.1 database_port: null database_name: symfony database_user: root database_password: null secret: f6b16aea89dc8e4bec811dea7c22d9f0e55593af
การกำหนดค่า Laravel ดูแตกต่างจาก Symfony มาก สิ่งเดียวที่พวกเขามีเหมือนกันคือทั้งคู่ใช้ไฟล์ที่ไม่ได้จัดเก็บภายใต้การควบคุมเวอร์ชัน (.env
ในกรณี Laravel) และเทมเพลตสำหรับสร้างไฟล์นี้ (.env.example
) ไฟล์นี้มีรายการคีย์และค่าดังตัวอย่างต่อไปนี้:
APP_ENV=local APP_KEY=base64:Qm8mIaur5AygPDoOrU+IKecMLWgmcfOjKJItb7Im3Jk= APP_DEBUG=true APP_LOG_LEVEL=debug APP_URL=http://localhost
เช่นเดียวกับไฟล์ Symfony YAML ไฟล์นี้สำหรับ Laravel ยังสามารถอ่านได้และดูสะอาดตา คุณสามารถสร้าง .env.testing
เพิ่มเติมได้ ไฟล์ที่จะใช้เมื่อเรียกใช้การทดสอบ PHPUnit
การกำหนดค่าแอปพลิเคชันถูกเก็บไว้ใน .php
ไฟล์ใน config
ไดเรกทอรี การกำหนดค่าพื้นฐานจะถูกเก็บไว้ใน app.php
ไฟล์และคอนฟิกูเรชันเฉพาะของคอมโพเนนต์จะถูกเก็บไว้ใน .php
ไฟล์ (เช่น cache.php
หรือ mail.php
) นี่คือตัวอย่างของ config/app.php
ไฟล์:
'Laravel', 'env' => env('APP_ENV', 'production'), 'debug' => env('APP_DEBUG', false), 'url' => env('APP_URL', 'http://localhost'), 'timezone' => 'UTC', 'locale' => 'en', // ... ];
กลไกการกำหนดค่าแอปพลิเคชันของ Symfony ช่วยให้คุณสร้างไฟล์ที่แตกต่างกันสำหรับสภาพแวดล้อมที่แตกต่างกัน นอกจากนี้ยังป้องกันไม่ให้คุณแทรกตรรกะ PHP ที่ซับซ้อนในการกำหนดค่า YAML
อย่างไรก็ตามคุณอาจรู้สึกสบายใจมากขึ้นกับไวยากรณ์การกำหนดค่า PHP เริ่มต้นที่ Laravel ใช้อยู่และคุณไม่จำเป็นต้องเรียนรู้ไวยากรณ์ YAML
โดยทั่วไปเว็บแอปพลิเคชันส่วนหลังมีหน้าที่หลักอย่างหนึ่งคืออ่านคำขอแต่ละรายการและสร้างคำตอบขึ้นอยู่กับเนื้อหาของคำขอ คอนโทรลเลอร์เป็นคลาสที่รับผิดชอบในการเปลี่ยนคำร้องขอเป็นการตอบสนองโดยการเรียกใช้วิธีการแอปพลิเคชันในขณะที่เราเตอร์เป็นกลไกที่ช่วยให้คุณตรวจพบคลาสคอนโทรลเลอร์และวิธีการที่คุณควรดำเนินการสำหรับคำร้องขอเฉพาะ
มาสร้างตัวควบคุมที่จะแสดงหน้าบล็อกโพสต์ที่ขอจาก /posts/{id}
เส้นทาง.
ตัวควบคุม
Post::findOrFail($id)]); } }
เราเตอร์
Route::get('/posts/{id}', ' [email protected] ');
เราได้กำหนดเส้นทางสำหรับ GET
คำขอ คำขอทั้งหมดที่มี URI ตรงกับ /posts/{id}
จะดำเนินการ BlogController
ผู้ควบคุม show
วิธีการและจะส่งผ่านพารามิเตอร์ id
กับวิธีการนั้น ในคอนโทรลเลอร์เราพยายามค้นหาวัตถุของโมเดล POST
ด้วยการผ่าน id
และโทรหาผู้ช่วย Laravel view()
เพื่อแสดงหน้า
ใน Symfony, exampleController
ใหญ่กว่าเล็กน้อย:
getDoctrine()->getRepository('BlogBundle:Post'); $post = $repository->find($id); if ($post === null) { throw $this->createNotFoundException(); } return $this->render('BlogBundle:Post:show.html.twig', ['post'=>$post]); } }
คุณจะเห็นว่าเราได้รวม @Route('/posts/{id}”)
ไว้แล้ว ในคำอธิบายประกอบดังนั้นเราจึงต้องรวมคอนโทรลเลอร์ไว้ใน routing.yml
ไฟล์กำหนดค่า:
blog: resource: '@BlogBundle/Controller/' type: annotation prefix: /
ลอจิกทีละขั้นตอนจะเหมือนกับในเคส Laravel
ในขั้นตอนนี้คุณอาจคิดว่า Laravel ดีกว่า Symfony มาก นี่เป็นความจริงในตอนแรก มันดูดีขึ้นและเริ่มง่ายขึ้น อย่างไรก็ตามในแอปพลิเคชันในชีวิตจริงคุณไม่ควรเรียก Doctrine จากคอนโทรลเลอร์ แต่คุณควรเรียกใช้บริการที่จะพยายามค้นหาโพสต์หรือโยน ข้อยกเว้น HTTP 404 .
Laravel มาพร้อมกับเครื่องมือแม่แบบที่เรียกว่า ใบมีด และ Symfony มาพร้อมกับ กิ่งไม้ . เอ็นจิ้นเทมเพลตทั้งสองใช้คุณสมบัติหลักสองประการ:
คุณลักษณะทั้งสองช่วยให้คุณกำหนดแม่แบบพื้นฐานที่มีส่วนที่เขียนทับได้และแม่แบบลูกที่เติมเต็มค่าของส่วนเหล่านั้น
ลองพิจารณาตัวอย่างของหน้าโพสต์บล็อกอีกครั้ง
พักโหนดบริการเว็บ js
// base.blade.php @section('page-title') Welcome to blog! @show {% block content %}{% endblock %} // show.html.twig {% extends '@Blog/base.html.twig' %} {% block page_title %}Post {{ post.title }} - read this and more in our blog.{% endblock %} {% block title %}{{ post.title }}{% endblock %} {% block content %} {{ post.content }} {% endblock %}
แม่แบบโครงสร้าง Blade และ Twig ค่อนข้างคล้ายกัน ทั้งสองสร้างเทมเพลตเป็นโค้ด PHP และทำงานได้รวดเร็วและใช้โครงสร้างการควบคุมเช่น if
งบและลูป คุณสมบัติที่สำคัญที่สุดทั้งสองเอนจิ้นมีคือหนีเอาท์พุทตามค่าเริ่มต้นซึ่งช่วยป้องกันการโจมตี XSS
นอกเหนือจากไวยากรณ์แล้วความแตกต่างที่สำคัญคือ Blade ช่วยให้คุณสามารถฉีดโค้ด PHP ลงในเทมเพลตของคุณได้โดยตรงและ Twig ไม่ทำ Twig ให้คุณใช้ฟิลเตอร์แทน
ตัวอย่างเช่นหากคุณต้องการใช้ตัวพิมพ์ใหญ่สตริงใน Blade คุณจะระบุสิ่งต่อไปนี้:
{{ ucfirst('welcome friend') }}
ในทางกลับกันใน Twig คุณจะต้องทำสิ่งต่อไปนี้:
{capitalize }
ใน Blade การขยายฟังก์ชันบางอย่างจะง่ายกว่า แต่ Twig ไม่อนุญาตให้ใช้โค้ด PHP โดยตรงในเทมเพลต
แอปพลิเคชันมีบริการและส่วนประกอบที่แตกต่างกันจำนวนมากโดยมีการพึ่งพาซึ่งกันและกัน คุณต้องจัดเก็บข้อมูลทั้งหมดเกี่ยวกับวัตถุที่สร้างขึ้นและการอ้างอิงอย่างใด
นี่คือส่วนประกอบต่อไปของเรา - คอนเทนเนอร์บริการ . เป็นวัตถุ PHP ที่สร้างบริการที่ร้องขอและเก็บข้อมูลเกี่ยวกับวัตถุที่สร้างขึ้นและการอ้างอิง
ลองพิจารณาตัวอย่างต่อไปนี้: คุณกำลังสร้างคลาส PostService
เพื่อใช้วิธีการที่รับผิดชอบในการสร้างบล็อกโพสต์ใหม่ คลาสนี้ขึ้นอยู่กับบริการอื่น ๆ สองบริการ: PostRepository
ซึ่งมีหน้าที่จัดเก็บข้อมูลในฐานข้อมูลและ SubscriberNotifier
ซึ่งมีหน้าที่ในการแจ้งเตือนผู้ใช้ที่สมัครสมาชิกเกี่ยวกับโพสต์ใหม่ เพื่อให้ใช้งานได้คุณต้องส่งสองบริการนี้เป็นอาร์กิวเมนต์ตัวสร้างของ PostService
หรือกล่าวอีกนัยหนึ่งคุณต้องฉีดการอ้างอิงเหล่านี้
ขั้นแรกให้กำหนดบริการตัวอย่างของเรา:
repository = $repository; $this->notifier = $notifier; } public function create(Post $post) { $this->repository->persist($post); $this->notifier->notifyCreate($post); } }
ต่อไปคือการกำหนดค่าการฉีดพึ่งพา:
c++ หน้าตาเป็นอย่างไร
# src/BlogBundle/Resources/config/services.yml services: # Our main service blog.post_service: class: BlogBundleServicePostService arguments: ['@blog.post_repository', '@blog.subscriber_notifier'] # SubscriberNotifier service. It could also have its own dependencies, for example, mailer class. blog.subscriber_notifier: class: BlogBundleServiceSubscriberNotifier # Repository. Don't dive deep into it's configuration, it is not a subject now blog.post_repository: class: BlogBundleRepositoryPostRepository factory: 'doctrine.orm.default_entity_manager:getRepository' arguments: - BlogBundleEntityPost
ตอนนี้คุณสามารถขอบริการโพสต์ของคุณได้ทุกที่ในรหัสจากออบเจ็กต์คอนเทนเนอร์บริการของคุณ ตัวอย่างเช่นในคอนโทรลเลอร์อาจเป็นดังนี้:
// Controller file. $post variable defined below $this->get('blog.post_service')->create($post);
คอนเทนเนอร์บริการเป็นส่วนประกอบที่ยอดเยี่ยมและช่วยในการสร้างแอปพลิเคชันของคุณต่อไปนี้ ของแข็ง หลักการออกแบบ
ที่เกี่ยวข้อง: True Dependency Injection ด้วยส่วนประกอบของ Symfony Laravel Dependency Injection ตัวอย่าง
การจัดการการอ้างอิงใน Laravel นั้นง่ายกว่ามาก ลองพิจารณาตัวอย่างเดียวกัน:
repository = $repository; $this->notifier = $notifier; } public function create(Post $post) { $this->repository->persist($post); $this->notifier->notifyCreate($post); } }
ความงามของ Laravel มาที่นี่ - คุณไม่จำเป็นต้องสร้างการกำหนดค่าการอ้างอิง . Laravel จะสแกนการอ้างอิงสำหรับ PostService
โดยอัตโนมัติ ในประเภทอาร์กิวเมนต์ตัวสร้างและแก้ไขโดยอัตโนมัติ
คุณยังสามารถใช้การฉีดในวิธีการควบคุมของคุณเพื่อใช้ PostService
โดย 'type-hinting' ในอาร์กิวเมนต์เมธอด:
'Title', 'content' => 'Content']); $service->create($post); return redirect('/posts/'.$post->id); } }
Dependency Injection: Symfony เทียบกับ Laravel
การตรวจจับอัตโนมัติของ Laravel ทำงานได้ดี Symfony มีความสามารถคล้ายกันที่เรียกว่า“ autowire ” ที่ถูกปิดโดยค่าเริ่มต้นและสามารถเปิดได้โดยเพิ่ม autowire: true
ในการกำหนดค่าการอ้างอิงของคุณ แต่ต้องมีการกำหนดค่าบางอย่าง วิธี Laravel นั้นง่ายกว่า
การแม็ปเชิงสัมพันธ์ของวัตถุ (ORM)
ในการทำงานกับฐานข้อมูลทั้งสองเฟรมเวิร์กมาพร้อมกับคุณสมบัติ Object-Relational Mapping (ORM) ORM แมปเร็กคอร์ดจากฐานข้อมูลไปยังอ็อบเจ็กต์ในโค้ด ในการดำเนินการนี้คุณต้องสร้างแบบจำลองสำหรับระเบียนแต่ละประเภท (หรือแต่ละตาราง) ในฐานข้อมูลของคุณ
Symfony ใช้โครงการของบุคคลที่สาม หลักคำสอน เพื่อโต้ตอบกับฐานข้อมูลในขณะที่ Laravel ใช้ไลบรารีของตัวเอง คมคาย .
ORM ที่คมคายใช้ รูปแบบ ActiveRecord เพื่อทำงานกับฐานข้อมูล ในรูปแบบนี้แต่ละรุ่นจะทราบถึงการเชื่อมต่อกับฐานข้อมูลและสามารถโต้ตอบกับฐานข้อมูลได้ ตัวอย่างเช่นสามารถบันทึกข้อมูลลงในฐานข้อมูลอัปเดตหรือลบบันทึก
หลักคำสอนดำเนินการ รูปแบบ Data Mapper โดยที่โมเดลไม่รู้อะไรเกี่ยวกับฐานข้อมูล พวกเขารับรู้เฉพาะข้อมูลเท่านั้น เลเยอร์แยกพิเศษ EntityManager
เก็บข้อมูลทั้งหมดเกี่ยวกับการโต้ตอบระหว่างโมเดลและฐานข้อมูลและจัดการการดำเนินการทั้งหมด
ลองดูตัวอย่างเพื่อทำความเข้าใจความแตกต่าง สมมติว่าโมเดลของคุณมีหลัก id
คีย์ชื่อเนื้อหาและผู้แต่ง กระทู้ ตารางเก็บเฉพาะผู้แต่ง id
ดังนั้นคุณต้องสร้างความสัมพันธ์กับไฟล์ ผู้ใช้ โต๊ะ.
หลักคำสอน
เริ่มต้นด้วยการกำหนดโมเดล:
ที่นี่เราได้สร้างข้อมูลการแม็ปโมเดลและตอนนี้สามารถใช้ตัวช่วยเพื่อสร้างเมธอดสตับ:
php bin/console doctrine:generate:entities BlogBundle
ต่อไปเราจะกำหนดวิธีการโพสต์ที่เก็บ:
getEntityManager()->persist($post); $this->getEntityManager()->flush(); } /** * Search posts with given author's name * * @param string $name * @return array */ public function findByAuthorName($name) { return $this->createQueryBuilder('posts') ->select('posts') ->join('posts.author', 'author') ->where('author.name = :name') ->setParameter('name', $name) ->getQuery() ->getResult(); } }
ตอนนี้คุณสามารถเรียกใช้วิธีการเหล่านี้จากบริการหรือตัวอย่างเช่นจาก PostController
:
// To search for posts $posts = $this->getDoctrine()->getRepository('BlogBundle:Post')->findByAuthorName('Karim'); // To save new post in database $this->getDoctrine()->getRepository('BlogBundle:Post')->persist($post);
คมคาย
ผู้ใช้ โมเดลมาพร้อมกับ Laravel และถูกกำหนดโดยค่าเริ่มต้นดังนั้นคุณต้องกำหนดโมเดลเดียวสำหรับ โพสต์ .
belongsTo('AppUser', 'author_id'); } }
ทั้งหมดนี้มีไว้สำหรับนางแบบ ใน Eloquent คุณไม่จำเป็นต้องกำหนดคุณสมบัติของโมเดลเนื่องจากสร้างแบบไดนามิกตามโครงสร้างตารางฐานข้อมูล เพื่อจัดเก็บโพสต์ใหม่ $post
ในฐานข้อมูลคุณต้องโทรออก (จากคอนโทรลเลอร์เป็นต้น):
$post->save();
หากต้องการค้นหาโพสต์ทั้งหมดของผู้เขียนที่มีชื่อระบุแนวทางที่ดีที่สุดคือค้นหาผู้ใช้ที่มีชื่อและขอโพสต์ของผู้ใช้ทั้งหมด:
$posts = Post::whereHas('author', function ($q) { $q->where('name', 'Karim'); })->get();
ORM: Symfony กับ Laravel
เกี่ยวกับ ORM Eloquent ดูเป็นมิตรมากขึ้นสำหรับ นักพัฒนา PHP และเรียนรู้ได้ง่ายกว่าหลักคำสอน
Event Dispatcher กับ Middleware

สิ่งที่สำคัญที่สุดอย่างหนึ่งในการทำความเข้าใจเกี่ยวกับเฟรมเวิร์กคือวงจรชีวิต
Symfony และ Event Dispatcher
ในการแปลงคำขอเป็นการตอบกลับ Symfony ใช้ EventDispatcher ส่งผลให้เกิดเหตุการณ์วงจรชีวิตที่แตกต่างกันและผู้ฟังเหตุการณ์พิเศษเพื่อจัดการกับเหตุการณ์เหล่านี้ ในตอนแรกมันจะยื้อ kernel.request
เหตุการณ์ที่มีข้อมูลการร้องขอ ผู้ฟังเริ่มต้นหลักของเหตุการณ์นี้คือ RouterListener
ซึ่งเรียกใช้คอมโพเนนต์เราเตอร์เพื่อค้นหากฎเส้นทางที่เหมาะสมสำหรับคำขอปัจจุบัน หลังจากนี้เหตุการณ์อื่น ๆ จะดำเนินการทีละขั้นตอน ผู้ฟังเหตุการณ์ทั่วไปคือการตรวจสอบความปลอดภัยการตรวจสอบโทเค็น CSRF และกระบวนการบันทึก หากคุณต้องการเพิ่มฟังก์ชันบางอย่างในวงจรการใช้งานของคำขอคุณต้องสร้าง EventListener
ที่กำหนดเอง และสมัครเข้าร่วมกิจกรรมที่จำเป็น
Laravel และ Middleware
Laravel ใช้โซลูชันอื่น: มิดเดิลแวร์ ฉันชอบเปรียบเทียบมิดเดิลแวร์กับหัวหอม: แอปพลิเคชันของคุณมีบางเลเยอร์และคำขอจะส่งผ่านเลเยอร์เหล่านี้ระหว่างทางไปยังคอนโทรลเลอร์และด้านหลัง ดังนั้นหากคุณต้องการขยายตรรกะแอปพลิเคชันของคุณและเพิ่มฟังก์ชันการทำงานบางอย่างในวงจรชีวิตของคำขอคุณต้องเพิ่มเลเยอร์เพิ่มเติมในรายการมิดเดิลแวร์ของคุณจากนั้น Laravel จะดำเนินการ
REST API
มาลองสร้างตัวอย่าง CRUD พื้นฐานเพื่อจัดการโพสต์บล็อก:
- สร้าง -
POST /posts/
- อ่าน -
GET /posts/{id}
- ปรับปรุง -
PATCH /posts/{id}
- ลบ -
DELETE /posts/{id}
REST API ใน Symfony
Symfony ไม่มีโซลูชันสำเร็จรูปที่ใช้งานง่ายสำหรับการสร้าง REST API ที่รวดเร็ว แต่มีบันเดิลของบุคคลที่สามที่ยอดเยี่ยม FOSRestBundle
และ JMSSerializerBundle
.
ลองพิจารณาตัวอย่างการทำงานขั้นต่ำด้วย FOSRestBundle
และ JMSSerializerBundle
. หลังจากที่คุณติดตั้งและเปิดใช้งานใน AppKernel
คุณสามารถตั้งค่าในการกำหนดค่าบันเดิลที่คุณจะใช้รูปแบบ JSON และไม่จำเป็นต้องรวมอยู่ในคำขอ URL:
#app/config/config.yml fos_rest: routing_loader: default_format: json include_format: false
ในการกำหนดค่าการกำหนดเส้นทางคุณควรระบุว่าคอนโทรลเลอร์นี้จะใช้รีซอร์ส REST:
#app/config/routing.yml blog: resource: BlogBundleControllerPostController type: rest
คุณใช้เมธอด persist ในที่เก็บในตัวอย่างก่อนหน้านี้ ตอนนี้คุณต้องเพิ่มวิธีการลบ:
// src/BlogBundle/Repository/PostRepository.php public function delete(Post $post) { $this->getEntityManager()->remove($post); $this->getEntityManager()->flush(); }
ถัดไปคุณต้องสร้างไฟล์ ฟอร์มคลาส เพื่อยอมรับคำขอป้อนข้อมูลและแมปกับโมเดล คุณสามารถทำได้โดยใช้ตัวช่วย CLI:
php bin/console doctrine:generate:form BlogBundle:Post
คุณจะได้รับแบบฟอร์มที่สร้างขึ้นพร้อมรหัสต่อไปนี้:
add('title')->add('content'); } /** * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => 'BlogBundleEntityPost', 'csrf_protection' => false ]); } /** * {@inheritdoc} */ public function getBlockPrefix() { return 'post'; } }
ตอนนี้มาใช้ตัวควบคุมของเรากัน
บันทึก: รหัสที่ฉันจะแสดงให้คุณไม่สมบูรณ์แบบ มันละเมิดหลักการออกแบบบางประการ แต่สามารถปรับโครงสร้างใหม่ได้ง่าย จุดประสงค์หลักคือเพื่อแสดงวิธีการใช้งานแต่ละวิธีทีละขั้นตอน
getDoctrine()->getRepository('BlogBundle:Post')->find($id); if ($post === null) { $view->setStatusCode(Response::HTTP_NOT_FOUND); } else { $view->setData(['post' => $post]); } return $this->handleView($view); } /** * @param Request $request * @return Response */ public function postPostAction(Request $request) { $view = new View(null, Response::HTTP_BAD_REQUEST); $post = new Post; $form = $this->createForm(PostType::class, $post, ['method' => $request->getMethod()]); $form->handleRequest($request); if ($form->isValid()) { $this->getDoctrine()->getRepository('BlogBundle:Post')->persist($post); $view->setStatusCode(Response::HTTP_CREATED); $postUrl = $this->generateUrl('get_post', ['id' => $post->getId()], UrlGeneratorInterface::ABSOLUTE_URL); $view->setHeader('Location', $postUrl); } else { $view->setData($form->getErrors()); } return $this->handleView($view); } /** * @param $id * @param Request $request * @return Response */ public function patchPostAction($id, Request $request) { $view = new View(null, Response::HTTP_BAD_REQUEST); $post = $this->getDoctrine()->getRepository('BlogBundle:Post')->find($id); if ($post === null) { $view->setStatusCode(Response::HTTP_NOT_FOUND); } else { $form = $this->createForm(PostType::class, $post, ['method' => $request->getMethod()]); $form->handleRequest($request); if ($form->isValid()) { $this->getDoctrine()->getRepository('BlogBundle:Post')->persist($post); $view->setStatusCode(Response::HTTP_NO_CONTENT); $postUrl = $this->generateUrl('get_post', ['id' => $post->getId()], UrlGeneratorInterface::ABSOLUTE_URL); $view->setHeader('Location', $postUrl); } else { $view->setData($form->getErrors()); } } return $this->handleView($view); } /** * @param $id * @return Response */ public function deletePostAction($id) { $view = new View(null, Response::HTTP_NOT_FOUND); $post = $this->getDoctrine()->getRepository('BlogBundle:Post')->find($id); if ($post !== null) { $this->getDoctrine()->getRepository('BlogBundle:Post')->delete($post); $view->setStatusCode(Response::HTTP_NO_CONTENT); } return $this->handleView($view); } }
ด้วย FOSRestBundle
คุณไม่จำเป็นต้องประกาศเส้นทางสำหรับแต่ละวิธี เพียงทำตามแบบแผนด้วยชื่อเมธอดคอนโทรลเลอร์และ JMSSerializerBundle
จะแปลงโมเดลของคุณเป็น JSON โดยอัตโนมัติ
REST API ใน Laravel
ขั้นแรกคุณต้องกำหนดเส้นทาง คุณสามารถทำได้ใน API
ส่วนของกฎเส้นทางเพื่อปิดส่วนประกอบมิดเดิลแวร์เริ่มต้นบางส่วนและเปิดใช้งานอื่น ๆ API
จะอยู่ในส่วน routes/api.php
ไฟล์.
ในโมเดลคุณควรกำหนด $fillable
คุณสมบัติในการส่งผ่านตัวแปรในวิธีการสร้างและอัปเดตของโมเดล:
ตอนนี้เรามากำหนดตัวควบคุม:
get('post')); return response(null, Response::HTTP_CREATED, ['Location'=>'/posts/'.$post->id]); } public function update(Post $post, Request $request) { $post->update($request->get('post')); return response(null, Response::HTTP_NO_CONTENT, ['Location'=>'/posts/'.$post->id]); } public function destroy(Post $post) { $post->delete(); return response(null, Response::HTTP_NO_CONTENT); } }
ใน Symfony คุณกำลังใช้ FosRestBundle
ซึ่งรวมข้อผิดพลาดไว้ใน JSON ใน Laravel คุณต้องทำเอง คุณต้องอัปเดตวิธีการแสดงผลในตัวจัดการข้อยกเว้นเพื่อส่งคืนข้อผิดพลาด JSON สำหรับคำขอ JSON ที่คาดหวัง:
expectsJson()) { $status = 400; if ($this->isHttpException($exception)) { $status = $exception->getStatusCode(); } elseif ($exception instanceof ModelNotFoundException) { $status = 404; } $response = ['message' => $exception->getMessage(), 'code' => $exception->getCode()]; return response()->json($response, $status); } return parent::render($request, $exception); } // ... }
REST API: Symfony กับ Laravel
อย่างที่คุณเห็นสำหรับ REST API ทั่วไป Laravel นั้นง่ายกว่า Symfony มาก
เลือกผู้ชนะ: Symfony หรือ Laravel?
ไม่มีผู้ชนะที่ชัดเจนระหว่าง Laravel และ Symfony เนื่องจากทุกอย่างขึ้นอยู่กับเป้าหมายสุดท้ายของคุณ
Laravel เป็นทางเลือกที่ดีกว่าหาก:
นามสกุลไฟล์ c++
- นี่เป็นประสบการณ์ครั้งแรกของคุณกับกรอบงานเนื่องจากง่ายต่อการเรียนรู้และมีไวยากรณ์ที่ง่ายกว่าและสื่อการเรียนรู้ที่ดีกว่า
- คุณกำลังสร้างผลิตภัณฑ์เริ่มต้นและตรวจสอบสมมติฐานของคุณเนื่องจากเป็นสิ่งที่ดีสำหรับการพัฒนาแอปพลิเคชันอย่างรวดเร็วและ นักพัฒนา Laravel หาง่าย
Symfony เป็นตัวเลือกที่ดีที่สุดหาก:
- คุณกำลังสร้างแอปพลิเคชันสำหรับองค์กรที่ซับซ้อนเนื่องจากสามารถปรับขนาดได้มากบำรุงรักษาได้และมีโครงสร้างที่ดี
- คุณกำลังสร้างการโยกย้ายของโครงการระยะยาวขนาดใหญ่เนื่องจาก Symfony มีแผนการเปิดตัวที่คาดเดาได้สำหรับหกปีข้างหน้าดังนั้นจึงมีโอกาสน้อยที่จะเกิดความประหลาดใจใด ๆ