You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CI4自定义验证规则传参异常:控制器变量变为字符串而非整数

如何在CodeIgniter 4中正确将控制器变量传递给自定义验证规则?

我正在将页面从CI3迁移至CI4。在CI3中,验证规则可从控制器接收参数,但改写代码后,传入自定义验证规则的projectid参数变为字符串'projectid'而非实际整数值。我曾尝试用隐藏输入传参,但日志仍显示参数为变量名而非实际值。


相关代码

app\Config\Validation.php

public array $manageProjectInfo = array (
    'fldPublish' => array (
        'label' => 'Make project public',
        'rules' => 'trim|check_publish_datasets[projectid]'
    )
);

自定义验证方法

// check that there are no unpublished datasets if unpublishing project
public function check_publish_datasets($fldPublish, $pid) { 
    $valid = TRUE;
    $project_model = model('Project_model');
    if (!$fldPublish) {
        log_message('debug','pid: '.$pid);
        $nDatasets = $project_model->get_projectdataavail($pid,$published=TRUE);

        if (count($nDatasets) > 0) {
            $valid = FALSE;
            $error = "This project cannot be unpublished because it contains published datasets.";
        }
    }    
    return $valid;
}

app\Controllers\Manage\Project.php

public function info($projectid = -1) {
    $basics['pagetitle'] = "Manage Project Information";
    if ($this->request->getPost()) {
        $project['fldPublish'] = $this->request->getPost('fldPublish');
    }
    //Define form attributes
    $data['formattribs'] = array(
        'class' => 'basicForm',
        'id' => 'manage-project-info-form'
    );
    //Create array of input options, setting default values to either what they were in the database or what was entered in post data for form repopulation on error
    $data['fldPublish_publish'] = array(
        'name' => 'fldPublish',
        'id' => 'fldPublish',
        'type' => 'radio',
        'value' => '1',
        'checked' => ($project['fldPublish'] == "1" ? TRUE : FALSE)
    );
    $data['fldPublish_notpublish'] = array(
        'name' => 'fldPublish',
        'id' => 'fldPublish',
        'type' => 'radio',
        'value' => '0',
        'checked' => ($project['fldPublish'] == "0" ? TRUE : FALSE)
    );
    //Check if form validation has already been run and passed    
    //Form validation rules set in form_validation config file
    if (!$this->request->is('post') || !$this->validateData($this->request->getPost(), 'manageProjectInfo')) {
        $this->common->render_page($basics, 'manage/project/info', $data);
    }
    //If successful form validation...
    else {
        //Collect post data for insert
        $project = array(
            'fldPublish' => $this->request->getPost('fldPublish')
        );
        $validData = $this->validator->getValidated();
        foreach ($validData as $key=>$valid) {
            $project[$key] = $valid;
        }
        //Check flag-type columns to see if they're set to one, if they aren't set values to zero.
        if ($project['fldPublish'] != 1)
            $project['fldPublish'] = 0;
        //Convert null dates
        $builder = $this->db->table('tblProject');
        $builder->where('pkProjectID', $projectid);
        $updateattempt = $builder->update($info_changes);
        if ($updateattempt) {
            //update the projectUpdated date and log a tblProjectChanges record
            $this->project_model->logProjectUpdated($projectid, "project", "info");
            $this->session->setFlashdata('successmessage', "Your changes were successfully submitted");
            return redirect()->to('manage/project/' . $projectid . '/info');
        } else {
            $data['errormessage'] = "There was a problem writing your changes to the database. Please try again";
            //Load the views with render_pages, passing either name of main view to load or array of main pages to load
            $this->common->render_page($basics, 'manage/project/info', $data);
        }
    }
}

解决方法

CI4的验证规则机制和CI3不同,不能直接在配置文件的规则里引用控制器变量,下面两种方法可以解决:

方式一:动态生成验证规则(推荐)

直接在控制器里根据当前的projectid构建验证规则,把实际值传入自定义规则:

修改控制器的info方法,替换原来的验证逻辑:

public function info($projectid = -1) {
    // ... 保留原有其他代码

    // 动态构建带实际projectid的验证规则
    $validationRules = [
        'fldPublish' => [
            'label' => 'Make project public',
            'rules' => "trim|check_publish_datasets[$projectid]"
        ]
    ];

    // 使用动态规则验证,不再依赖配置文件的规则组
    if (!$this->request->is('post') || !$this->validateData($this->request->getPost(), $validationRules)) {
        $this->common->render_page($basics, 'manage/project/info', $data);
    }

    // ... 后续代码保持不变
}

方式二:通过验证器实例传递额外数据

如果想保留配置文件的规则组,可以把projectid存入验证器实例,再在自定义方法中读取:

  1. 控制器修改验证逻辑:
public function info($projectid = -1) {
    // ... 保留原有其他代码

    // 获取验证器实例,传入规则组和数据
    $validator = \Config\Services::validator();
    $validator->setData($this->request->getPost());
    $validator->setRuleGroup('manageProjectInfo');
    // 把projectid存入验证器的自定义属性
    $validator->projectid = $projectid;

    // 执行验证
    if (!$this->request->is('post') || !$validator->run()) {
        $data['validation'] = $validator; // 传递错误信息到视图
        $this->common->render_page($basics, 'manage/project/info', $data);
    }

    // ... 后续代码保持不变
}
  1. 修改自定义验证方法,从验证器实例获取projectid:
// check that there are no unpublished datasets if unpublishing project
public function check_publish_datasets($fldPublish) { 
    $valid = TRUE;
    // 从验证器实例读取projectid
    $pid = $this->validator->projectid;
    $project_model = model('Project_model');
    
    if (!$fldPublish) {
        log_message('debug','pid: '.$pid);
        $nDatasets = $project_model->get_projectdataavail($pid, TRUE);

        if (count($nDatasets) > 0) {
            $valid = FALSE;
            // 设置错误信息
            $this->setError("This project cannot be unpublished because it contains published datasets.");
        }
    }    
    return $valid;
}

注意:这种方式需要把配置文件里的规则改成'rules' => 'trim|check_publish_datasets',去掉后面的[projectid]参数。


内容的提问来源于stack exchange,提问作者xanabobana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:27:05