I'm trying to rewrite a page from CI3 to CI4. In CI3, the validation rule took a parameter from the controller. But now that I've rewritten the code, that parameter (projectid) is coming through as the text 'projectid'. How do I pass a variable from the controller to a custom validation rule in CI4?
in app\Config\Validation.php:
public array $manageProjectInfo = array (
'fldPublish' => array (
'label' => 'Make project public',
'rules' => 'trim|check_publish_datasets[projectid]'
)
);
The following is writing pid: projectid into the logs:
// 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;
}
in 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);
}
}
}
}
In the CI4 documentation, there is an example sending one of the other form inputs as a parameter (https://codeigniter.com/user_guide/libraries/validation.html#setting-multiple-rules). So I tried making a hidden input and passing that, but it also just printed the text name of the variable into the logs.
I ended up having to do two things to fix this. First, I found in the CI4 documentation that,
"If your method needs to work with parameters, the function will need a minimum of three parameters:
https://codeigniter.com/user_guide/libraries/validation.html#setting-multiple-rules
However, even passing my variable through the $params parameter, it was still coming through as the text name of the variable.
So, I added a hidden input to my form with the variable I needed and accessed it through the $data parameter.
public function check_publish_datasets($fldPublish, string $args, array $data, ?string &$error = null):bool {
$pid=$data['projectID'];
$valid = TRUE;
$project_model = model('Project_model');
if (!$fldPublish) {
$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;
}