Toidicode.com

Toidicode.com

BASIC TO ADVANCE

Bài 30: Query với Eloquent ORM trong Laravel 8

Phần trước mình đã giới thiệu với mọi người về Eloquent Model trong Laravel rồi, phần này mình sẽ giới thiệu tiếp với mọi người về query, CRUD trong Eloquent Model.

1. Query DB trong Eloquent ORM.

Query

Khi bạn sử dụng Eloquent để query đến database thì bạn có thể coi nó như một bản nâng cấp của query builder với nhiều tính năng hay ho hơn.

Bạn có thể sử dụng phương thức all giống như trong query builder để lấy ra tất cả bản ghi của model nào đó trong Eloquent.

VD: Lấy ra tất cả dữ liệu trong model Flight.

use App\Models\Flight;

foreach (Flight::all() as $flight) {
    echo $flight->name;
}

Như ở trên mình đã nói thì các bạn có thể hiểu nôm na mỗi một eloquent tương tự như một query builder được chỉ định sẵn table (mặc dù chính xác là chúng được base trên 2 class khác nhau phần này mình sẽ nói sau) chính vì thế bạn cũng có thể build query qua các method như query builder và sử dụng phương thức get để lấy ra dữ liệu.

VD:

$flights = Flight::where('active', 1)
               ->orderBy('name')
               ->take(10)
               ->get();

Bạn có thể làm mới dữ liệu từ một eloquent đã được query trước đó bằng cách sử dụng phương thức fresh. Phương thức này sẽ thực hiện query lại đến database để lấy ra dữ liệu mới nhất trong database của bản ghi tương ứng.

VD:

$flight = Flight::where('number', 'FR 900')->first();

$freshFlight = $flight->fresh();

Tương tự bạn có thể sử dụng phương thức refresh để lấy ra giữ liệu mới nhất của bản ghỉ đó trong database đồng thời nó sẽ lấy luôn cả dữ liệu mới của các relationship nếu có.

VD:

$flight = Flight::where('number', 'FR 900')->first();

$flight->number = 'FR 456';

$flight->refresh();

$flight->number; // "FR 900"

Collection

Nếu như kết quả truy vấn của bạn trả về nhiều hơn một bản ghi thì Eloquent sẽ tự động convert nó sang collection để tiện cho mọi người xử lí dữ liệu.

VD:

$flights = Flight::where('destination', 'Paris')->get();

$flights = $flights->reject(function ($flight) {
    return $flight->cancelled;
});

Chunk data

Trong eloquent bạn có thể sử dụng phương thức chunk để chunk data nhỏ ra để tiện cho việc xử lý.

VD:

use App\Models\Flight;

Flight::chunk(200, function ($flights) {
    foreach ($flights as $flight) {
        //
    }
});

Hoặc bạn có thể sử dụng phương thức chunkById để thực hiện chunking data theo column id.

VD:

Flight::where('departed', true)
        ->chunkById(200, function ($flights) {
            $flights->each->update(['departed' => false]);
        }, $column = 'id');

2. Query nâng cao.

Eloquent cho phép chúng ta lồng các query khác vào trong một query (cái này gọi là subquery) một cách rất đơn giản.

Slect subquery

Để có thể lồng một query khác vào trong câu lệnh select bạn có thể truyền thêm một builder khác vào trong một trong 2 phương thức select hoặc addSelect.

VD:

use App\Models\Destination;
use App\Models\Flight;

return Destination::addSelect(['last_flight' => Flight::select('name')
    ->whereColumn('destination_id', 'destinations.id')
    ->orderByDesc('arrived_at')
    ->limit(1)
])->get();

oderBy subquery

Tương tự bạn cũng có thể order theo một subquery.

VD:

return Destination::orderByDesc(
    Flight::select('arrived_at')
        ->whereColumn('destination_id', 'destinations.id')
        ->orderByDesc('arrived_at')
        ->limit(1)
)->get();

where subquery

Bạn cũng có thể where với subquery.

VD:

Products::whereIn('id', function($query){
    $query->select('paper_type_id')
    ->from(with(new ProductCategory)->getTable())
    ->whereIn('category_id', ['223', '15'])
    ->where('active', 1);
})->get();

...

3. Insert, update, delete dữ liệu.

Eloquent cung cấp khá nhiều phương thức để giúp bạn insert dữ liệu vào trong database.

create

Bạn có thể insert dữ liệu sử dụng phương thức create với cú pháp:

ModelName::create($data);

Trong đó: $data là một mảng chứa dữ liệu cần insert với key là tên cột và giá trị là giá trị dữ liệu của cột đó. Tuy nhiên bạn cần phải đảm bảo các column bạn chỉ định cần phải được xuất hiện trong $fillable. Phương thức này sẽ trả về dữ liệu là một instance của model chưa dữ liệu của record vừa insert.

VD:

use App\Models\Flight;

$flight = Flight::create([
    'name' => 'London to Paris',
]);

insert

Phương thức này tương tự như phương thức create ở trên. Chỉ có điều là phương thức này sẽ trả về true nếu insert thành công và false nếu không thành công.

VD:

use App\Models\Flight;

$successed = Flight::insert([
    'name' => 'London to Paris',
]);

save

Bạn cũng có thể khởi tạo một object của model rồi set dữ liệu cho các cột sau đó sử dụng phương thức save để insert dữ liệu vào trong database.

VD:

$flight = new Flight;

$flight->name = $request->name;

$flight->save();

Trong trường hợp object của bạn đang là một instance của một record trong DB thì phương thức save sẽ update dữ liệu thay vì insert.

VD:

$flight = Flight::first();

$flight->name = $request->name;

$flight->save();

firstOrCreate

Phương thức firstOrCreate có tác dụng lấy ra bản ghi đầu tiên của dữ liệu phù hợp với query, nếu không có nó sẽ insert dữ liệu query vào DB và trả về bản ghi đó.

Cú pháp:

ModelName::firstOrCreate($attributes, $values);

Trong đó:

  • $attribute là một mảng chứa các điều kiện bạn muốn query để tìm kiếm bản ghi trong DB.
  • $values là mảng chứa dữ liệu sẽ được insert vào trong database khi bản ghi cần tìm không tồn tại trong DB.

VD:

use App\Models\Flight;

// Sẽ trả về bản ghi có name là 'London to Paris' hoặc insert dữ liệu này vào trong DB rồi trả về.
$flight = Flight::firstOrCreate([
    'name' => 'London to Paris'
]);

// Sẽ trả về bản ghi có name là 'London to Paris' hoặc insert dữ liệu name, delayed và delayed vào trong DB rồi trả về.
$flight = Flight::firstOrCreate(
    ['name' => 'London to Paris'],
    ['delayed' => 1, 'delayed' => '11:30']
);

firstOrNew

Phương thức này cũng tương tự như phương thức firstOrCreate ở trên, chỉ khác một điều là nếu như điều kiện where không tồn tại trong DB thì nó sẽ chỉ trả về instance của Model đó mà không insert dữ liệu vào trong DB.

VD:

use App\Models\Flight;

$flight = Flight::firstOrNew([
    'name' => 'London to Paris'
]);

$flight = Flight::firstOrNew(
    ['name' => 'Tokyo to Sydney'],
    ['delayed' => 1, 'arrival_time' => '11:30']
);

updateOrCreate

Phương thức này có cú pháp sử dụng như phương thức firstOrNewfirstOrCreate, chỉ có điều là phương thức này sẽ thực thi update dữ liệu nếu có dữ liệu matching với điều kiện, hoặc sẽ insert dữ liệu nếu như không có bản ghi nào matching với điều kiện.

VD:

$flight = Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99, 'discounted' => 1]
);

delete

Phương thức delete có tác dụng delete bản ghi trong DB.

VD: Xóa bản ghi trong bảng flights có id=1.

use App\Models\Flight;

$flight = Flight::find(1);

$flight->delete();

destroy

Phương thức destroy sẽ thực thi delete dữ liệu trong DB với dữ liệu truyền vào phương thức là giá trị của primary key của model đó.

VD: Xóa bản ghi trong bảng flights có id=1.

Flight::destroy(1);

Bạn cũng có thể xóa nhiều bản ghi bằng các chuyền các giá trị vào trong phương thức.

VD:

Flight::destroy(1, 2, 3);

// hoặc

Flight::destroy([1, 2, 3]);

// hoặc

Flight::destroy(collect([1, 2, 3]));

4. Soft Delete.

Ngoài ra bạn cũng có thể sử dụng tính năng soft delete để thực hiện xóa mềm các bản ghi trong DB. Khi sử dụng xóa mềm thì Eloquent sẽ gán giá trị cho cột deleted_at là thời gian mà bạn thực hiện xóa bản ghi.

Để sử dụng tính năng soft delete trong Eloquent bạn cần phải thêm trait Illuminate\Database\Eloquent\SoftDeletes vào trong model.

VD:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;
}

Chú ý: Bạn cần phải chắc chắn trong table của bạn có cột deleted_at có kiểu dữ liệu là timestamp và nullable. Bạn cũng có thể sử dụng migration để thêm sort delete với phương thức softDeletes.

Trong trường hợp bạn muốn kiểm tra xem instance nào đó đã được xóa mềm hay chưa bằng cách sử dụng phương thức trashed.

VD:

if ($flight->trashed()) {
    //
}

Bạn cũng có thể khôi phục lại một bản ghi đã được xóa mềm bằng cách sử dụng phương thức restore.

VD:

$flight->restore();

Để lấy ra tất cả các bản ghi kể cả bản ghi đã được xóa mềm trong table bạn có thể sử dụng phương thức withTrashed.

VD: restore bản ghi có airline_id =1.

Flight::withTrashed()
        ->where('airline_id', 1)
        ->restore();

Trong trường hợp bạn muốn xóa vĩnh viễn một bản ghi nào đó ra khỏi table, bạn có thể sử dụng phương thức forceDelete.

VD: Xóa vĩnh viễn bản ghi có id=1.

Flight::find(1)->forceDelete();

Để lấy ra các bản ghi đã được xóa mềm trong table bạn có thể sử dụng phương thức onlyTrashed. Phương thức này thực ra sẽ thêm một where query deleted_at is not null vào trong query của bạn.

VD:

$flights = Flight::onlyTrashed()
                ->where('airline_id', 1)
                ->get();

5. Lời kết.

Query liên quan đến Eloquent ORM sau này sẽ sử dụng xuyên suốt dự án của bạn, nên các bạn cần tìm hiểu kĩ về chúng.

Đăng ký nhận tin.

Chúng tôi chỉ gửi tối đa 2 lần trên 1 tháng. Tuyên bố không spam mail!

Vũ Thanh Tài

About author
The best way to learn is to share
Xem tất cả bài đăng

0 Comments

Bài viết chưa có ai bình luận, hãy là người đầu tiên đi bạn!

Bình luận

Captcha