hướng dẫn tối ưu hoá Hiệu xuất hoạt động của Laravel nhằm tăng tốc độ xử lý của website, nếu bạn đang thiết kế website bằng Laravel thì đây quả thật là 1 bài viết hữu ích đấy.
BelongsTo Default Models
Hãy xem bạn có Post
phụ thuộc vào Author
và ở Blade code của bạn:
{{ $post->author->name }}
Nhưng điều gì sẽ xảy ra nếu author bị xóa, hoặc không được xét vì 1 vài lý do? Bạn sẽ gặp 1 error, một cái gì đó giống như “property of non-object”
. Dĩ nhiên, bạn có thể ngăn chặn nó bằng cách:
{{ $post->author->name ?? '' }}
Tuy nhiên, bạn có thể thực hiện nó trên Eloquent relationship:
public function author()
{
return $this->belongsTo('App\Author')->withDefault();
}
Trong ví dụ này, author()
relation sẽ trả về một empty App\Author
model nếu không có author nào được đính kèm vào bài đăng.
Hơn nữa, chúng ta có thể gán các giá trị default property cho default model đó.
public function author()
{
return $this->belongsTo('App\Author')->withDefault([
'name' => 'Guest Author'
]);
}
Order by Mutator
Hãy tưởng tượng bạn có điều này:
function getFullNameAttribute()
{
return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
}
Bây giờ, bạn muốn order by theo full_name
? Nó sẽ không hoạt động:
$clients = Client::orderBy('full_name')->get(); // doesn't work
Giải pháp khá đơn giản. Chúng ta cần order kết quả sau khi chúng ta get
chúng:
$clients = Client::get()->sortBy('full_name'); // works!
Lưu ý tên function là khác nhau, nó không phải là orderBy
mà nó là sortBy
.
Default ordering in global scope
Điều gì sẽ xảy ra nếu bạn muốn User::all()
luôn được sắp xếp theo field name
? Bạn có thể chỉ định một global scope. Hãy quay lại method boot()
mà chúng ta đã đề cập ở trên.
protected static function boot()
{
parent::boot();
// Order by name ASC
static::addGlobalScope('order', function (Builder $builder) {
$builder->orderBy('name', 'asc');
});
}
Đọ thêm về .
Raw query methods
Đôi khi chúng ta cần thêm raw query vào Eloquent statement của chúng ta. May mắn, có functions cho điều này:
// 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();
Replicate: make a copy of a row
Không cần phải giải thích sâu, ở đây, cách tốt nhất để tạo một bản sao của cơ sở dữ liệu:
$task = Tasks::find(1);
$newTask = $task->replicate();
$newTask->save();
Chunk() method for big tables
Không chính xác là Eloquent related, nó hơn về Collection, nhưng vẫn mạnh mẽ để xử lý các bộ dữ liệu lớn hơn, bạn có thể chia nhỏ chúng thành từng mảnh.
Thay vì:
$users = User::all();
foreach ($users as $user) {
// ...
Bạn có thể làm:
User::chunk(100, function ($users) {
foreach ($users as $user) {
// ...
}
});
Create additional things when creating a model
Tất cả chúng ta đều biết câu lệnh Artisan này:
php artisan make:model Company
Nhưng bạn có biết có 3 flags hữu ích để generate các file có liên quan tới model?
php artisan make:model Company -mcr
- -m sẽ tạo 1 migration file
- -c sẽ tạo 1 controller
- -r sẽ chỉ định rằng controller đó thành resourceful
Override updated_at when saving
Bạn có biết phương thức save()
có thể chấp nhận các parameter không? Kết quả là chúng ta có thể nói với nó về việc "ignore" updated_at
chức năng mặc định để được fill vào với timestamp hiện tại. Hãy xem:
$product = Product::find($id);
$product->updated_at = '2019-01-01 10:00:00';
$product->save(['timestamps' => false]);
Ở đây, chúng ta đã ghi đè default updated_at
với define được xác định trước.
Kết quả của hàm update() là gì?
Bạn đã bao giờ tự hỏi những gì code này thực sự return?
$result = $products->whereNull('category_id')->update(['category_id' => 2]);
Ý tôi là, update được thực hiện trong cơ sở dữ liệu, nhưng biến $result
chứa những gì?
Câu trả lời là nhiều rows bị thay đổi, Vì vậy, nếu bạn cần kiểm tra xem có bao nhiêu row bị ảnh hưởng, bạn không cần phải gọi bất cứ điều gì khác ngoài phương thức update()
, nó sẽ trả về cho bạn con số này.
Transform brackets bên trong Eloquent query
Điều gì xảy ra nếu bạn có and-or mix trong SQL query của bạn, giống như thế này:
... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
Làm thế nào để dịch nó sang Eloquent? đây là 1 cách sai:
$q->where('gender', 'Male');
$q->orWhere('age', '>=', 18);
$q->where('gender', 'Female');
$q->orWhere('age', '>=', 65);
Order sẽ không chính xác. Cách đúng phức tap hơn một chút, sử dụng các hàm clossure như sub-queries:
$q->where(function ($query) {
$query->where('gender', 'Male')
->where('age', '>=', 18);
})->orWhere(function($query) {
$query->where('gender', 'Female')
->where('age', '>=', 65);
})
orWhere với nhiều giá trị
Cuối cùng, bạn có thể pass một array của paramenter vào orWhere()
. Cách thông thường:
$q->where('a', 1);
$q->orWhere('b', 2);
$q->orWhere('c', 3);
Bạn có thể làm nó giống như sau:
$q->where('a', 1);
$q->orWhere(['b' => 2, 'c' => 3]);
Hy vọng những chia sẻ trên có thể giúp bạn có giúp ích cho bạn trong việc lập trình với Laravel.
Chúc các bạn học tốt làm chủ Laravel