Create and Edit
In a Trongate admin CRUD module, a single controller method serves both creation and editing. The same create() method renders the form, and the same submit() method handles the submission. The difference is whether a primary key is present in the URL:
/countries/create- new record form (empty fields)/countries/create/5- edit form (pre-populated with record id 5)/countries/submit- inserts a new record (no update_id in POST)/countries/submit/5- updates record id 5 (update_id in URL)
The Controller Method
/**
* Display form for creating or editing a country.
*
* Shows form with appropriate headline and action URL.
* Automatically repopulates form with submitted data on validation errors.
*
* @return void
*/
public function create(): void {
$this->trongate_security->make_sure_allowed();
$update_id = segment(3, 'int');
if ((REQUEST_TYPE === 'GET') && ($update_id > 0)) {
$data = $this->model->get_data_from_db($update_id);
} else {
$data = $this->model->get_data_from_post();
}
// Add view-specific data
$data['headline'] = ($update_id > 0) ? 'Update Country Record' : 'Create New Country Record';
$data['cancel_url'] = ($update_id > 0) ? 'countries/show/'.$update_id : 'countries/manage';
$data['form_location'] = 'countries/submit/'.$update_id;
$data['view_module'] = 'countries';
$data['view_file'] = 'create';
$this->templates->admin($data);
}The logic flows as follows:
- Check authentication via
$this->trongate_security->make_sure_allowed(). - Extract the
update_idfrom URL segment 3 (0 if absent). - If the request is a GET and
update_id > 0(editing), fetch the existing record from the database usingget_data_from_db(). The model returnsfalseif not found, which the template handles gracefully. - Otherwise, start with empty data from
get_data_from_post(). This covers both a fresh create form and the case where validation failed (the submitted values are preserved). - Set the headline, cancel URL, and form action based on whether we are creating or editing.
- Render the
create.phpview inside the admin template.
This pattern avoids the need for a separate edit() method. One method handles both GET (show form) and POST (show form with errors after failed validation). The submit logic is delegated to submit().
The Create View
<h1><?= $headline ?></h1>
<?= validation_errors() ?>
<div class="card">
<div class="card-heading">
Country Details
</div>
<div class="card-body">
<?php
echo form_open($form_location);
echo form_label('Country Title');
$country_title_attr = [
'placeholder' => 'Enter Country Title',
'required' => true,
'minlength' => 2,
'maxlength' => 255
];
echo form_input('country_title', $country_title, $country_title_attr);
echo form_label('Country Code');
$country_code_attr = [
'placeholder' => 'Enter Country Code',
'required' => true,
'minlength' => 2,
'maxlength' => 2
];
echo form_input('country_code', $country_code, $country_code_attr);
echo '<div class="text-center">';
echo anchor($cancel_url, 'Cancel', ['class' => 'button alt']);
echo form_submit('submit', 'Submit');
echo '</div>';
echo form_close();
?>
</div>
</div>Key details:
validation_errors()renders before the card, so that error messages appear above the form.form_open()takes the$form_locationset by the controller, which points tocountries/submit/{id}.- Each
form_input()is passed HTML attributes includingrequired,minlength, andmaxlengthfor client-side validation. Note thatcountry_codehasmaxlength="2"because the database column isVARCHAR(2). - The Cancel button uses
anchor()to link back to the manage page (for new records) or the show page (for existing records). - The form does not include a Delete button - deletion is handled separately through the
delete_conf()flow from the manage page or the show page.
The $cancel_url variable is set by the controller depending on the context. When creating a new record, it points back to the manage page. When editing, it points to the show page for that record.
The Submit Handler
/**
* Handle form submission for creating/updating countries.
*
* Validates input, converts checkbox data, and saves to database.
* Includes automatic CSRF validation and proper checkbox conversion.
*
* @return void
*/
public function submit(): void {
$this->trongate_security->make_sure_allowed();
$submit = post('submit', true);
if ($submit === 'Submit') {
$this->validation->set_rules('country_title', 'country title', 'required|min_length[2]|max_length[255]');
$this->validation->set_rules('country_code', 'country code', 'required|min_length[2]|max_length[2]');
if ($this->validation->run()) {
$update_id = segment(3, 'int');
$data = $this->model->get_data_from_post();
if ($update_id > 0) {
$this->model->update_record($update_id, $data);
$flash_msg = 'Country updated successfully';
$finish_url = 'countries/show/'.$update_id;
} else {
$update_id = $this->model->create_new_record($data);
$flash_msg = 'Country created successfully';
$finish_url = 'countries/manage';
}
set_flashdata($flash_msg);
redirect($finish_url);
} else {
$this->create();
}
} else {
redirect('countries/manage');
}
}The pattern is straightforward:
- Check authentication.
- Read the
submitbutton value. If it is not exactly "Submit", redirect to the manage page. This prevents direct URL access from doing anything. - Set validation rules using
$this->validation->set_rules()with pipe-delimited rules:required|min_length[2]|max_length[255]. - If validation passes, gather the sanitised data from the model and insert or update depending on whether
$update_idis present. - Set a flashdata success message and redirect. For updates, the user is taken back to the show page. For new records, the user is taken to the manage page.
- If validation fails, re-render the form with error messages by calling
$this->create().
The set_flashdata() message is displayed on the next page load via <?= flashdata() ?> in the view.
Validation Rules
Trongate uses a validation module that is configured declaratively with pipe-delimited rule strings. The rules above say:
country_titleis required, minimum 2 characters, maximum 255 characters.country_codeis required, minimum 2 characters, maximum 2 characters (matching the VARCHAR(2) column).
The validation module checks for a POST field matching the rule name. If the field is missing, empty, or does not meet the length constraints, validation fails and $this->validation->run() returns false. The error messages are collected and displayed by validation_errors() at the top of the form.
Client-side HTML attributes such as required, minlength, and maxlength provide a first line of defence in the browser, but server-side validation via the validation module is the authoritative check.
We're continually improving the Trongate documentation. If anything is incorrect, unclear, incomplete, or could be better, we'd genuinely appreciate your input.
Share your thoughts in the Documentation Feedback.