0

Kohana ORM 的验证是使用rules

function rules()
{
  return array(
    'username' => array(
      array('not_empty'),
      array(array($this, 'availability')),
    )
  );
}

我正在努力使用$_serialize_columns.

class Model_Admin extends ORM {
  protected $_belongs_to = array();
  protected $_has_many = array(
    'plans' => array(),
    'groups' => array(),
    'transactions' => array(),
    'logins' => array()
  );

  protected $_serialize_columns = array('data');

  /**
   * @param array $data
   * @param Validation $validation
   *
   * @return bool
   */
  public function data($data, $validation)
  {
     return 
       Validation::factory(json_decode($data, TRUE))
       // ... rules ...
       ->check();
  }

  public function rules()
  {
     return array(
       'data' => array(
         array(array($this, 'data'), array(':value',':validation')
       )
     );
  }
}

被编码的数组是:

array(
  'name' => '',
  'address' => '',
  'phone' => '',
  'postalcode' => ''
);

data方法接收 json 编码的数据,因为 ORM 在进行验证之前运行过滤器,所以我需要将其转换回关联数组,然后创建一个新的验证对象来专门检查该数组的内容。因为我无法合并Validation来自另一个Validation实例的规则

4

1 回答 1

0

更新的答案

必须使用第二个验证对象,因为save()会检查内部模型验证对象。这意味着添加到从验证规则检查的验证对象的规则将被忽略(Validation->check()在循环之前将规则导入本地范围)。

由于数据本身在技术上是另一个对象(在对象关系的意义上,它有自己的需要验证的数据集),理想的解决方案是找到一种方法来创建一个保存数据的真实模型。

使用正确的数据库列定义保存数据还有许多其他好处,尤其是在您需要执行数据属性查找、进行原位更改等时(否则将需要对所有行中的数据列进行反序列化)。

有一些替代方案,但它们对我来说就像是杂物:

  1. 创建一个表示数据对象的模型并向其添加规则,check()用于验证数据(问题:需要大量维护,没有真实世界的表意味着必须手动定义列)。

  2. 在 Admin 模型中将数据设置为真实列,并使用过滤器将其转换为设置的数据列(问题:再次,必须手动定义列并从保存操作中排除其他列)。

我希望这有一些用处。

原始答案

Kohana ORMsave()方法允许包含一个“额外的”验证对象,该对象被合并到主 ORM 验证对象命名空间中。

此处简要记录了这一点。

如果我理解正确,我认为您正在寻求做这样的事情:

// another script, e.g., a controller

// Create the model
$admin = ORM::factory('Admin');

// $data = the data as an array, before serialization ...

$extra_validation = Validation::factory($data)
                    // add ->rule() calls here, but DO NOT chain ->check()
                    ;

// Set $data in the model if it is going to be saved, e.g., $admin->data = $data;
// Set other data... e.g., $admin->foo = 'bar';

// Save the model
try {
    $admin->save($extra_validation);
}
catch (ORM_Validation_Exception $e)
{
    // Manipulate the exception result
}

虽然在此示例中您仍必须创建另一个验证对象,但您现在能够在单个块中捕获所有异常。如果您使用 i18n 消息来提供人类可读的错误消息,我建议使用var_dump()或类似的方法来检查命名空间。$e->errors()您应该会发现在响应中创建了一个名为“_external”的命名空间。

于 2012-12-19T16:36:40.650 回答