多次覆盖setAttribute和getAttribute函数(具有不同特征)

时间:2019-08-07 10:08:02

标签: php laravel

我有一列存储信用卡号。目前,它的值是encrypted写入数据库之前,decrypted则是从表中读取。

我想要做的是一旦从表和decrypted中读取了值,就“屏蔽了值”。 “掩盖值”是指用x代替除数字以外的所有内容。例如,4242 4242 4242 4242应该变成x4242。为此,我创建了新的trait,将其命名为Maskable,其中函数getAttribute被覆盖以执行上述操作,并且setAttribute函数被覆盖以检查值是否为试图保存等于“ x” +四位数。如果是,请跳过此列,因为这意味着它尚未更改。否则,将其正常保存,然后更改表中的值(但先对其进行加密)。

是否可以在一个模型中多次重写同一功能?如果是,我该如何判断应该先使用哪种set/getAttribute方法?我在不同的模型中使用Encryptable trait,但是新的trait暂时仅在这里使用,这就是为什么我不能在同一trait中全部使用它。

编辑

我面临的错误: Trait method getAttribute has not been applied, because there are collisions with other trait methods on ...

//My example model

class RentalApplication extends Model {
use Encryptable, Maskable;

protected $encryptable = ['card_number'];
protected $maskable = ['card_number'];
}

//Traits

trait Maskable {

public function getAttribute($key) {
    $value = parent::getAttribute($key);
    if(isset($this->maskable) && in_array($key, $this->maskable) && !empty($value)) {
        try {
            $value = 'x'.substr($value, -4);
        } catch (\Exception $e) {
            return $value;
        }
    }
    return $value;
}

trait Encryptable {

public function getAttribute($key) {
    $value = parent::getAttribute($key);
    if(isset($this->encryptable) && in_array($key, $this->encryptable) && !empty($value)) {
        try {
            $value = Crypt::decrypt($value);
        } catch (\Exception $e) {
            return $value;
        }
    }
    return $value;
}

public function setAttribute($key, $value) {
    if(isset($this->encryptable) && in_array($key, $this->encryptable) && !is_null($value)) {
        if(Schema::hasColumn($this->getTable(), $key.'_search') && !empty($this->id)) {
            parent::setAttribute($key.'_search', hash('sha512', env('APP_KEY').$this->id.$value));
        }
        $value = Crypt::encrypt($value);
    }
    return parent::setAttribute($key, $value);
}

public function toArray() {
    $array = parent::toArray();
    foreach($this->encryptable as $key) {
        if(array_key_exists($key, $array)) {
            $array[$key] = $this->{$key};
        }
    }
    return $array;
}
}

1 个答案:

答案 0 :(得分:1)

不推荐使用的解决方案

//Traits

trait Maskable {

public function getAttribute($key) {
    $value = parent::getAttribute($key);
    if(isset($this->maskable) && in_array($key, $this->maskable) && !empty($value)) {
        try {
            $value = 'x'.substr($value, -4);
        } catch (\Exception $e) {
            return $value;
        }
    }
    return $value;
}

trait Encryptable {

public function getAttribute($key) {
    if (in_array(Maskable::class, class_uses(self::class))) {
        $value = self::getMaskedAttribute($key);
    } else {
        $value = parent::getAttribute($key);
    }

    if(isset($this->encryptable) && in_array($key, $this->encryptable) && !empty($value)) {
        try {
            $value = Crypt::decrypt($value);
        } catch (\Exception $e) {
            return $value;
        }
    }
    return $value;
}

然后解决冲突

//My example model

class RentalApplication extends Model {
use Encryptable, Maskable {
    Encryptable::getAttribute insteadof Maskable;
    Maskable::getAttribute as getMaskedAttribute;
};

protected $encryptable = ['card_number'];
protected $maskable = ['card_number'];
}