Người viết: Hong Quan
Như tiêu đề, đây là hậu truyện của phần “Laravel còn giấu diếm chúng ta những gì” khá là thành công trước đó. Cho bạn nào vừa ở trên rừng xuống thì Laravel đã cho ra mắt phiên bản 6.0 cách đây ít ngày, bản thân mình còn chưa đọc hết document của các phiên bản trước nữa mà đã thấy có 1 đống thứ hay ho ít người biết rồi.
Có lẽ series này sẽ được làm thành hẳn 1 franchise rồi up to saga giống như Avengers luôn, vì các phiên bản mới của Laravel đang liên tục được cập nhật và cứ mỗi lần cập nhật là có thêm một cơ số những thứ mà mấy ông dev rảnh rỗi thêm vào.
Anyway, let’s begin!
Default Model
Nếu bạn đang có mộn relation ví dụ như belongsTo, MorphOne hoặc HasOne, nó có thể trả về kết quả null. Trong trường hợp đó, bạn có thể đặt giá trị mặc định bằng phương thức withDefault()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public function user() { return $this->belongsTo('App\User')->withDefault(); } //or public function user() { return $this->belongsTo('App\User')->withDefault([ 'name' => 'Guest Author', ]); } // or public function user() { return $this->belongsTo('App\User')->withDefault(function ($user) { $user->name = 'Guest Author'; }); } |
Cache Forever
Nếu bạn đang sử dụng chức năng lưu Cache, sẽ có đôi lúc bạn muốn dữ liệu của mình được lưu lâu dài, rồi xóa lúc nào cần thiết, trong trường hợp đó chỉ cần sử dụng phương thức rememberForever()
như này:
1 2 3 4 5 |
$value = Cache::rememberForever('users', function () { return DB::table('users')->get(); }); |
Nhân bản và làm mới Model
Đầu tiên là làm mới một Model, bạn có thể sử dụng phương thức fresh()
hoặc refresh()
để làm mới một Model hoặc, đưa Model đó về trạng thái ban đầu nếu có “nhỡ tay” thay đổi mất
Xem ví dụ cho dễ hiểu:
1 2 3 4 5 6 |
$user = \App\User::first(); $user->name = "Something new"; $user = $user->fresh(); dump($user->name); // 'Something new' |
Thật sự không hiểu lắm ông dev nào rảnh rỗi nghĩ ra cái này, cá nhân mình thấy nó chưa hữu dụng ở chỗ nào mà chỉ để biết cho vui thôi
Tiếp cái dưới đây mới có ích này. Nếu bạn muốn nhân bản một Model, hãy sử dụng phương thức replicate()
, đừng như mình get dữ liệu ra xong đưa lại vào 1 mảng giống hệt vì cần thay đổi một số dữ liệu xong lại lưu vào DB
1 2 3 4 5 |
$new = SomeModel::first()->replicate(); $new->column = "Some thing"; $new->save(); |
Hơn thế nữa, phương thức này còn cho phép bỏ qua một số trường mà bạn không muốn hoặc không nên được duplicate
1 2 3 4 5 |
$new = User::first()->replicate(['password']); $new->name = "Peter Parker" $new->save(); |
Có 6 phương thức routing chính mà chúng ta hay sử dụng đó là:
1 2 3 4 5 6 7 8 |
Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback); // hiếm dùng vc, mà chắc chả ai để ý |
Nhưng ngoài ra bạn có biết còn 2 phương thức nữa cũng cực kỳ hữu dụng?
1.
1 2 3 |
Route::match(['get', 'post'], '/', $callback); |
Phương thức này dành cho bạn nào muốn một route có thể sử dụng 2 hoặc nhiều phương thức HTTP cùng lúc.
2.
1 2 3 |
Route::any('foo', $callback); |
Phương thức này cho phép một route có thể nhận một HTTP methods bất kỳ luôn, lười level max. Tất nhiên sử dụng thế nào là ở bạn nhưng theo mình cái any()
này cũng chả hữu dụng lắm, chỉ để biết cho vui thôi
Redirect URL ngay trong web.php
Có rất nhiều trường hợp, nhất là ở các bạn newbie mới tìm hiểu Laravel, viết hẳn một Controller rất hoành tráng, trong là một mớ methods mà có nhiều cái chỉ làm đúng nhiệm vụ redirect sang một trang khác.
Cách đơn giản để thực hiện một việc đơn giản là sử dụng luôn một phương thức redirect mà Laravel đã cung cấp sẵn, ngay trong web.php
1 2 3 |
Route::redirect('/here', '/there', 301); |
Return view trong web.php
Tương tự như trường hợp trên, bạn cũng có thể return ra một view ngay trong web.php nhưng với cách gọn hơn như này rất nhiều:
1 2 3 4 5 6 7 8 9 10 11 |
// thay vì Route::get('/welcome', function() { return 'welcome'; }); //hãy làm như này Route::view('/welcome', 'welcome'); //hoặc Route::view('/welcome', 'home.welcome', ['name' => 'SomeName']); |
Route name prefixes
Nếu bạn có một đống các routes và có thể bạn đang đặt tên cho nó kiểu như thế này:
1 2 3 |
Route::get("/","BlogController@show")->name("blog.show"); |
Bạn có thể gom tất cả các route name bắt đầu bằng blog thành các group với prefix là blog. như sau:
1 2 3 4 5 6 7 |
Route::name('blog.')->group(function () { Route::get('show', function () { //... })->name('show'); }); |
Code clean, tại sao lại không chứ?
optional()
Một phương thức rất hữu dụng khác nhưng có lẽ ít người để ý. Phương thức này nhận vào tất cả value và cho phép bạn gọi đến các thuộc tính hoặc phương thức mà bạn truyền vào nó. Nếu method hoặc thuộc tính bạn truyền vào là null thì nó sẽ trả ra null luôn.
1 2 3 4 5 6 |
$a = new Model(); optional($a)->doSomething(); // gọi doSomething() nếu có, không thì return null optional($a)->someProperty; // show ra someProperty nếu có, nếu không trả ra null |
Rất hữu dụng khi bạn không biết liệu một array mình dùng có value mình cần hay không, thay thế câu lệnh if/else luôn được ấy
1 2 3 4 5 6 7 |
$blogPost = BlogPost::first(); // view echo "<div class='author_box'>" . optional($blogPost->author)->name // nếu không có tên author thì tự trả ra null luôn . "</div>"; |
Sử dụng array_wrap() để chắc rằng biến là một array
Đôi khi bạn cần làm việc với một array nhưng bạn không dám chắc tham số đầu vào là gì vì nó có thể nhận mọi loại dữ liệu, bạn sẽ muốn sử dụng phương thức trên để biến mọi loại dữ liệu về với kiểu array cực kỳ đơn giản thay vì cách truyền thống như này:
1 2 3 4 5 6 7 8 9 |
$value = foo(); if (!is_array($value)) { $value = [$value]; } foreach($value as $row) { /* ... */ } |
Hãy làm như này:
1 2 3 4 5 |
$value = array_wrap(foo()); foreach($value as $row) { /* ... */ } |
Hoặc
1 2 3 4 |
$value = array_wrap(['a','b']); // ['a', 'b'] (no change) $value = array_wrap('asdf'); // return ['asdf'] |
Lấy phần tử đầu tiên của mảng KHÔNG TRƯỢT PHÁT NÀO bằng Collection first()
Nghe thì có vẻ hiển nhiên nhưng bạn đã rơi vào trường hợp muốn lấy ra một phần tử của mảng nhưng không chắc rằng tham số đầu vào là một string hay một array??
Tôi đã rơi vào trường hợp này khi đã quên mất một case trong quá trình validate dữ liệu, khi cho phép tham số đầu dùng mà người dùng nhập vào có thể là bất cứ điều gì, tôi cứ hồn nhiên lấy ra phần tử đầu tiên bằng $array[0]
, vào một ngày đẹp trời, có bạn tester nhập vào một string và thế là toanggg.
Sau đó tôi đã ngay lập tức chữa cháy bằng một cú fix:
1 2 3 4 5 6 7 |
if (is_array($params)) { return $array[0]; } return $params; |
Trông có vẻ ngon nhưng hơi khó chịu thôi :v vì phải mất công tạo thêm một function cho một case bé tí, sau đó tôi đã phát hiện ra một cách đơn giản hơn nhiều, đó là lợi dụng phương thức collect()
của Laravel. Mặc định phương thức này sẽ trả về một array bất kể đầu vào là một array hay một string hay một integer, nếu đầu vào là một string, đầu ra sẽ là một mảng một Collection một phần tử, chỉ cần dùng ->first()
là xong
1 2 3 4 |
$array = 'Anthony'; return collect($array)->first(); |
HOẶC Bạn có thể lợi dụng luôn array_wrap()
để lấy ra phần tử đầu tiên như vậy nhưng chỉ là trông nó không được đẹp cho lắm:
1 2 3 4 |
$array = 'Anthony'; return array_wrap($array)[0]; |
Lấy phần tử trong mảng theo điều kiện bất kỳ bằng Collection filter()
Vấn đề thế này, bạn có một mảng dữ liệu, mỗi phần tử trong mảng là một object với nhiều thuộc tính và ác thuộc tính đó đều được sử dụng cho một câu lệnh tìm kiếm, ví dụ với array sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$books = [ [ 'book' => 'IT', 'author' => 'Stephan King', 'type' => 'honor', ], [ 'book' => 'Harry Potter', 'author' => 'J.K.Rowling', 'type' => 'fiction', ], [ 'book' => 'Avengers', 'author' => 'Stan Lee', 'type' => 'fiction', ], [ 'book' => 'Shining', 'author' => 'Stephan King', 'type' => 'honor', ], ... ] |
Bây giờ tôi muốn lấy một cuốn sách với duy nhất một tham số điều kiện là $condition
, với điều kiện tôi đưa vào, tôi sẽ lấy được một cuốn sách có author hoặc book hoặc type là $condition
.
Đơn giản thôi, foreach
rồi if/else
có gì khó đâu:
1 2 3 4 5 6 7 |
foreach($books as $book) { if ($book['book'] == $condition || $book['author'] == $condition || $book['type'] == $condition) { return $book; } } |
Hầu hết sẽ làm như vầy đúng không, đúng là rất đơn giản nhưng lại quá dài, không clean.
Thay vào đó Laravel cung cấp cho chúng ta một công cụ mạnh mẽ hơn nhiều, giờ hãy thử dùng phương thức filter()
như sau:
1 2 3 4 5 |
return collect($books)->filter(function ($book) use ($condition) { return $book['book'] == $condition || $book['author'] == $condition || $book['type'] == $condition; }); |
Kết quả trả về của cả 2 đều là object phù hợp với điều kiện đưa vào nhưng sử dụng filter()
cho code gọn và clean hơn nhiều
Có thể bạn quan tâm:
- Một số kiến thức nhỏ về Migration trong Laravel
- Các Laravel route tips giúp bạn cải thiện routing
- Hướng dẫn cách viết clean code cho lập trình viên (P1)
Xem thêm việc làm Software Developers tại TopDev
TopDev via Viblo