Vậy là ngày nữa đã tới, Mình vẫn ngồi đây và dốc hết vốn liếng văn học để viết bài cho nó kịp cái KPI, Không biết viết gì thì lại bài cũ dùng lại vậy :v. So sánh Eloquent và Query Builder, Khi nào nên sử dụng eloquent, khi nào nên sử dụng query builder? Chủ đề này có lẽ phải cả tá người viết rồi nhưng vẫn phải múc thôi, biết sao được vì chúng quan trọng mà =)).
Bài viết này sẽ tiếp nối seri laravel core, Nếu bạn chưa đọc 2 bài viết trước của mình về N+1 trong laravel – Nguyên nhân và cách khắc phục. và Phân biệt Method và Properties trong laravel, 4 trường hợp không nên sử dụng Properties. thì bạn có thể đọc lại nhé, chúng đều là những khái niệm hết sức cơ bản trong laravel mà các bạn không thể không biết.
Anh em code laravel chắc không còn xa lạ gì với cách viết User::all() nữa đúng không? Đó là cách chúng ta thường làm, tuy nhiên laravel còn cung cấp 1 phương thức khác để truy vấn dữ liệu đó là query builder, cú pháp của Query Builder sẽ kiểu như: DB::table(‘users’)->get().
Vậy tại sao đã có ông Eloquent rồi còn sinh ra thêm ông Query Builder nữa làm gì cho nó đau đầu nhỉ?
Thực tế thì 2 cách truy vấn này có cơ chế hoàn toàn khác nhau, mỗi cách sẽ có ưu điểm và nhược điểm riêng. Là gì thì cùng đọc tới cuối bài nhé!
Ô CÊ LẸT GÔ…!
Eloquent
Để biểu rõ được Eloquent là cái khỉ khô gì thì trước tiên anh em phải hiểu ORM là gì đã, vì hắn cũng chính là sử dụng cơ chế này.
Hiểu 1 cách nôm na thì ORM là 1 mô hình ánh xạ mỗi bảng của DB qua 1 Model của ứng dụng. Có thể hiểu là mỗi bảng trong DB sẽ tương ứng với 1 model và mình sẽ thao tác với CSDL thông qua model thay vì thao tác trực tiếp với DB. Hiện nay có rất nhiều framework đã sử dụng hình thức này.
Ví dụ: Nếu bạn muốn thêm 1 bài viết vào trong DB thì thông thường sẽ thao tác trực tiếp dưới dạng query INSERT TABLE posts VALUES (…) đúng không. Nhưng với ORM thì các ta sẽ thao tác thông qua 1 model có tên là Post và đương nhiên các xử lý như CRUD, thao tác với các CSDL khác nhau… đã được xử lý sẵn trong Model core rồi, việc của chúng ta là sử dụng những hàm mà model này cung cấp mà thôi. Nhưng nếu muốn sử dụng được các hàm này thì model phải được kế thừa từ class Illuminate\Database\Eloquent\Model.
Mô hình cơ bản sẽ như sau:
Có thể thấy Eloquent rất mạnh mẽ, chúng ta chỉ cần Extend nó và sử dụng thôi. Tuy nhiên phương pháp nào cũng có điểm mạnh và điểm yếu, Khứa này cũng vậy:
Ưu điểm:
- Cung cấp các phương thức giao tiếp với database nên cú pháp rất dễ dùng và tiện lợi. Code clear, dễ đọc, dễ viết. Trong code sẽ không còn những lệnh DB::table lặp đi lặp lại bởi Eloquent đã implement ActiveRecord (nó là sự mapping 1-1 giữa object với data row trong cơ sở dữ liệu). Mỗi model sẽ được mapping với một table cụ thể và việc của ta chỉ là thao tác trên model đó.
- Không cần lo lắng về cú pháp SQL, những người không giỏi về SQL vẫn có thể code được.
- Đặc biệt là Eloquent chỉ tiến hành update những field thay đổi trong 1 record => việc này đã giúp phần tăng performance lên rất nhiều.
- Dễ maintain, sửa chữa, nâng cấp: không cần phải quan tâm tới việc thay đổi CSDL sau này, Eloquent đã thay bạn làm điều đó rồi.
- Có cung cấp các phương thức để quản lý các mối quan hệ giữa các bảng bằng cách định nghĩa quan hệ trong model.
- Tận dụng được các tính năng ưu việt như ActiveRecord pattern, relationships, Model boot, softDelete, eager loading. Thao tác nhiều hơn với dữ liệu trả về (là Collection chứ không phải 1 array như query builder)
- Hỗ trợ SoftDeletes (Query Builder không hỗ trợ).
- Bảo mật tốt: Không cần lo lắng về lỗ hổng SQL Injection (Sẽ có bài viết chi tiết về cách tấn công này, link chưa cập nhật)
Nhược điểm:
- Tốc độ chậm: với việc phải tạo ra thêm 1 Model trong ứng dụng để thao tác với DB đã làm cho Eloquent bị chậm đi vì chúng cần khởi tạo Object, đổ data… qua model này. Đặc biệt với công việc update và create thì sẽ còn chậm hơn nữa. Nếu nhiều data chúng ta có thể cảm nhận được 1 cách rõ rệt.
- Không thao tác được các logic phức tạp: Mặc dù Eloquent đã cung cấp cho chúng ta rất nhiều phương thức có thể giao tiếp với hầu hết các công việc với DB, tuy nhiên vẫn còn 1 số logic phức tạp thì Eloquent lại không xử lý được, Khi này chúng ta sẽ phải nhờ đến QueryBuilder giúp sức.
Query Builder
Trong khi Eloquent ORM sử dụng các model để tương tác với cơ sở dữ liệu thì QueryBuilder sử dụng các phương thức chuỗi để xây dựng câu truy vấn và thao tác trực tiếp với DB. Cơ chế của query builder là chỉ chuyển qua SQL query và chạy trực tiếp. Ví dụ lệnh DB::table(‘users’)->get() thì sẽ được chuyển đổi thành string SELECT * FROM users; và chạy luôn trên DB, kết quả nhận được sẽ đổi vào mảng thay vì Collection như Eloquent.
Ưu điểm:
- Query Builder sử dụng PDO (PHP Data Object, hệ thống API có sẵn của PHP để kết nối đến các CSDL thông dụng).
- Tốc độ nhanh: Từ Query Builder chỉ cần chuyển chúng qua sql và chạy thôi nên tốc độ sẽ nhanh hơn Eloquent.
- Linh hoạt hơn: trong query builder ta hoàn toàn có thể chạy một raw query y như mysql, điều này cực kì có lợi khi cần phải thực hiện các query phức tạp
Nhược điểm:
- Do chỉ là sử dụng các phương thức chuỗi để xây dựng câu truy vấn nên khó có khả năng tương thích với nhiều DB. Nếu bạn viết nhiểu lệnh raw thì sau này có muốn chuyển sang CSDL khác thì phải thay đổi các lệnh trong logic => tương đối đau đầu.
- Bảo mật kém. Dù Query Builder sử dụng PDO đã hỗ trợ bảo vệ trước các cuộc tấn công SQL Injection, tuy nhiên Query Builder lại hỗ trợ việc chạy trực tiếp SQL thông qua raw nên nếu code bảo mật không tốt vẫn có thể bị tấn công.
- Kết quả cảu QueryBuilder trả về 1 mảng kết quả, trong đó mỗi kết quả là 1 object StdClass của PHP => khó thao tác hơn so với collection.
Khi nào sử dụng Eloquent, khi nào sử dụng query builder
Tới đây khi biết được ưu điểm và nhược điểm của từng thằng thì các bạn chắc hẳn đã có nhận định riêng về việc khi nào dùng dùng thằng nào rồi đúng không. Theo quan điểm cá nhân mình thì nên ưu tiên sử dụng Eloquent với những dự án có lượng truy cập là trung bình và nhỏ, vì nó sẽ giúp việc fix bug, bảo trì và nâng cấp trở lên dễ dàng, code clear, dễ đọc và bảo mật hơn. So với lợi ích to lớn của nó thì vài trăm speed cũng đáng để đánh đổi.
Với các hệ thống có lượt truy cập lớn thì nên sử dụng Query Buillder vì chúng sẽ nâng cao hiệu năng hơn, nếu code tốt thì vẫn có thể bảo mật. Sau đây mình tổng hợp lại 1 chút về ưu nhược điểm của 2 cách:
Eloquent | Query Builder | |
---|---|---|
Bảo mật | Có thể chống Sql Injection do sử dụng ORM | Bảo mật kém, dễ bị Sql Injection nếu viết raw kém bảo mật |
Khả năng tương tác | Có thể sử dụng Query Builder bên trong Eloquent | Ko thể sử dụng Eloquent bên trong Query Builder |
Tính thẩm mĩ | Ngắn gọn, Clear, Dễ hiểu | Rườm rà, Đau đầu vì giống cú pháp SQL |
Hiệu suất | Chậm do phải xử lý thêm 1 lớp trung gian | Do chỉ chuyển đổi sang Sql nên tốc độ sẽ nhanh hơn |
Bảo trì nâng cấp | Dễ bảo trì, nâng cấp, Tương tác với nhiều loại database | Sử dụng Raw sẽ khó có khả năng tương thích với một số database |
Tổng kết
Tới đây thì mình cũng hết chữ rồi, vì các bài kiểu như này đã có rất nhiều. Mình chỉ tóm tắt lại những ý mình thấy là quan trọng để hiểu được 2 thằng này là gì và khi nào nên dùng thằng nào thôi.
Bài tiếp theo mình sẽ đề cập đến chủ đề: Dependency Injection là gì? 3 phương pháp DI thường gặp, Nếu các bạn có hứng thú có thể tìm đọc nhé.