在 Laravel 中扩展访问器和修改器
Extending accessor and mutators in Laravel
我正在尝试在 Laravel 5.5
中开发一个小型应用程序,其中我制作了一个 abstract model
,它正在扩展 Laravel eloquent model
类似这样的东西:
<?php
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
}
现在为了一般惯例,我为此模型设置了一个数据库连接:
<?php
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
/**
* Defining connection for database
*
* @var string
**/
protected $connection='mysql';
}
我创建了自己的模型来扩展这个 abstract class
:
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Posts extends AbstractModel
{
use SoftDeletes;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'unique_id', 'title', 'contents'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'id'
];
}
通过默认定义它,我们知道它将有一个数据库连接 mysql,类似地,fillable
被定义为批量分配。以类似的方式,我想创建一个 encrypt
变量,它将 encrypt
和 decrypt
来自数据库的数据,因此为此我将 accessor
和 mutator
添加到我的encrypt variable
在我的模型中:
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Posts extends AbstractModel
{
use SoftDeletes;
/**
* The attributes that will have encryption.
*
* @var array
*/
protected $encryption = ['unique_id', 'title', 'contents'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'unique_id', 'title', 'contents'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'id'
];
}
并在我的 abstract model
:
中重新配置它
<?php
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
/**
* Defining connection for database
*
* @var string
**/
protected $connection='mysql';
/**
* Defining encryption
*
* @var array
**/
protected $encryption = [];
public function setAttributes()
{
foreach ($this->encryption as $attributes)
{
$this->attributes[$attributes] = Crypt::encryptString($this->attributes[$attributes]);
}
}
public function getAttributes()
{
foreach ($this->encryption as $attributes)
{
$this->attributes[$attributes] = Crypt::decryptString($this->attributes[$attributes]);
}
}
}
我认为我的方法是错误的,因为没有对这些属性进行加密或解密,我可以看到发送来创建行的数据存储在数据库中没有任何加密,并且也以相同的方式检索。
此外,我想有一个用例,我正在加密这些字段,并且它们的属性访问器或修改器在它们自己的模型中被调用,例如:
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Posts extends AbstractModel
{
use SoftDeletes;
/**
* The attributes that will have encryption.
*
* @var array
*/
protected $encryption = ['unique_id', 'title', 'contents'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'unique_id', 'title', 'contents'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'id'
];
public function setTitleAttributes($value)
{
return ucfirst($value);
}
public function getTitleAttributes($value)
{
return ucfirst($value)
}
}
欢迎任何反馈意见。谢谢。
首先,Eloquent 模型有 setAttribute()
和 getAttribute()
方法,而不是 setAttributes()
和 getAttributes()
。
其次,对于这种情况。我宁愿使用 Eloquent's event。因为 setAttribute()
或 getAttribute()
方法只会在您动态访问属性时触发,例如:$post->title
.
您可以加密 saving
事件的属性。并使用 retrieved
事件将其解密。
<?php
namespace App;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Database\Eloquent\Model;
abstract class AbstractModel extends Model
{
protected $connection = 'mysql';
protected $encryption = [];
protected static function boot()
{
parent::boot();
// When being retrieved, decrypt the attributes.
static::retrieved(function ($instance) {
foreach ($instance->encryption as $encryptedKey) {
$instance->attributes[$encryptedKey] = Crypt::decryptString($instance->attributes[$encryptedKey]);
}
});
// When saving (could be create or update) the modal, encrypt the attributes.
static::saving(function ($instance) {
foreach ($instance->encryption as $encryptedKey) {
$instance->attributes[$encryptedKey] = Crypt::encryptString($instance->attributes[$encryptedKey]);
}
});
// Once it's saved, decrypt it back so it's still readble.
static::saved(function ($instance) {
foreach ($instance->encryption as $encryptedKey) {
$instance->attributes[$encryptedKey] = Crypt::decryptString($instance->attributes[$encryptedKey]);
}
});
}
}
当您决定使用这种方法时,不要同时覆盖 setAttribute()
和 getAttribute()
方法。因为它很可能会使 encrypt/decrypt 属性加倍。
此外,它应该是 setTitleAttribute()
和 getTitleAttribute()
——单数形式。在 setTitleAttribute()
上你应该改变 title
属性;不返回预期值。我也看不出将 title
大写的目的,因为它无论如何都会被加密。
<?php
namespace App;
class Post extends Model
{
protected $encryption = ['unique_id', 'title', 'contents'];
protected $fillable = ['unique_id', 'title', 'contents'];
// Expected to mutate the title attribute.
public function setTitleAttribute($value)
{
$this->attributes['title'] = ucfirst($value);
}
public function getTitleAttribute($value)
{
return ucfirst($value);
}
}
希望这能给你一些想法。
我正在尝试在 Laravel 5.5
中开发一个小型应用程序,其中我制作了一个 abstract model
,它正在扩展 Laravel eloquent model
类似这样的东西:
<?php
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
}
现在为了一般惯例,我为此模型设置了一个数据库连接:
<?php
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
/**
* Defining connection for database
*
* @var string
**/
protected $connection='mysql';
}
我创建了自己的模型来扩展这个 abstract class
:
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Posts extends AbstractModel
{
use SoftDeletes;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'unique_id', 'title', 'contents'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'id'
];
}
通过默认定义它,我们知道它将有一个数据库连接 mysql,类似地,fillable
被定义为批量分配。以类似的方式,我想创建一个 encrypt
变量,它将 encrypt
和 decrypt
来自数据库的数据,因此为此我将 accessor
和 mutator
添加到我的encrypt variable
在我的模型中:
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Posts extends AbstractModel
{
use SoftDeletes;
/**
* The attributes that will have encryption.
*
* @var array
*/
protected $encryption = ['unique_id', 'title', 'contents'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'unique_id', 'title', 'contents'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'id'
];
}
并在我的 abstract model
:
<?php
use Illuminate\Database\Eloquent\Model;
class AbstractModel extends Model
{
/**
* Defining connection for database
*
* @var string
**/
protected $connection='mysql';
/**
* Defining encryption
*
* @var array
**/
protected $encryption = [];
public function setAttributes()
{
foreach ($this->encryption as $attributes)
{
$this->attributes[$attributes] = Crypt::encryptString($this->attributes[$attributes]);
}
}
public function getAttributes()
{
foreach ($this->encryption as $attributes)
{
$this->attributes[$attributes] = Crypt::decryptString($this->attributes[$attributes]);
}
}
}
我认为我的方法是错误的,因为没有对这些属性进行加密或解密,我可以看到发送来创建行的数据存储在数据库中没有任何加密,并且也以相同的方式检索。
此外,我想有一个用例,我正在加密这些字段,并且它们的属性访问器或修改器在它们自己的模型中被调用,例如:
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Posts extends AbstractModel
{
use SoftDeletes;
/**
* The attributes that will have encryption.
*
* @var array
*/
protected $encryption = ['unique_id', 'title', 'contents'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'unique_id', 'title', 'contents'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'id'
];
public function setTitleAttributes($value)
{
return ucfirst($value);
}
public function getTitleAttributes($value)
{
return ucfirst($value)
}
}
欢迎任何反馈意见。谢谢。
首先,Eloquent 模型有 setAttribute()
和 getAttribute()
方法,而不是 setAttributes()
和 getAttributes()
。
其次,对于这种情况。我宁愿使用 Eloquent's event。因为 setAttribute()
或 getAttribute()
方法只会在您动态访问属性时触发,例如:$post->title
.
您可以加密 saving
事件的属性。并使用 retrieved
事件将其解密。
<?php
namespace App;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Database\Eloquent\Model;
abstract class AbstractModel extends Model
{
protected $connection = 'mysql';
protected $encryption = [];
protected static function boot()
{
parent::boot();
// When being retrieved, decrypt the attributes.
static::retrieved(function ($instance) {
foreach ($instance->encryption as $encryptedKey) {
$instance->attributes[$encryptedKey] = Crypt::decryptString($instance->attributes[$encryptedKey]);
}
});
// When saving (could be create or update) the modal, encrypt the attributes.
static::saving(function ($instance) {
foreach ($instance->encryption as $encryptedKey) {
$instance->attributes[$encryptedKey] = Crypt::encryptString($instance->attributes[$encryptedKey]);
}
});
// Once it's saved, decrypt it back so it's still readble.
static::saved(function ($instance) {
foreach ($instance->encryption as $encryptedKey) {
$instance->attributes[$encryptedKey] = Crypt::decryptString($instance->attributes[$encryptedKey]);
}
});
}
}
当您决定使用这种方法时,不要同时覆盖 setAttribute()
和 getAttribute()
方法。因为它很可能会使 encrypt/decrypt 属性加倍。
此外,它应该是 setTitleAttribute()
和 getTitleAttribute()
——单数形式。在 setTitleAttribute()
上你应该改变 title
属性;不返回预期值。我也看不出将 title
大写的目的,因为它无论如何都会被加密。
<?php
namespace App;
class Post extends Model
{
protected $encryption = ['unique_id', 'title', 'contents'];
protected $fillable = ['unique_id', 'title', 'contents'];
// Expected to mutate the title attribute.
public function setTitleAttribute($value)
{
$this->attributes['title'] = ucfirst($value);
}
public function getTitleAttribute($value)
{
return ucfirst($value);
}
}
希望这能给你一些想法。