Trước đây, chúng ta bị giới hạn cast mặc định do Laravel cung cấp. Mặc dù, có một số gói thư viện có thể giúp chúng ta custom được nhưng chúng có một nhược điểm lớn. Bởi vì, chúng ghi đề phương thức setAttribute và getAttribute thông qua trait, chúng không thể sử dụng bất kì một gói thư viện nào khác vì chúng cũng ghi đè phương thức đó.
Giờ đây, Laravel đã hỗ trợ phần custom cast, sẽ không xảy ra vấn đề như không tương thích giữa các thư viện nữa. Để hiểu rõ hơn về Laravel Custom Eloquent Casts chúng ta hãy thực hiện một số ví dụ đơn giản như sau.
Để khai báo một Custom Eloquent Casts:
Chúng ta cần implement interface CastsAttributes có chứa 2 phương thức get và set dùng để get giá trị và set giá trị cho các attribute.
Đầu tiên, chúng ta sẽ tạo một file tên là EncryptCast.php nằm ở thư mục app/Casts, phần tạo này các bạn hãy bằng tay vì Laravel chưa cung cấp lệnh command để tạo file một cách tự động.
Sau đó bạn hãy mở file EncryptCast.php và chỉnh sửa như sau:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class EncryptCast implements CastsAttributes
{
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return array
*/
public function get($model, $key, $value, $attributes)
{
return decrypt($value);
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param array $value
* @param array $attributes
* @return string
*/
public function set($model, $key, $value, $attributes)
{
return [$key => encrypt($value)];
}
}
Trong Model (ở đây mình sử dụng Model User), chúng ta sẽ set thuộc tính password sử dụng Custom Cast mà chúng ta vừa tạo ở trên như sau:
<?php
namespace App\Models;
use App\Casts\EncryptCast;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'password' => EncryptCast::class,
];
}
Bây giờ, chúng ta hãy trải nghiệm cách hoạt động của Laravel Custom Cast ở một controller bất kỳ nào.
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$user = User::first();
$user->password = 'ManhDanBlogs';
$user->save();
// Giá trị được mã hóa (sẽ được lưu vào database)
// Raw value : eyJpdiI6IjI1dE9RMGFQUktjeTk5aTVIQWlSNX....
dd($user->getAttributes()['password']);
// Giá trị chưa được mã hóa
dd($user->password);
}
Đôi khi, bạn chỉ muốn format giá trị đang set trên model và không thực hiện bất kỳ xử lý nào khi chúng ta truy xuất dữ liệu từ model.
Vì vậy, chúng ta nên sử dụng interface CastsInboundAttributes, vì nó chỉ yêu cầu bắt buộc duy nhất là hàm set.
Ví dụ, bạn muốn giới hạn độ dài của string khi thực hiện set giá trị trong model.
Đầu tiên, chúng ta sẽ tạo một file tên là LimitCaster.php nằm ở thư mục app/Casts và chỉnh sửa như sau:
<?php
namespace App\Casts;
use Illuminate\Support\Str;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
class LimitCaster implements CastsInboundAttributes
{
/**
* Create a new cast class instance.
*
* @param string|null $algorithm
* @return void
*/
public function __construct($length = 25)
{
$this->length = $length;
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param array $value
* @param array $attributes
* @return string
*/
public function set($model, $key, $value, $attributes)
{
return [$key => Str::limit((string) $value, $this->length)];
}
}
Trong Model (ở đây mình sử dụng Model User), chúng ta sẽ set thuộc tính name sử dụng Custom Cast mà chúng ta vừa tạo ở trên như sau:
<?php
namespace App\Models;
use App\Casts\LimitCaster;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
name' => LimitCaster::class . ':7'
];
}
Bây giờ, chúng ta hãy trải nghiệm cách hoạt động của nó ở một controller bất kỳ nào.
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$user = User::first();
$user->name = 'ManhDanBlogs';
$user->save();
// Value: ManhDan...
dd($user->name);
}
Như vậy, chúng ta đã thực hiện xong một ví dụ đơn giản về Laravel Custom Cast, tôi hy vọng hướng dẫn của tôi sẽ giúp ích cho công việc của bạn. Nếu bạn có bất kỳ câu hỏi nào hãy liên hệ với chúng tôi qua trang contact. Cảm ơn bạn.