Bữa nay rảnh rỗi clone Symfony demo (ver hiện tại chạy với Symfony 3.3.*) về để xem thử mặt mũi nó thế nào, và cũng quả không phí, có vài thứ bản thân nhận thấy khá là hay ho.
Không handle được nội dung của logout action
Khi bạn configure logout của firewall như này:
1 | security: |
Done, khi bạn tạo một route mới với name là security_logout
thì xin chúc mừng, Symfony sẽ tự động handle việc logout của user và bạn sẽ chả làm được gì ở cái action này
1 | /** |
Symfony Styles
Bắt đầu từ Symfony 2.7, Symfony Styles
được giới thiệu. Công việc của nó là giúp cho các command bạn viết ra được consistent
. Và việc sử dụng nó gần như là bắt buộc nếu các command của bạn có sự tương tác cao khi sử dụng (như render list
, table
, process bar
, confirm
, …)
1 | class GreetCommand extends ContainerAwareCommand |
Xem thêm về cháu nó: Symfony Styles
Submit form with multiple buttons
Trong trường hợp form của bạn có nhiều submmit buttons thì bạn handle nó bằng việc kiểm tra isClicked
của button đó. (Lưu ý: submmit button add trong template nhé, đừng như ví dụ bên dưới)
1 | $form = $this->createFormBuilder($task) |
Xem thêm: How to Submit a Form with Multiple Buttons
Việc check $form->isSubmmited()
chỉ là optional
Bình thường lúc viết code ta sẽ viết như này:
1 | if ($form->isSubmitted() && $form->isValid()) { |
Thực tế thì việc check $form->isSubmitted()
là không cần thiết vì $form->isValid()
đã ôm luôn việc check submmited trong đó rồi. Vậy tại sao ta vẫn cứ viết như vậy? Câu trả lời là vì thuận miệng, thuận mắt (from Symfony demo: to improve code readability
)
Security annotation
Khi bạn giỏi tiếng Anh và thích viết những message exception thật trất thì:
1 | /* |
Tuy nhiên dốt thì không có quyền được deep, âu cơ, sử dụng annotation, khỏi message gì sất:
1 | /* |
Define util as service
Đây là cái mình thấy khá dị từ Symfony demo và một vài opensource khác, define thành service hết bất kể (static function
là cái gì dạ?). Không biết nên thế nào là hợp lý hơn và xin nhắc lại tí:
- Service nếu không gọi đến thì nó cũng chả tự chạy đâu mà sợ tốn memory
- Symfony giờ đã có
autowired
, xài service éo cần quan tâm cháu nó tên gì nữa, cứ pass nó thành args của action mà táng
1 | public function editAction(Request $request, Post $post, Slugger $slugger) |
Render controller
Thử tưởng tượng bạn render một page show post
có phần related posts
. Có nhiều cách để làm được cái phần đó như là:
- query đống posts đó ra ngay trong
showPostAction
và render như phình phường - render cháu nó bằng ajax append
- viết 1 action mới (không nhất thiết phải có router) và render cháu nó trong template của
showPostAction
. Đây là cách khuyến cáo vì nó sáng sủa và rõ ràng
1 | public function relatedPostsAction(Post $post) { |
1 | public function showPostAction(Post $post) { |
1 | // template of showPostAction |
DependentFixtureInterface
Khi tạo DataFixture
, có những data set bạn cần phải có data từ những fixture trước. VD: khi chạy fixture Order
, bạn cần có Product
, Customer
trước. Để giải quyết, bạn có 2 cách:
- Sử dụng
OrderedFixtureInterface
(thô thiển và mất công handle order number)
1 | class Customer implements FixtureInterface, OrderedFixtureInterface { |
- Xài
DependentFixtureInterface
<- right way, code sẽ clean hơn RẤT RẤT nhiều
1 | class Customer implements FixtureInterface { |
Trans everywhere
Bạn có thể apply được trans ở rất nhiều chỗ (controller, template,…) trong đó có Entiy constraints message
& form label
(và tất nhiên, trans hay không là tùy bạn, mình thì nhác)
1 | use Symfony\Component\Validator\Constraints as Assert; |
1 | class PostType extends AbstractType |
Data provider and yield
Biết cái yield
này rồi mới thấy hồi viết data provider mình bị ngu các bợn ạ. À, tất nhiên bạn thích dùng kiểu nào là tùy nhé, mình chả nói gì đâu :troll:
1 | /** |
1 | // Old |
1 | // New |
Âu cơ, đây là những thứ mình thấy hay ho khi lần đầu tiên thực sự clone Symfony demo về máy thay vì cưỡi ngựa xem hoa qua giao diện UI của github.
Về cơ bản, nó là những kiến thức cơ bản nên nếu cơ bản bạn thấy nó cơ bản thì đúng là nó cơ bản thật và đừng cười mình nhé :troll: