Các pro Laravel cho em hỏi chút về Query Builder với ạ
Chả là em mới nhận maintain 1 dự án Laravel.
Cũng 3 năm toàn làm C#, ko động tới Laravel nên e cũng quên tiệt rồi.
Nên có thể câu hỏi sẽ hơi ngu nên mong mọi người gạch đá cho ít đáp án để củng cố kiến thức ạ.
Dự án hiện tại source code Laravel 5.8, mà k thấy dùng tí Eloquent nào, toàn dùng query builder
Dùng DB:: và thực hiện truy vấn ngay tại controller.
Vấn đề là em đang thấy có khá nhiều đoạn code bị lặp đi lặp lại ở nhiều controller khác nhau , chắc trc do cao thủ viết
Nên em muốn gom nó lại thành các function viết ở class mới để tái sử dụng.
Em định tạo các class đóng vai trò là model (do ko dùng eloquent nên e cũng sẽ ko extends Model của Laravel) để copy đưa các hàm giống nhau kia vào để tái sử dụng.
Đại loại như
namespace ABC;
use DB;
class ABC {
public static function common1() {
//copy from controller
DB::...
}
public static function common2() {DB::...}
}
Và ở các controllers thì call tới đây để gọi hàm.
Không biết các refactor code này của em có hợp lý không ạ. Mong mọi người cho ý kiến ạ.
P/s: Tất nhiên phần mới e viết thì em sẽ dùng Eloquent cho nhàn ạ
6 CÂU TRẢ LỜI
Dự án của bạn cũng tách thành các class để viết hàm hàm chung sử dụng query builder à
Thấy code dự án mình, có chỗ viết cả function sử dụng query builder trong Eloquent Model. (nanqua)
@thanhnguyen Mình tách thành class Query nhưng đa số vẫn dùng Eloquent Model, chỉ những query phức tạp quá thì viết Query Builder để sửa dụng Raw query thôi.
@dao.thai.son
Uhm bạn, mình cũng thi thoảng dùng builder cho câu khó
chắc người code dự án của mình trc có quan niệm query builder thì luôn nhanh hơn eloquent thì phải.
ko dùng model thay bằng dùng DB:: trực tiếp trong controller và views
@thanhnguyen Mình thường không viết query trong views đâu, viết trong Controller hoặc gọi đến query trong Controller thôi.
Mình thấy dùng query builder cũng ổn mà, nếu nhiều người dùng nhiều data thì có khả năng còn nhanh hơn eloquent nữa. Nhưng để cho dễ thì phần query nên để ra 1 class riêng, có thể sử dụng cấu trúc repository và viết query trong đó, controller gọi ra (giống cách của bạn)
Uhm, cũng công nhận là nhiều cases ko thể dùng Eloquent thì vẫn dùng Query builder để tối ưu.
OK, thanks bạn. 2 người đồng quan điểm là ok rồi
theo mình thì việc bạn tách như vậy cũng là ok rồi. Việc sử dụng query builder cũng không có vấn đề gì
Mình nghĩ việc refactor sẽ tùy vào việc phần code bạn muốn tách ra đang làm gì
- Với những phần logic đơn giản có thể tách các hàm utilities và re-use lại
- Với những phần logic phức tạp, hoặc đại diện cho một feature hay business logic nào đó, thì bạn có thể sử dụng
Query Object
(thực chất là việc tách class thôi). Đảm bảo tên class mô tả đúng cái đang thực hiện và nội dụng class tập trung vào 1 vấn đề thôi. Hoặc nguy hiểm hơn thì dùng
Repository
(nhưng thực sự theo mình dùng Repository vs Active Record của Laravel là hơi thừa và làm codebase phức tạp hơn) - Tất nhiên là có thể sử dụng pattern này pattern khác vào nữa nhưng mình nghĩ cái đó ko quá quan trọng, miễn sao sau một vài tháng bạn quay lại đọc đoạn code đó vẫn hiểu là đc.
mình cũng đang dùng Query Object bạn ak. Thanks bạn
Mình thấy cách của bạn ổn. Còn về việc viết Eloquent thì cũng tuy thuộc vào dự án của bạn nếu dự án của bạn lớn thì mình thấy query builder sẽ giúp cho bạn tốc độ nhanh hơn so với Eloquent. Còn nếu dự án vừa vừa thì mình dùng Eloquent cho tiện
Bạn có thể sử dụng một class như là repository. Ví dụ như thế này, đảm bảo không cần extend Models
namespace App\Repo;
use Illuminate\Database\Connection;
use Illuminate\Support\Collection;
class StreetRepository implements StreetRepositoryInterface
{
/**
* @var \Illuminate\Database\Connection
*/
protected $db;
/**
* StreetRepository constructor.
*
* @param \Illuminate\Database\Connection $db
*/
public function __construct(Connection $db)
{
$this->db = $db;
}
/**
* @return \Illuminate\Database\Query\Builder
*/
protected function query()
{
return $this->db->table('streets');
}
public function paginateList($page = null, array $columns = ['*'], $perPage = StreetRepositoryInterface::DEFAULT_LIMIT)
{
return $this->query()
->paginate($perPage, $columns, 'page', $page);
}
....
Lâu lâu cũng gặp các cao thủ như vậy. Nếu sau muốn sửa thì phải kiếm hết 20 chỗ để sửa. Bác đã chia kiểu trên thì chia luôn ra 2 loại: ObjectBuilder{} hay ObjectService{} và AbcBuilder{}/AbcService{} Cái nào chung thì gọi ObjectBuilder, riêng thì gọi AbcBuilder.