[Laravel] Note 1: SQL & Helper in blade view file

Bài viết tổng hợp 1 số tips trong Laravel

1. Feature Toggle in laravel

Thêm helper cho blade, việc bật/tắt hiển thị giờ sẽ do config, dễ dàng hơn. Ví dụ chức năng login with Facebook

  • Tạo file cấu hình (config/features.php)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php

    return [
    'loginWithGoogle' => true,
    'newSearchBox' => true,
    'newsLetterBox' => false,
    /*
    Some Features ....
    */
    ];
  • Sau đó chỉnh sửa file AppServiceProvider và thêm helper cho phương thức boot()
    1
    2
    3
    Blade::if('feature', function ($feature) {
    return config("features.$feature", false);
    });
  • Done! Giờ bạn có thể dùng ở blade files (views)
    1
    2
    3
    4
    5
    6
    @feature('loginWithGoogle')
    <a href="#" class="btn btn-primary-soft">
    <i class="fa fa-google"></i>
    <span>Login With Google</span>
    </a>
    @endfeature

3. Sáu cách để thực hiện 1 truy vấn SQL

3.1. Một số cách load dữ liệu trong quan hệ của Laravel

Trước khi xem các cách thực hiện truy vấn trong Larael, chúng ta cùng điểm qua xem Eloquent của Laravel sử dụng lấy dữ liệu như thế nào nhé.

Eloquent trong Laravel cung cấp cho chúng ta 3 cách query dữ liệu: Lazy load, Eager Loading, Lazy Eager Loading

Lazy load (chỉ lấy dữ liệu chính nó)

Đây là các lấy dữ liệumặc định, các Eloquent sẽ chỉ lấy các dữ liệu của chính nó mà không query để lấy các quan hệ

1
2
$users = User::all()
$flight = App\Flight::where('number', 'FR 900')->first();

Eager Loading (lấy parent model cùng các quan hệ)

Khi bạn thực hiện truy cập quan hệ Eloquent như thuộc tính, dữ liệu relationship đó là “lazy loaded”. Điều đó có nghĩa relationshop data không thực sự được load cho tới khi lần đầu bạn truy cập vào thuộc tính của nó. Tuy nhiên, Eloquent có thể “eager load” relationship tại thời điểm bạn truy vấn vào parent model. Eager loading giải quyết vấn đề N + 1 truy vấn

1
$books = App\Book::with('author')->get();

Phương thức with này sử dụng lấy quan hệ cho tất cả các books. Nếu muốn load quan hệ theo từng model, hãy xem xét phương thức load() bên dưới. Điều đó có nghĩa là truy vấn sau sẽ không có ý nghĩa lấy User có id là 1 và quan hệ của nó:
1
2
$user = User::find(1)->with('posts')->get(); 
// find không có ý nghĩa vì nó load hết quan hệ và trả về tất cả users

Lazy Eager Loading (lấy parent model xong sau đó quyết định có lấy các quan hệ hay không vì mặc định nó chỉ lấy parent model chính là lazy loading)

Đôi khi bạn có thể cần eager load 1 quan hệ sau khi parent model được lấy. Ví dụ điều này cực kì hữu ích nếu bạn muốn quyết định có load các model liên quan trong quan hệ hay không?

1
2
3
4
5
$books = App\Book::all();

if ($someCondition) {
$books->load('author', 'publisher');
}

Trái với with là lấy dữ liệu quan hệ toàn bộ các model, load sẽ được sử dụng để lấy các quan hệ của 1 model do bạn chỉ định :D
1
$posts = User::find(1)->load('posts'); // không dùng with nhé

Ngoài lề: Dynamic relationships in Laravel using subqueries

Ơ thì đằng nào cũng đang nói về quan hệ mình xin nói luôn 1 bài toán khá hay mình đã gặp. Thông thường các quan hệ được liên kết thông qua khóa ngoài, phép so sánh bằng, như user_id trong bảng posts bằng với id trong bảng users. Tuy nhiên đôi khi lại có 1 chút khác biệt, giả sử user_id trong bảng posts lại là giá trị id trong bảng user cộng thêm 1 thì sao (ví dụ thôi nhé, thực tế chắc không có). Hay một bài toán khác lấy lần login cuối cùng của 1 user, dữ liệu thực tế chúng ta muốn lấy chỉ là 1 bản ghi trong bảng logins chứ không phải toàn bộ dữ liệu logins của users rồi mới xử lý tiếp. Lúc đó hãy dùng subquery để xây dựng ra các quan hệ động nhé :D

Link bài viết gốc: https://reinink.ca/articles/dynamic-relationships-in-laravel-using-subqueries

3.2 Một số truy vấn trong Laravel

Chúng ta cùng xem xét 6 cách truy vấn DB trong Laravel

Given this tables:

1
2
3
4
5
6
7
8
Users
id
name

Posts
id
content
user_id

Select all post from specific user:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* First Way */
$user = User::find(1); // Just Eloquent
$posts = $user->posts; // Just Eloquent

/* Second Way */
$posts = User::with('posts')->find(1); // Eloquent with Eager loading

/* Third Way */
$posts = User::find(1)->load('posts'); // Eloquent with Lazy Eager Loading

/* Fourth Way */
$posts = User::join('posts', 'users.id', '=', 'posts.user_id')
->where('users.id', 1)
->get();
// Eloquent with Query Builder methods

/* Fifth Way */
$posts = DB::table('users')
->join('posts', 'users.id', '=', 'posts.user_id')
->where('users.id', 1)->get();
// Just Query Builder

/* Sixth Way */
$posts = DB::select(
'select * from users join posts on users.id = posts.user_id where users.id = 1'
); // Just SQL

4. Xem SQL query được sinh ra bởi Eloquent hoặc Query Builder. Ghi log

Laravel cung cấp 1 số phương thức giúp bạn dump câu lệnh truy vấn toSql(), getBindings()

1
2
3
4
5
6
7
8
App\Models\Division::where('type', 'rx')->toSql();

// generates the following query:
"select * from `divisions` where `type` = ?"

$query = DB::table('table')->whereIn('some_field', [1,2,30]);
$bindings = $query->getBindings();
// Giá trị mảng truyền vào truy vấn

Vậy nếu để gộp 2 kết quả trên thành 1 truy vấn hoàn chỉnh thì sao nhỉ? Bạn chỉ cần thay các giá trị ? từ phương thức toSql() thành các giá trị nhận được từ phương thức getBindings() :D
1
2
3
4
5
6
7
8
9
public function getQueries(Builder $builder)
{
$addSlashes = str_replace('?', "'?'", $builder->toSql());

return vsprintf(
str_replace('?', '%s', $addSlashes),
$builder->getBindings()
);
}

Chi tiết bạn có thể xem thêm tại đây

Phương thức dd() hay dump() cũng là 1 cách xem SQL Query:

1
2
3
DB::table('users')->where('votes', '>', 100)->dd();

DB::table('users')->where('votes', '>', 100)->dump();

Link: https://laravel.com/docs/7.x/queries#debugging

Để ghi các truy vấn vào log, hãy enableQueryLog lên rồi ghi vào log bình thường nhé :D

1
2
3
4
5
6
// Toàn bộ truy vấn sẽ được ghi lại từ khi enableQueryLog()
DB::enableQueryLog();

App\User::where(['id'=>'1'])->delete();

Log::info(DB::getQueryLog());

Author

Ming

Posted on

2019-11-23

Updated on

2021-04-10

Licensed under

Comments