Laravel: Tìm hiểu về Query Builder (Phần 1)

https://viblo.asia/p/laravel-tim-hieu-ve-query-builder-phan-1-bJzKm0wD59N

Laravel: Tìm hiểu về Query Builder (Phần 1)

Bài đăng này đã không được cập nhật trong 4 năm

Introduction

Query builder cung cấp một giao thức thuận tiện, linh hoạt cho việc tạo và thực thi các truy vấn dữ liệu. Nó có thể sử dụng để thực hiện hầu hết các tính toán dữ liệu trong ứng dụng của bạn, và hoạt động trên tất các các hệ cơ sở dữ liệu được hỗ trợ.

Laravel query builder sử dụng PDO parameter binding để bảo vệ ứng dụng của bạn khỏi tấn công SQL injection. Vì vậy không cần phải xử lí các chuỗi khi truyền vào.

Retrieving Results

Retrieving All Rows From A Table

Bạn có thể sử dụng phương thức table trong DB facade để bắt đầu một query. Phương thức table trả về một instance của fluent query builder với bảng đã cho, cho phép bạn thêm nhiều ràng buộc vào truy vấn và lấy kết quả bằng phương thức get:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show a list of all of the application's users.
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::table('users')->get();

        return view('user.index', ['users' => $users]);
    }
}

Phương thức get trả về một Illuminate\Support\Collection chứa các kết quả mà mỗi kết quả là một instance của PHP StdClass. Bạn có thể truy cập mỗi cột giá trị bằng cách coi cột như là thuộc tính của một object:

foreach ($users as $user) {
    echo $user->name;
}

Retrieving A Single Row / Column From A Table

Nếu bạn chỉ cần lấy một row từ bảng dữ liệu, bạn có thể sử dụng phương thức first. Phương thức này sẽ trả về một đối tượng đơn StdClass:

$user = DB::table('users')->where('name', 'John')->first();

echo $user->name;

Nếu bạn không cần lấy toàn bộ row, bạn có thể lấy ra một giá trị từ một bản ghi sử dụng phương thức value. Phương thức này sẽ trả về giá trị của cột ngay tức khắc:

$email = DB::table('users')->where('name', 'John')->value('email');

Retrieving A List Of Column Values

Nếu bạn muốn lấy một Collection chứa các giá trị của một cột, bạn có thể sử dụng phương thức pluck. Trong ví dụ này, chúng ta sẽ lấy một Collection của các role titles:

$titles = DB::table('roles')->pluck('title');

foreach ($titles as $title) {
    echo $title;
}

Bạn cũng có thể chỉ định một cột key cho Collection trả về:

$roles = DB::table('roles')->pluck('title', 'name');

foreach ($roles as $name => $title) {
    echo $title;
}

Chunking Results

Nếu bạn phải làm việc với hàng nghìn record dữ liệu, hãy xem xét việc sử dụng phương thức chunk. Phương thức này sẽ lấy một đoạn nhỏ (chunk) các kết quả tại một thời điểm, và nạp từng chunk này vào một Closure để xử lí. Phương thức này vô cùng hữu ích cho việc viết Artisan commands để xử lí hàng nghìn record. Ví dụ hãy làm việc với toàn bộ bảng users với các chunks 100 bản ghi một lúc:

DB::table('users')->orderBy('id')->chunk(100, function ($users) {
    foreach ($users as $user) {
        //
    }
});

Bạn có thể dừng các chunk khác khỏi việc xử lí bằng cách trả về false từ Closure:

Aggregates

Query builder cũng cung cấp một tập hợp các phương thức khác nhau, như là count, max, min, avg, và sum. Bạn có thể gọi bất kì phương thức nào sau cấu trúc truy vấn của bạn:

$users = DB::table('users')->count();

$price = DB::table('orders')->max('price');

Dĩ nhiên, bạn cũng có thể kết những phương thức này với các mệnh đề khác để tạo nên câu truy vấn:

$price = DB::table('orders')
                ->where('finalized', 1)
                ->avg('price');

Selects

Specifying A Select Clause

Tất nhiên, có thể không phải lúc nào bạn cũng muốn lấy toàn bộ các cột từ một bảng. Sử dụng phương thức select bạn có thể chỉ định tùy chọn một mệnh đề select cho truy vấn:

$users = DB::table('users')->select('name', 'email as user_email')->get();

Phương thức distinct cho phép bạn ép buộc truy vấn trả về các kết quả phân biệt:

$users = DB::table('users')->distinct()->get();

Nếu bạn đã có sẵn một query builder instance và bạn muốn thêm một cột vào mệnh đề select, bạn có thể sử dụng phương thức addSelect:

$query = DB::table('users')->select('name');

$users = $query->addSelect('age')->get();

Raw Expressions

Đôi khi bạn có thể cần sử dụng một raw expression trong truy vấn. Những expression này sẽ được đưa vào truy vấn như các chuỗi, vì vậy hãy cẩn thận đừng tạo bất kì lỗi SQL injection nào. Để tạo một raw expression, bạn có thể sử dụng phương thức DB::raw:

$users = DB::table('users')
                     ->select(DB::raw('count(*) as user_count, status'))
                     ->where('status', '<>', 1)
                     ->groupBy('status')
                     ->get();

Joins

Inner Join Clause

Query builder cũng có thể được sử dụng để viết các câu lệnh join. Để thực hiện một "inner join" SQL cơ bản, bạn có thể sử dụng phương thức join trên một query builder instance. Tham số được truyền vào đầu tiên trong phương thức join là tên của bảng bạn join đến, trong khi tham số còn lại chỉ định các cột ràng buộc cho việc join. Tất nhiên như bạn có thể thấy, bạn có thể join nhiều bảng trong một truy vấn:

$users = DB::table('users')
            ->join('contacts', 'users.id', '=', 'contacts.user_id')
            ->join('orders', 'users.id', '=', 'orders.user_id')
            ->select('users.*', 'contacts.phone', 'orders.price')
            ->get();

Left Join Clause

Nếu bạn muốn thực hiện một "left join" thay vì "inner join", sử dụng phương thức leftJoin. Phương thức leftJoin này có cú pháp giống phương thức join:

$users = DB::table('users')
            ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
            ->get();

Cross Join Clause

Để thực hiện một "cross join", sử dụng phương thức crossJoin với tên của bảng bạn muốn cross join đến. Cross join sinh ra một cartesion product giữa bảng đầu tiên và bảng được join.

$users = DB::table('sizes')
            ->crossJoin('colours')
            ->get();

Advanced Join Clauses

Bạn cũng có thể chỉ định nhiều mệnh đề join nâng cao. Để bắt đầu, truyền một Closure như là tham số thứ 2 vào phương thức join. Closure sẽ nhận một đối tượng JoinClause cho phép bạn chỉ định các ràng buộc trong mệnh đề join:

DB::table('users')
        ->join('contacts', function ($join) {
            $join->on('users.id', '=', 'contacts.user_id')->orOn(...);
        })
        ->get();

Nếu bạn muốn sử dụng mệnh đề "where" trong truy vấn join của bạn, bạn có thể sử dụng phương thức whereorWhere trong join. Thay vì so sánh 2 cột, các phương thức này sẽ so sánh cột với một giá trị:

DB::table('users')
        ->join('contacts', function ($join) {
            $join->on('users.id', '=', 'contacts.user_id')
                 ->where('contacts.user_id', '>', 5);
        })
        ->get();

Unions

Query builder cũng cung cấp một cách nhanh chóng để "union" 2 truy vấn với nhau. Ví dụ, bạn có thể tạo một truy vấn khởi tạo, và sau đó sử dụng phương thức union để nối nó vào truy vấn thứ 2:

$first = DB::table('users')
            ->whereNull('first_name');

$users = DB::table('users')
            ->whereNull('last_name')
            ->union($first)
            ->get();

Tài liệu: https://laravel.com/docs/5.4/queries

Last updated