post-image

20 Laravel Eloquent Tips and Tricks

Tổng quan

Lời nói đầu

Xin chào mọi người.Đầu tiên mình cảm ơn các bạn đang đọc bài chia sẻ của mình,và mình tin là những bạn đang đọc bài viết này đều là những bạn đang làm việc với Laravel Framework. Như các bạn cũng biết thì laravel là Framework rất mạnh của php và được đa số lập trình viên PHP sử dụng.

Thực tế Laravel có rất nhiều tính năng hay ho và vô cùng hữu ích giúp cho các lập trình viên có thể giảm tải được thời gian code và làm cho code chặt chẽ hơn.một chức năng vô cùng hữu ích đó là Eloquent ORM, hẳn thì Eloquent ORM đã rất quen thuộc với các bạn đúng không nào, có thế nói đây là tính năng mà bất kỳ project nào sử dụng Laravel cũng phải dùng đến.

ORM là gì?

ORM (Object Relational Mapping) là một kỹ thuật lập trình dùng để chuyển đổi dữ liệu giữa một hệ thống không hướng đối tượng như cơ sở dữ liệu sang hệ thống hướng đối tượng như lập trình hướng đôi tượng trong PHP. Kỹ thuật này tạo ra các đối tượng CSDL ảo có thể được lập trình trong mã nguồn và có nhiều ưu điểm như mã nguồn trở lên rõ ràng và dễ bảo trì, dễ dàng thao tác với dữ liệu và thực hiện việc tối ưu hệ thống thông qua việc sử dụng bộ đệm…

Các công việc khó hoặc không thể xử lý ở database layer sẽ được đưa lên lớp ứng dụng. Tuy nhiên hôm nay mình sẽ không đi sâu vào tìm hiểu ORM là gì, mà trong bài này mình sẽ chia sẻ 20 tips rất hay ho mà có thể nhiều bạn không để ý khi sử dụng Eloquent ORM. Bắt đầu nhé.

20 Laravel Eloquent Tips and Tricks

1. Increments and Decrements

bình thường chúng ta sử dụng câu lệnh như sau:

$article = Article::find($article_id); $article->read_count++; $article->save();
Code language: PHP (php)

thay vì sử dụng những câu lệnh này các ban có thể viết như sau:

$article = Article::find($article_id); $article->increment('read_count');
Code language: PHP (php)

hoặc

Article::find($article_id)->increment('read_count'); Article::find($article_id)->increment('read_count', 10); // +10 Product::find($produce_id)->decrement('stock'); // -1
Code language: PHP (php)

2. XorY methods

Eloquent có vài function là sự sự kết hợp của 2 methods theo kiểu “please do X, otherwise do Y .”

findOrFail

bình thường chúng ta sẽ viết như sau:

$user = User::find($id); if (!$user) { abort (404); }
Code language: PHP (php)

thay vì vậy các bạn có thể viết:

$user = User::findOrFail($id);
Code language: PHP (php)

firstOrCreate()

thay vì các bạn sử sự phương thức create như này:

$user = User::where('email', $email)->first(); if (!$user) { User::create([ 'email' => $email ]); }
Code language: PHP (php)

các bạn có thể sử dụng hàm firstOrCreate:

$user = User::firstOrCreate(['email' => $email]);
Code language: PHP (php)

3.Model boot() method

trong function boot này bạn có thể ghi đề những hành vi mặc định của Eloquent Model

class User extends Model { public static function boot() { parent::boot(); static::updating(function($model) { // do some logging // override some property like $model->something = transform($something); }); } }
Code language: PHP (php)

4.Relationship with conditions and ordering

bình thường thì chúng ta vẫn định nghĩa quan hệ trong model như sau:

public function users() { return $this->hasMany('App\User'); }
Code language: PHP (php)

tuy bạn có biết là chúng ra có thể thêm vào câu điều kiện và sắp xếp như sau:

public function approvedUsers() { return $this->hasMany('App\User')->where('approved', 1)->orderBy('email'); }
Code language: PHP (php)

như ở thì các ta sẽ query được đến các user đã approved và để về thứ tự sắp xếp theo email.

5.Model properties: timestamps, appends etc.

ở đây có vài tham số của một Eloquent Model được coi là thuộc tính của của Model class.kiểu khai báo thường dùng là:

class User extends Model { protected $table = 'users'; protected $fillable = ['email', 'password']; // which fields can be filled with User::create() protected $dates = ['created_at', 'deleted_at']; // which fields will be Carbon-ized protected $appends = ['field1', 'field2']; // additional values returned in JSON protected $primaryKey = 'uuid'; // it doesn't have to be "id" public $incrementing = false; // and it doesn't even have to be auto-incrementing! protected $perPage = 25; // Yes, you can override pagination count PER MODEL (default 15) const CREATED_AT = 'created_at'; const UPDATED_AT = 'updated_at'; // Yes, even those names can be overridden public $timestamps = false; // or even not used at all }
Code language: PHP (php)

6. Find multiple entries

Có lẽ các bạn đều biết phương thức find() đúng không? và nó thường được sử dụng như thế này:

$user = User::find(1);
Code language: PHP (php)

tuy nhiên bạn có biết rằng hàm find() có thể tìm kiếm multiple entries như sau:

$users = User::find([1,2,3]);
Code language: PHP (php)

7. WhereX

câu truy vấn điều kiện hay được dùng là:

$users = User::where('approved', 1)->get();
Code language: PHP (php)

cùng với kết quả đó,bạn có thể sử dụng câu lệnh sau:

$users = User::whereApproved(1)->get();
Code language: PHP (php)

bạn có thể thay đổi bất kỳ trường nào và append nó như là một hậu tố của where.và đã có vài phương thức đã được định nghĩa trước liên quan đến date/time

User::whereDate('created_at', date('Y-m-d')); User::whereDay('created_at', date('d')); User::whereMonth('created_at', date('m')); User::whereYear('created_at', date('Y'));
Code language: PHP (php)

8. Order by relationship

hơi khó một chút.nếu có vấn đề như sau: bạn sẽ làm gì nếu bạn có forums topics nhưng bạn muốn sắp xếp chúng theo thứ bởi bài Post mới nhất.Có một yêu cầu khá phổ biến đó là những mài đăng mới nhất sẽ được cho lên đầu.Và các thược hiện sẽ là:
tại Model:

public function latestPost() { return $this->hasOne(\App\Post::class)->latest(); }
Code language: PHP (php)

Tại Controller:

$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
Code language: PHP (php)

9. Eloquent::when() – no more if-else’s

rất nhiều bạn trong chung ta viết câu lệnh điều kiện if-else như sau:

if (request('filter_by') == 'likes') { $query->where('likes', '>', request('likes_amount', 0)); } if (request('filter_by') == 'date') { $query->orderBy('created_at', request('ordering_rule', 'desc')); }
Code language: PHP (php)

có một cách tố hơn là dùng when()

$query = Author::query(); $query->when(request('filter_by') == 'likes', function ($q) { return $q->where('likes', '>', request('likes_amount', 0)); }); $query->when(request('filter_by') == 'date', function ($q) { return $q->orderBy('created_at', request('ordering_rule', 'desc')); });
Code language: PHP (php)

nếu bạn thấy nó không ngắn và tối ưu hơn, cách tốt nhất là sử dụng tham sô(parammeters);

$query = User::query(); $query->when(request('role', false), function ($q, $role) { return $q->where('role_id', $role); }); $authors = $query->get();
Code language: PHP (php)

10. BelongsTo Default Models

ví dụ bạn có một bài Post thuộc về một Author. thì code trong file blade se là:

{{ $post->author->name }}
Code language: PHP (php)

nhưng nếu trong trường hợp mà Author này bị xóa, hoặc không được set vì một vài lý do thì bạn sẽ bị lỗi. tất nhiên là chúng ta các cách phòng ngừa là:

{{ $post->author->name ?? '' }}
Code language: PHP (php)

tuy nhiên bạn có thể làm điều đó trong Eloquent relationship:

public function author() { return $this->belongsTo('App\Author')->withDefault(); }
Code language: PHP (php)

trong ví dụ trên author() sẽ trả về model App\Author rỗng nếu không có author nào được đính kèm với bài Post.
hơn nữa thì chúng ta có thể gán giá trị thuộc tính mặc định cho Model mặc định

public function author() { return $this->belongsTo('App\Author')->withDefault([ 'name' => 'Guest Author' ]); }
Code language: PHP (php)

11. Order by Mutator

tưởng tượng rằng bạn có như sau:

function getFullNameAttribute() { return $this->attributes['first_name'] . ' ' . $this->attributes['last_name']; }
Code language: PHP (php)

bây giờ. bạn muốn sắp sếp theo full_name

$clients = Client::orderBy('full_name')->get(); // doesn't work
Code language: PHP (php)

câu lệnh trên sẽ không chạy.
giải pháp ở đây khá đơn giản.chúng ta phải kết quả sau khi đã lấy được

$clients = Client::get()->sortBy('full_name'); // works!
Code language: PHP (php)

chú ý là tên function hơi khác một chút. không phải là orderBy mà là sortBy.

12. Default ordering in global scope

bạn sẽ làm gì nếu User::all() luôn luôn sắp xếp theo trường name? bạn có thể gán nó cho một global scope.hãy trở lại với hàm boot()

protected static function boot() { parent::boot(); // Order by name ASC static::addGlobalScope('order', function (Builder $builder) { $builder->orderBy('name', 'asc'); }); }
Code language: PHP (php)

13. Raw query methods

thỉnh thoảng chúng ta muôn thêm raw queries vào trong câu lệnh Eloquent. may mắn là chúng ta có các hàm cho nó.

// whereRaw $orders = DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get(); // havingRaw Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get(); // orderByRaw User::where('created_at', '>', '2016-01-01') ->orderByRaw('(updated_at - created_at) desc') ->get();
Code language: PHP (php)

14. Replicate: make a copy of a row

đây là cách để tạo bản sao của một bản ghi

$task = Tasks::find(1); $newTask = $task->replicate(); $newTask->save();
Code language: PHP (php)

15.Chunk() method for big tables

Không phải chính xác là Eloquent, nhưng mà vẫn rất là mạnh mẽ để xử lý các tập dữ liệu lớn. chúng ta có thể chia nhỏ thành nhiều phần.
Thường chúng ta vẫn hay viết:

$users = User::all(); foreach ($users as $user) { // ...
Code language: PHP (php)

Thay vào đó bạn có thể viết lại như sau:

User::chunk(100, function ($users) { foreach ($users as $user) { // ... } });
Code language: PHP (php)

16.Create additional things when creating a model

Chúng ta đều biết đến câu lệnh Artisan này đúng không

php artisan make:model Company
Code language: CSS (css)

nhưng bạn có biết là chúng ta có 3 flags vô cùng hữu ích để tạo những files có quan hệ với Model

php artisan make:model Company -mcr
Code language: CSS (css)
  • -m tương ứng là sẽ tao ra file migration
  • -c tương ứng là sẽ tạo file Controller
  • -r tương là sẽ biểu thị rằng Controller được tạo ra là Resource Controller

17.Override updated_at when saving

Bạn có biết rằng phương thức ->save() có thể nhận vào các tham số.Với kết quả nhận được, bạn có thể ignore phương thức update_at của timestamps.

$product = Product::find($id); $product->updated_at = '2019-01-01 10:00:00'; $product->save(['timestamps' => false]);
Code language: PHP (php)

chúng ta vừa override updated_at với giá trị được định nghĩa trước.

18.What is the result of an update()?

Các bạn đã bao giờ tự hỏi đoạn code dưới đây sẽ trả về giá trị gì không?

$result = $products->whereNull('category_id')->update(['category_id' => 2]);
Code language: PHP (php)

ý của mình là chúng ta đang thực hiện chức năng update. nhưng giá trị $result trả về chứa cái gì.
Câu trả lời chính là giá trị của row bị ảnh hưởng của phương thức update này.Nếu như các bạn muốn kiểm tra xem có bao nhiêu row bị ảnh hưởng bởi lệnh update này thì bạn cũng không cần phải gọi bất kỳ hàm nào nữa. update() sẽ trả về giá trị cho bạn.

19. Transform brackets into an Eloquent query

Điều gì sẽ xảy ra khi bạn lết hợp and-or trong câu truy vấn SQL như thế này:

... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
Code language: JavaScript (javascript)

Làm thế nào để chuyển câu truy vấn trên vào trong Eloquent.Cách dưới đây là một cách biến đổi sai

$q->where('gender', 'Male'); $q->orWhere('age', '>=', 18); $q->where('gender', 'Female'); $q->orWhere('age', '>=', 65);
Code language: PHP (php)

Thứ tự thực hiện sẽ sai. Cách biến đổi đúng thì phúc tạp hơn một chút.Chúng ta dùng Closure Function như là sub-queries.

$q->where(function ($query) { $query->where('gender', 'Male') ->where('age', '>=', 18); })->orWhere(function($query) { $query->where('gender', 'Female') ->where('age', '>=', 65); })
Code language: PHP (php)

20. orWhere with multiple parameters

Và cuối cùng.Bạn có thể chuyền vào một mảng các tham số vào orWhere.
Bình thường chúng ta vẫn hay viết như sau:

$q->where('a', 1); $q->orWhere('b', 2); $q->orWhere('c', 3);
Code language: PHP (php)

Thay vì vậy, các bạn có thể viết lại như sau:

$q->where('a', 1); $q->orWhere(['b' => 2, 'c' => 3]);
Code language: PHP (php)

Lời cảm ơn

Đến đây mình đã chia sẻ với các bạn 20 Eloquent Trick and Tip. Có thể còn nhiều những Tricks và Tip nữa nhưng với bài chia sẻ này mình hi vọng có thể giúp các bạn tối ưu hơn về các sử dụng câu truy vấn trong Laravel. Cảm ơn các bạn đã theo dõi bài đọc của mình. Thanks You!

Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Tham khảo: Viblo

Leave a Reply

Your email address will not be published. Required fields are marked *