【问题标题】:Custom is_unique_logical_key - validation or callback?自定义 is_unique_logical_key - 验证还是回调?
【发布时间】:2012-11-12 07:34:33
【问题描述】:

我可以为以下问题提供设计建议吗:

我正在使用 Codeigniter/Grocery_CRUD。

我的系统是多租户的 - 不同的自治站点 - 在同一个客户端内。我有很多具有唯一逻辑键的表实例。一种这样的表结构是:

装备物品
编号 (pk)
装备类型 ID(fk 到装备类型)
site_id(fk 到站点)
姓名

where (equip_type_id, site_id, name) 一起是我数据库中的唯一键。

问题在于,当使用grocery_CRUD 表单添加或编辑违反此数据库规则的记录时 - 添加或编辑失败(由于数据库中的限制)但我没有得到任何反馈。

我需要 is_unique form_validation 规则的变体,通过它我可以指定必须唯一的字段*s*。

问题:
如何指定规则? set_rules() 用于给定字段,我有多个字段适用该规则。这是否意味着我应该放弃 Form_validation 模式?还是我遵循“匹配”规则模式并以某种方式指向其他字段?

也许回调函数会更好,但这意味着在每个模型中编写一个自定义函数,我最后一次遇到这个问题,这是 9 个表。在一个地方执行此操作似乎要好得多(扩展 form_validation)。

我是否遗漏了在 codeigniter 或grocery_CRUD 中已经解决了这个问题的东西?

如果您有任何建议/建议,我们将不胜感激。

编辑: 实际上,Johnny 提供的解决方案似乎并没有完全达到目标——它强制 unique_fields() 中的每个字段独立唯一——与在每个字段上设置 is_unique() 相同。我的问题是,在我的场景中,这些字段是复合唯一键(但不是主键)。我不知道它是否重要,但比原始问题陈述更进一步:1)site_id 是一个“隐藏”字段类型 - 我不希望我的用户担心他们在不同的站点上,所以我正在处理 site_id 后面场景。 2) 同样处理equip_status_id 属性(不是唯一键的一部分)。并且 3) 我在所有这些外键属性上都有 set_relations(),grocery_CRUD 为我处理了不错的下拉菜单。

编辑 2 我已经使用回调解决了这个问题。

【问题讨论】:

    标签: php codeigniter-2 grocery-crud


    【解决方案1】:

    更新:此代码现在是杂货店 CRUD 版本 >= 1.4 的一部分,您不再需要使用扩展程序。有关更多信息,请参阅unique_fields 的文档

    我会尽量解释清楚:

    1.首先对于那些杂货店 CRUD 低于或等于 1.3.3 的人必须使用这个小更改:https://github.com/scoumbourdis/grocery-crud/commit/96ddc991a6ae500ba62303a321be42d75fb82cb2

    2. 其次在应用程序/库中创建一个名为grocery_crud_extended.php 的文件

    3. 将以下代码复制到您的文件 application/libraries/grocery_crud_extended.php

    <?php 
    class grocery_CRUD_extended extends grocery_CRUD
    {
        protected $_unique_fields = array();
    
        public function unique_fields()
        {
            $args = func_get_args();
    
            if(isset($args[0]) && is_array($args[0]))
            {
                $args = $args[0];
            }
    
            $this->_unique_fields = $args;
    
            return $this;
        }
    
        protected function db_insert_validation()
        {
            $validation_result = (object)array('success'=>false);
    
            $field_types = $this->get_field_types();
            $unique_fields = $this->_unique_fields;
            $add_fields = $this->get_add_fields();
    
            if(!empty($unique_fields))
            {
                $form_validation = $this->form_validation();
    
                foreach($add_fields as $add_field)
                {
                    $field_name = $add_field->field_name;
                    if(in_array( $field_name, $unique_fields) )
                    {
                        $form_validation->set_rules( $field_name, 
                                $field_types[$field_name]->display_as, 
                                'is_unique['.$this->basic_db_table.'.'.$field_name.']');
                    }
                }
    
                if(!$form_validation->run())
                {
                    $validation_result->error_message = $form_validation->error_string();
                    $validation_result->error_fields = $form_validation->_error_array;
    
                    return $validation_result;
                }
            }
            return parent::db_insert_validation();
        }
    
        protected function db_update_validation()
        {
            $validation_result = (object)array('success'=>false);
    
            $field_types = $this->get_field_types();
            $unique_fields = $this->_unique_fields;
            $add_fields = $this->get_add_fields();
    
            if(!empty($unique_fields))
            {
                $form_validation = $this->form_validation();
    
                $form_validation_check = false;
    
                foreach($add_fields as $add_field)
                {
                    $field_name = $add_field->field_name;
                    if(in_array( $field_name, $unique_fields) )
                    {
                        $state_info = $this->getStateInfo();
                        $primary_key = $this->get_primary_key();
                        $field_name_value = $_POST[$field_name];
    
                        $ci = &get_instance();
                        $previous_field_name_value = 
                            $ci->db->where($primary_key,$state_info->primary_key)
                                ->get($this->basic_db_table)->row()->$field_name;
    
                        if(!empty($previous_field_name_value) && $previous_field_name_value != $field_name_value) {
                            $form_validation->set_rules( $field_name, 
                                    $field_types[$field_name]->display_as, 
                                    'is_unique['.$this->basic_db_table.'.'.$field_name.']');
    
                            $form_validation_check = true;
                        }
                    }
                }
    
                if($form_validation_check && !$form_validation->run())
                {
                    $validation_result->error_message = $form_validation->error_string();
                    $validation_result->error_fields = $form_validation->_error_array;
    
                    return $validation_result;
                }
            }
            return parent::db_update_validation();
        }   
    
    }
    

    4.现在您只需像这样加载grocery_CRUD_extended:

        $this->load->library('grocery_CRUD');
        $this->load->library('grocery_CRUD_extended');
    

    然后使用:

    $crud = new grocery_CRUD_extended();
    

    代替:

    $crud = new grocery_CRUD();
    

    5. 现在您可以简单地拥有它的 unique_fields,它的工作原理如下:

    $crud->unique_fields('field_name1','field_name2','field_name3');
    

    在你的情况下:

    $crud->unique_fields('equip_type_id','site_id');
    

    很简单吧?

    这是在不实际更改杂货店 CRUD 的核心的情况下检查字段是否唯一。您可以简单地使用grocery_CRUD_extended 而不是grocery_CRUD 并照常更新grocery CRUD 库。由于我是该库的作者,我将尝试将其包含在杂货店 CRUD 版本 1.4 中,因此您将来不必使用杂货店_CRUD_extended。

    【讨论】:

    • 约翰。先生。先生,您是一个血腥的传奇!除非你来为我做这个项目,否则我实际上并不确定你能提供多少帮助。
    • 嗯,为此您实际上需要为每个自定义 set_rules。您可以使用 set_rules 回调来完成。您当然可以使用 $_POST 在 set_rules 中设置一个或多个参数。更多请查看codeigniter.com/user_guide/libraries/…。目前没有其他方法可以做到这一点。希望能帮助到你。如果您仍然遇到问题,我建议将此问题移至论坛(gcrud.com/forums
    • @john-skoumbourdis 你能回答这个问题吗? stackoverflow.com/questions/15494526/…
    【解决方案2】:

    我已经使用回调完成了这项工作:

    $crud->set_rules('name','Name','callback_unique_equip_item_check['.$this->uri->segment(4).']');     
    
    function unique_equip_item_check($str, $edited_id)
    {
        $var = $this->Equip_Item_model->is_unique_except(
                $edited_id,
                $this->input->post('site_id'),
                $this->input->post('equip_type_id'),
                $this->input->post('name'));
    
        if ($var == FALSE) {
            $s = 'You already have an equipment item of this type with this name.';
            $this->form_validation->set_message('unique_equip_item_check', $s);
            return FALSE;
            }
        return TRUE;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-06
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 2018-05-20
      • 2017-10-01
      • 1970-01-01
      相关资源
      最近更新 更多