Trongate Way Docs

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

PHP
/**
 * 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:

  1. Check authentication via $this->trongate_security->make_sure_allowed().
  2. Extract the update_id from URL segment 3 (0 if absent).
  3. If the request is a GET and update_id > 0 (editing), fetch the existing record from the database using get_data_from_db(). The model returns false if not found, which the template handles gracefully.
  4. 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).
  5. Set the headline, cancel URL, and form action based on whether we are creating or editing.
  6. Render the create.php view 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

View File
<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_location set by the controller, which points to countries/submit/{id}.
  • Each form_input() is passed HTML attributes including required, minlength, and maxlength for client-side validation. Note that country_code has maxlength="2" because the database column is VARCHAR(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

PHP
/**
 * 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:

  1. Check authentication.
  2. Read the submit button value. If it is not exactly "Submit", redirect to the manage page. This prevents direct URL access from doing anything.
  3. Set validation rules using $this->validation->set_rules() with pipe-delimited rules: required|min_length[2]|max_length[255].
  4. If validation passes, gather the sanitised data from the model and insert or update depending on whether $update_id is present.
  5. 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.
  6. 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_title is required, minimum 2 characters, maximum 255 characters.
  • country_code is 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.

Leave Feedback About This Page