Có khi nào bạn phải hiển thị một tổ hợp đầy đủ các cột dữ liệu từ bảng hoặc xử lý dữ liệu trước khi lưu vào trong hệ thống cơ sở dữ liệu? Những bạn lập trình viên có lẽ sẽ quen thuộc với thao tác này. Nhưng làm như vậy thì mất nhiều thời gian và công sức. Accessors và Mutators ra đời sẽ giúp các bạn giảm thiểu thời gian thực hiện chuyện xử lý dữ liệu phức tạp để lưu vào trong hệ thống cơ sở dữ liệu.
Accessor và Mutator trong Laravel cho phép chúng ta định dạng lại chính xác các giá trị thuộc tính của Eloquent khi các bạn lấy hoặc thêm vào Model. Ngoài hỗ trợ tạo Acessor và Mutator, Eloquent cũng có thể tự chuyển các trường date thành Carbon instance hoặc chuyển trường text thành JSON.
Accessor là gì?
Các bạn tạo một hàm có tên getNameAttribute trong model User tại thư mục app như sau:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function getNameAttribute($value)
{
return $this->strtoupper($value);
}
}
Các bạn có thấy hàm bên trong function getNameAttribute nó như thế nào rồi phải không? Đây là hàm chuyển ngữ thường qua chữ hoa trong PHP framework. Tiếp theo, các bạn vào mysql và thêm vào cơ sở dữ liệu có các bản ghi. Các bạn có thể tạo thêm một hàng bằng tay:
Ở thư mục routes/web.php, các bạn tạo một route mới:
Route::get('/accessors', function() {
$user = App\User::find(1);
return $upper_name = $user->name;
});
Sau đó, các bạn mở trình duyệt theo đường dẫn localhost:8000/accessors. Các bạn có thấy kết quả VIỆT NAM VÔ ĐỊCH hay không? Bây giờ, các bạn trở lại với model User. Ở ví dụ này, các bạn quan sát hàm getNameAttribute. Hàm này đã được tạo theo kiểu camelCase để thực hiện việc lấy giá trị cho thuộc tính name. Nếu bạn muốn định nghĩa một accessors trong bất cứ model nào, thì bạn phải có tiền tố get và hậu tố Attribute trong function.
Mutator là gì?
Mutator cho phép bạn định dạng lại các giá trị thuộc tính trước khi bạn lưu vào hệ thống cơ sở dữ liệu. Để hiểu rõ hơn về Mutator, các bạn nên tìm hiểu định nghĩa một phương thức setPasswordAttribute trong model User.
public function setPasswordAttribute($password)
{
$this->attributes['password'] = bcrypt($password);
}
Route::get('/mutators', function() {
$user = App\User::find(1);
$user->password = 123456;
return $user->password;
});
Trở lại với trình duyệt và gõ địa chỉ localhost:8000/accessors. Kết quả của nó là một đoạn ký tự đã được mã hóa tự động. Bạn thấy ví dụ ở trên, hàm setPasswordAttribute sẽ được gọi cùng với $password truyền vào là 123456. Nếu bạn muốn định nghĩa một Mutator trong một model, function của bạn phải thêm tiền tố set và hậu tố là Attribute.
Date Mutator là gì?
Trong Laravel, Eloquent sẽ chuyển đổi thành hai trường: created_at và updated_at thành các instance của Carbon – một thư viện có nhiều hàm hữu ích và mở rộng class DateTime của PHP. Bạn có thể điều chỉnh trường nào linh hoạt để tự động mutated và có thể disable việc mutation bằng cách chèn lên thuộc tính $date trên model của bạn.
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
protected $dates = [
'created_at',
'update_at',
'delete_at',
];
}
Khi một cột là kiểu Date, các bạn đặt giá trị của nó là một UNIX timestamp, date string (Y – m – d), date-time string. Sau đó, bạn đặt một instance của DateTime/Carbon và giá trị của date sẽ tự lưu vào trong dữ liệu.
$user = App\User::find(1);
$user->deleted_at = now();
$user->save();
Khi các bạn lấy các giá trị trong $date, chúng sẽ chuyển cast thành các Carbon instance và bạn có thể sử dụng các method của Carbon nằm trong các attribute đó.
$user = App\User::find(1);
return $user->deleted_at->getTimestamp();
Date Format là gì?
Timestamp được định dạng dưới dạng Y-m-d H:i:s. Nếu bạn muốn điều chỉnh định dạng cho timestamp, thì bạn cần đặt thuộc tính $dateFormat trên model của bạn. Vì thuộc tính này sẽ quyết định giá trị date được lưu bên trong như thế nào. Mà cụ thể ở đây chính là database. Nó được ví như khi một model được serialized theo mảng nào đó hoặc theo JSON.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';
}
Attribute Casting là gì?
Để biết Attribute Casting là gì, các bạn nên tìm hiểu thuộc tính $casts. Đây là phương thức chuyển đổi tiện lợi các thuộc tính qua các dạng dữ liệu thường. Thuộc tính $casts là một mảng có key là tên của các attribute đã được cast và giá trị là kiểu dữ liệu mà bạn muốn cast. Các dạng dữ liệu để cast đã được hỗ trợ, bao gồm: integer, real, float, double, string, object, array, collection, date, timestamp, datetime và Boolean. Cast thuộc tính is_admin từ kiểu integer sang Boolean sẽ như sau:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'is_admin' => 'boolean',
];
}
Thuộc tính is_admin khi đó sẽ được cast thành Boolean khi bạn truy cập đến nó. Nếu giá trị của nó được lưu trong database là kiểu integer.
$user = App\User::find(1);
if ($user->is_admin) {
//
}
Array và JSON Casting là gì?
Cast dạng Array hữu ích khi các bạn thực hiện với các cột được lưu dưới dạng JSON. Ví dụ database của các bạn có một trường JSON hoặc TEXT có chứa serialized JSON. Khi thêm vào array cast lên attribute sẽ tự động deserialize các attribute thành PHP array khi bạn truy cập trong Eloquent model.
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'options' => 'array',
];
}
Khi cast đã được định nghĩa, các bạn truy cập giá trị options và nó sẽ tự động được deserialize từ JSON thành PHP array. Khi đặt giá trị options, nó sẽ tự động được serialize trở lại thành JSON để lưu vào trong cơ sở dữ liệu.
$user = App\User::find(1);
$options = $user->options;
$options['key'] = 'value';
$user->options = $options;
$user->save();
Cập nhật thêm được vài kiến thức mới
Bài viết hữu ích.
Hữu ích
Cảm ơn Admin. Bài viết khá hay !
OK bạn, mình sẽ sắp xếp viết một bài về Extend Validation. Cảm ơn bạn đã quan tâm nhé.