Laravel Tutorial

Bài 28: Query với Eloquent ORM trong Laravel

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.

1. Query cơ bản

all()

Lấy ra tất cả bản ghi của model  trong Eloquent

Ví dụ: Lấy ra tất cả dữ liệu trong model Flight

use App\Models\Flight;

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

get()

Lấy dữ liệu từ model trong Eloquent

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

fresh()

Làm mới dữ liệu từ một eloquent đã được query trước đó. 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

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

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ó

$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

$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ý

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

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

2. Sub Query

# select 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

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();

# orderby subquery

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

# where subquery

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

# 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

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

use App\Models\Flight;

$flight = 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

$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

$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 đó

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

Ví dụ:

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

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 firstOrNew và firstOrCreate, 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

$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

Ví dụ: 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 đó

Ví dụ: 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

Flight::destroy(1, 2, 3);
// Hoặc
Flight::destroy([1, 2, 3]);
// Hoặc
Flight::destroy(collect([1, 2, 3]));

# Soft delete

<?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

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

$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.

Ví dụ: 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

Ví dụ: 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

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

 

Leave a Comment