【问题标题】:cakephp isUnique for 2 fields?cakephp isUnique 对于 2 个字段?
【发布时间】:2010-03-17 09:59:20
【问题描述】:

我有一个注册表单,用户可以在其中填写两个电子邮件地址(email1 和 email2)。市场营销的要求是它们必须是唯一的(如果我们有 10 个用户,那么就必须是唯一的,那么就会有 10*2=20 个唯一的电子邮件地址)。

该系统已经建立在 cakephp 上,所以我想知道的是,是否有类似 isUnique 功能(在一个领域中唯一)可以立即执行此操作?还是我注定要自己编写代码?提前致谢。

编辑:基于 Richard 的示例,这对我有用:

function checkUnique($data, $fields) {
    if (!is_array($fields)) {
        $fields = array($fields);
    }
    foreach($data as $key) {
        $checks = $key;
    }
    if (empty($checks)) {
      return true;  //allow null
    }
    foreach($fields as $key) {
        $tmp[$key] = $checks;
    }
    if (isset($this->data[$this->name][$this->primaryKey])) {
        $tmp[$this->primaryKey] = "<>".$this->data[$this->name][$this->primaryKey];
    }
    return $this->isUnique($tmp);
}

【问题讨论】:

标签: cakephp unique-index cakephp-model


【解决方案1】:

我在 CakePHP Google Group 上发布了一个解决方案:

http://groups.google.com/group/cake-php/browse_frm/thread/b3a1e4ae3eeb6091/e168f54bac27c163?lnk=gst&q=checkUnique#e168f54bac27c163

将以下内容添加到您的 AppModel:

        /** 
         * checks is the field value is unqiue in the table 
         * note: we are overriding the default cakephp isUnique test as the 
original appears to be broken 
         * 
         * @param string $data Unused ($this->data is used instead) 
         * @param mnixed $fields field name (or array of field names) to 
validate 
         * @return boolean true if combination of fields is unique 
         */ 
        function checkUnique($data, $fields) { 
                if (!is_array($fields)) { 
                        $fields = array($fields); 
                } 
                foreach($fields as $key) { 
                        $tmp[$key] = $this->data[$this->name][$key]; 
                } 
                if (isset($this->data[$this->name][$this->primaryKey])) { 
                        $tmp[$this->primaryKey] = "<>".$this->data[$this->name][$this- 
>primaryKey]; 

                } 
                return $this->isUnique($tmp, false); 
        } 
} 

并用于您的模型验证:

        var $validate = array( 
                "name"=>array( 
                        "unique"=>array( 
                                "rule"=>array("checkUnique", array("name", "institution_id")), 
                                "message"=>"A contact with that name already exists for that 
institution" 
                        ) 
                ) 
       ); 

【讨论】:

  • 感谢您的首发!不过,我不得不对其进行一些修改以使其适合我的情况。将使用最终代码编辑原始问题。
  • if (isset($this-&gt;data[$this-&gt;name][$this-&gt;primaryKey])) { $tmp[$this-&gt;primaryKey] = "&lt;&gt;".$this-&gt;data[$this-&gt;name][$this- &gt;primaryKey]; 应该被删除,因为 Cake 2.x 会在 isUnique 方法中自己进行这项检查。更糟糕的是,它使 isUnique 返回对我来说不正确。
【解决方案2】:

checkUnique 可以写成isUnique 的包装器。

class AppModel extends Model {
    public function checkUnique($ignoredData, $fields, $or = true) {
        return $this->isUnique($fields, $or);
    }
}

并在您的模型验证中使用:

public $validate = array(
    'name' => array(
        'unique' => array(
            'rule' => array('checkUnique', array('name', 'institution_id'), false), 
            'message' => 'A contact with that name already exists for that 
institution'
        )
    )
);

【讨论】:

  • 这比最初接受的答案要简单得多。
  • @KimStacks 这个功能在我写原始答案时在 CakePHP 中不可用
  • 知道了。谢谢你告诉我@RichardAtHome
  • 编辑案例是什么。??当我们设置这个条件来绕过该行时。
【解决方案3】:

From cakePHP 2.0 documentation:

您可以通过提供多个字段并将 $or 设置为 false 来验证一组字段是否唯一:

public $validate = array(
    'email' => array(
        'rule' => array('isUnique', array('email', 'username'), false),
        'message' => 'This username & email combination has already been used.'
    )
);

在跨多个字段制定唯一规则时,请确保将原始字段包含在字段列表中。

如果列出的字段未包含在模型数据中,则将其视为空值。您可以考虑根据需要标记列出的字段。

【讨论】:

    【解决方案4】:

    是和不是。

    是的,您必须自己编写代码,但在 CakePHP 验证组件中。

    验证组件具有允许自定义验证规则的机制。本质上,您在 $validate 中放置了一个函数名称(就像您通常那样)。你必须定义函数;在这种情况下,它非常简单(只需执行您的双重 isUnique 要求)。

    http://book.cakephp.org/2.0/en/models/data-validation.html#custom-validation-rules

    【讨论】:

      【解决方案5】:

      冒着因为提供 non-CakePHP 解决方案而遭受打击的风险,让我介绍以下内容。

      在您的数据库中创建一个唯一索引,无论您需要多少列。

      标准的 SQL 语法是:

      create unique index {IndexName} on {Table} ({Column}, {Column}, ...)
      

      将“$this->Model->save()”命令放在“try/catch”块中。在“catch”块中,测试错误代码的异常。在 MySQL 中,唯一键违规是错误代码 23000,但您也应该为其他可能的错误做好准备。

      快速简单,不涉及计算数组括号。

      您应该始终将数据库访问代码放在“try/catch”块中。部分异常处理应包括记录任何意外错误消息。你不能指望 CakePHP 为你做一切

      【讨论】:

      • 我看到我的回答被否决了。不管。我认为我的解决方案更简单,可能更快,并且肯定比指定的“正确”答案涉及更少的编码。
      【解决方案6】:

      据我所知,您必须使用模型中的beforeSave 方法来执行这种强制。我有一个要求,一个对象至少有一个 N fks 集,我只能这样做。

      编辑:尝试this thread 看看是否有任何东西可以解决您的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多