有多种方法可以解决此问题(请注意,以下代码是未经测试的示例代码!在使用任何此类代码之前,您应该首先了解新的基础知识)。
自定义数据库类型
一种是自定义数据库类型,它将在将值绑定到数据库语句时进行加密,并在获取结果时进行解密。那是我希望的选择。
这是一个简单的示例,假设db列可以容纳二进制数据。
src /数据库/类型/CryptedType.php
这应该是自言自语的,转换为数据库时进行加密,转换为PHP时进行解密。
<?phpnamespace AppDatabaseType;use CakeDatabaseDriver;use CakeDatabaseType;use CakeUtilitySecurity;class CryptedType extends Type{ public function toDatabase($value, Driver $driver) { return Security::encrypt($value, Security::salt()); } public function toPHP($value, Driver $driver) { if ($value === null) { return null; } return Security::decrypt($value, Security::salt()); }}src / config / bootstrap.php
注册自定义类型。
use CakeDatabaseType;Type::map('crypted', 'AppDatabaseTypeCryptedType');src / Model / Table / PatientsTable.php
最后,将可加密的列映射到注册的类型,就是这样,从现在开始,所有内容都会自动处理。
// ...use CakeDatabaseSchemaTable as Schema;class PatientsTable extends Table{ // ... protected function _initializeSchema(Schema $table) { $table->columnType('patient_surname', 'crypted'); $table->columnType('patient_first_name', 'crypted'); return $table; } // ...}参见 **[食谱
数据库访问和ORM>数据库基础>添加自定义类型](http://book.cakephp.org/3.0/en/orm/database-
basics.html#adding-custom-types)**
beforeSave和结果格式化程序
较不干燥且紧密的耦合方法(基本上是2.x代码的一部分)将使用
beforeSave回调/事件和结果格式化程序。结果格式化程序可以例如附加在
beforeFind事件/回调中。
在
beforeSave刚刚设置/获取值/从通过实体实例,你可以利用
Entity::has(),
Entity::get()并且
Entity::set(),甚至使用数组访问,因为实体实施
ArrayAccess。
结果格式化程序基本上是一个after find挂钩,您可以使用它轻松地遍历结果并进行修改。
这是一个基本示例,不需要进一步解释:
// ...use CakeEventEvent;use CakeORMQuery;class PatientsTable extends Table{ // ... public $encryptedFields = [ 'patient_surname', 'patient_first_name' ]; public function beforeSave(Event $event, Entity $entity, ArrayObject $options) { foreach($this->encryptedFields as $fieldName) { if($entity->has($fieldName)) { $entity->set( $fieldName, Security::encrypt($entity->get($fieldName), Security::salt()) ); } } return true; } public function beforeFind(Event $event, Query $query, ArrayObject $options, boolean $primary) { $query->formatResults( function ($results) { return $results->map(function ($row) { foreach($this->encryptedFields as $fieldName) { if(isset($row[$fieldName])) { $row[$fieldName] = Security::decrypt($row[$fieldName], Security::salt()); } } return $row; }); } ); } // ...}要对此进行一点解耦,您还可以将其移为一个行为,以便您可以轻松地在多个模型之间共享它。



