【问题标题】:modify data before store with PHP Traits使用 PHP Traits 在存储之前修改数据
【发布时间】:2026-02-18 02:20:03
【问题描述】:

我尝试使用 PHP trait 加密 Laravel 模型中的一些密钥

这个特征已经在 setAttribute 方法中加密了值,但是数据没有加密存储在数据库中,我不明白为什么会发生这种情况

当我在 setAttribute 方法中使用 dump 时,一切正常并且值已加密

namespace App\EncryptorTraits;


use blackpanda\encryptor\Encryptor;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\EncryptException;
use Illuminate\Encryption\Encrypter;

trait Encryptable
{

    public function setAttribute($key,$val)
    {
        if($this->shouldEncrypt($key) && !$this->isEncrypted($val))
        {
            $val = $this->encryptAttribute($val);
        }

        return parent::setAttribute($key,$val);
    }

    public function getAttributeFromArray($key)
    {
        return $this->doDecryptAttribute($key,parent::getAttributeFromArray($key));
    }

    public function getArrayableAttributes()
    {
        return $this->doDecryptAttributes(parent::getArrayableAttributes());
    }

    public function getAttributes()
    {
        return $this->doDecryptAttributes(parent::getAttributes());
    }





    public function doEncryptAttributes($key)
    {
        if($this->shouldEncrypt($key) && !$this->isEncrypted($this->attributes[$key])){
            $this->attributes[$key] = $this->encryptAttribute($this->attributes[$key]);
        }
    }

    public function encryptAttribute($value)
    {

        try {
            $encrypted = $this->getEncrypter()->encrypt($value);
        } catch (EncryptException $e) {
            throw new EncryptException($e->getMessage(), $e->getCode());
        }

        return $this->getEncryptionPrefix() . $encrypted;
    }


    public function decryptAttribute($value)
    {
        if( !$this->isEncrypted($value) ) return $value;

        try{
            $decrypted = $this->getEncrypter()->decrypt(str_replace($this->getEncryptionPrefix(), '', $value));
        }
        catch (DecryptException $e)
        {
            throw new DecryptException($e->getMessage(),$e->getCode());
        }

        return $decrypted;
    }

    public function doDecryptAttribute($key , $val)
    {
        if($this->shouldEncrypt($key) && $this->isEncrypted($val))
        {
            return $this->decryptAttribute($val);
        }

        return $val;
    }

    public function doDecryptAttributes($attributes)
    {
        foreach ($attributes as $key => $val)
        {
            $attributes[$key] = $this->doDecryptAttribute($key,$val);
        }

        return $attributes;
    }





    protected function getEncryptionPrefix()
    {
        return config('encryptor.db_encryption_prefix');
    }

    protected function getEncryptableList()
    {
        return (isset($this->encryptable)) ? $this->encryptable : [];
    }

    protected function shouldEncrypt($key) : bool
    {
        $encryptableList = $this->getEncryptableList();

        return (in_array($key, $encryptableList));
    }

    protected function isEncrypted($value)
    {
        return strpos((string)$value, $this->getEncryptionPrefix()) === 0;
    }

    protected function getEncrypter()
    {
        return new Encrypter($this->getEncryptionSecret(),'AES-256-CBC');
    }

    protected function getEncryptionSecret()
    {
        $encryptor = new Encryptor();
        return $encryptor->getDatabaseSecret();
    }
}

我尝试像这样存储数据

$Create = \App\myModel::create([
        'key1' => 'val1',
        'key2' => 'val2',
        ..
        ..
 ]);

我也尝试了 Save 方法,但数据仍然未加密地存储在数据库中!

这是我的模型

<?php


namespace App;


use App\EncryptorTraits\Encryptable;
use Illuminate\Database\Eloquent\Model;

class myModel extends Model
{
    use Encryptable;

    protected $encryptable = ['name'];

    protected $guarded = ['id'];
    protected $table = 'table';

}

【问题讨论】:

  • 你有什么问题?
  • @LeventeOtta 数据未以加密格式存储
  • 顺便说一句,你为什么要捕获异常然后创建一个具有相同值的相同类型的新异常并抛出它?
  • 这是我的错,我现在修好了,但我存储数据的问题还没有解决
  • 你在这段代码中的什么地方试图加密任何东西?您所要做的就是创建一个模型。

标签: php laravel eloquent traits


【解决方案1】:

我的一个项目具有相同的可加密特征。

<?php


namespace App\Traits\Models;

use Throwable;

trait Encryptable
{
    public function getEncryptable(): array
    {
        if (property_exists($this, 'encryptable')) {
            return $this->encryptable;
        }

        return [];
    }

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->getEncryptable(), true)) {
            $value = encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }

    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if ($value !== '' && in_array($key, $this->getEncryptable(), true)) {
            try {
                $value = decrypt($value);
            } catch (Throwable $exception) {
                //
            }
        }

        return $value;
    }

    public function attributesToArray(): array
    {
        $attributes = parent::attributesToArray();

        foreach ($this->getEncryptable() as $key) {
            if (isset($attributes[$key])) {
                $attributes[$key] = decrypt($attributes[$key]);
            }
        }

        return $attributes;
    }

    public function decrypt()
    {
        foreach ($this->getEncryptable() as $key) {
            parent::setAttribute($key, $this->{$key});
        }

        return $this;
    }
}

【讨论】:

    最近更新 更多