Hiểu về sole() Query Builder Method trong Laravel

sole() là một phương thức query builder được giới thiệu ở Laravel 8.23, phương thức này trả về một single record và Object của sole() có relation giống như first() method . Trước sole() luôn là một điều kiện where

Sử dụng Sole khi nào?

Sole được sử dụng khi bạn cần một single record từ query và query đó cũng matching với duy nhất một record. Lợi ích của việc này là khi bạn mong muốn câu truy vấn của bạn luôn luôn có duy nhất một bản ghi, không hơn không kém record. Nếu câu query của bạn trả về ít hơn hoặc nhiều hơn 1 bản ghi thì nó sẽ bắn ra lỗi Laravel throws exception.

Để hiểu rõ hơn điều này chúng ta cùng tìm hiểu Case Study đưới đây. Tôi sẽ chia ra ba trường hợp như sau

  1. Chỉ có 1 bản ghi matching với câu query
  2. Không có bản ghi nào matching
  3. Có nhiều hơn 1 bản ghi matching

Quick Demo

Trước tiên, bạn tạo một project Laravel với câu lệnh Composer sau

composer create-project laravel/laravel sole-demo
cd sole-demo


Tiếp theo, tạo một model Bookmigration tương ứng

php artisan make:model -m Book

Cuối cùng bạn mở file migration lên và định nghĩa column cho bảng books như sau

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('summary');
            $table->dateTime('published_at')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('books');
    }
}

Trong Book model khai báo thêm thuộc tính $guarded

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    use HasFactory;

    protected $guarded = [];
}

Ok, mọi thứ đã xong. Bây giờ bạn chạy migration để tạo bảng

php artisan migrate:fresh

Để bắt đầu với sole() chúng ta sử dụng Tinker để tạo mới 1 record và thực hiện query với bảng books bằng cách chạy lệnh này lên

php artisan tinker

Sau đó chạy lệnh này để thêm mới 1 record vào bảng books

Book::create([
    'title' => 'War of the Worlds',
    'summary' => 'Example summary'
]);


Bảng books đã có dữ liệu, chúng ta sẽ thử first()get() method với câu query sau xem điều gì sẽ sảy ra .

Với get() method

Book::where('title', 'like', '%War%')->get();

Kết quả:

Illuminate\Database\Eloquent\Collection {#4264
 all: [
   App\Models\Book {#4209
     id: 1,
     title: "War of the Worlds",
     summary: "Example summary",
     published_at: null,
     created_at: "2021-01-21 22:14:29",
     updated_at: "2021-01-21 22:14:29",
   },
 ],
}

Với first() method

Book::where('title', 'like', '%War%')->first();

Kết quả:

App\Models\Book {#4210
     id: 1,
     title: "War of the Worlds",
     summary: "Example summary",
     published_at: null,
     created_at: "2021-01-21 22:14:29",
     updated_at: "2021-01-21 22:14:29",
   }

Cả get() và first() đều là những phương thức phổ biến trong Laravel, nhìn vào kết quả sẽ không có gì đặc biệt ở đây cả.

Với sole() method

Book::where('title', 'like', '%War%')->sole();

Kết quả:

App\Models\Book {#3647
  id: 1,
  title: "War of the Worlds",
  summary: "Example summary",
  published_at: null,
  created_at: "2021-01-21 22:14:29",
  updated_at: "2021-01-21 22:14:29",
}

Kết quả cũng không khác gì sử dụng first() đúng không? Vậy sole() khác biệt ở chỗ nào? Chúng ta tiếp tục insert thêm bản ghi thứ 2 vào bảng books nhé

Book::create([
    'title' => 'War and Peace',
    'summary' => 'Example summary'
]);

Lúc này trong books đã có 2 bản ghi và câu query này sẽ trả về 2 record vì điều kiện là like

Book::where('title', 'like', '%War%')->get()


Chúng ta thay thế get() thành sole() như sau

Book::where('title', 'like', '%The War')->sole();

Kết quả: Các bạn sẽ nhìn thấy lỗi này

Illuminate\Database\MultipleRecordsFoundException

Lý do là sole() chỉ được thực hiện khi câu query trên trả về 1 bản ghi matching, nhưng vì điều kiện là like nên chúng ta có 2 bản ghi được trả về dẫn đến khi dùng sole() sẽ bị lỗi

Hy vọng qua bài này các bạn có cái nhìn rõ hơn về sole() method trong Laravel!

Thanks!

Khôi Phạm
Khôi Phạm

Share is way to learn

SUNTECH VIỆT NAM   Đăng ký để nhận thông báo mới nhất