Trongate PHP Framework Docs
Introduction
Basic Concepts
Understanding Routing
Intercepting Requests
Module Fundamentals
Database Operations
Templates
Helpers
Form Handling
Form Validation
Working With Files
Image Manipulation
Working With Dates & Times
Language Control
Authorization & Authentication
Tips And Best Practices

The Create/Update Pattern

Building forms for creating and editing records is a universal requirement in web applications. Trongate v2 encourages an elegant pattern that handles both operations with a single form, single set of validation rules, and minimal code duplication.

Why This Pattern Works

  • DRY (Don't Repeat Yourself) — One form, one view, one set of validation rules
  • Simple Logic — A single conditional determines data source
  • Maintainable — Change fields in one place, not two
  • User-Friendly — Consistent interface for creation and editing

The Three Components

Component Purpose Key Responsibility
create() Display the form Decide whether to load data from POST or database
submit() Process submission Validate, save, redirect on success or redisplay on failure
Model helpers Data preparation get_data_from_post() and get_data_from_db()

Complete Working Example

Here's a complete Members module demonstrating the pattern:

The Controller (Members.php)

The Model (Members_model.php)

The View (create.php)

How It Works: The Four Scenarios

The key to this pattern is the conditional in create():

Translation: "If we're creating a new record OR if the form was just submitted (validation error), get data from POST. Otherwise, we're editing an existing record, so get data from the database."

Scenario 1: Creating a New Record

URL/members/create
Condition$update_id === 0 is true
Data Sourceget_data_from_post() returns empty strings
ResultEmpty form displays

Scenario 2: Editing an Existing Record

URL/members/create/5
Condition$submit is empty (GET request)
Data Sourceget_data_from_db(5)
ResultForm displays with existing data

Scenario 3: Validation Error

TriggerUser submits form with invalid data
Flowsubmit() calls create() on failure
Condition$submit === 'Submit' is true
Data Sourceget_data_from_post() with submitted values
ResultForm redisplays with user's values and error messages

Scenario 4: Successful Submission

TriggerUser submits valid form
ValidationPasses in submit()
DatabaseInsert or update via get_data_from_post()
Feedbackset_flashdata() stores success message
ResultRedirect to manage page (PRG pattern)

Validation Flow

Validation happens in submit(), not create():

  1. User submits form to submit()
  2. defines validation requirements
  3. executes validation
  4. If valid: Save data, then invoke , followed by
  5. If invalid: Errors stored in session, create() gets called to redisplay form

Key Point: The create() method never validates. It only decides where to get data from (POST or database) and displays the form. Validation is exclusively the responsibility of submit().

Checkbox Handling

Checkboxes require special attention because unchecked boxes submit nothing. The following model code demonstrates a robust and consistent way to handle checkboxes:

This conversion works for both:

  • Database storage: Stores 0 or 1 in the database
  • Form redisplay: Returns 0 or 1, which form_checkbox() interprets correctly

The Post-Redirect-Get (PRG) Pattern

After successful submission, Trongate uses PRG to prevent duplicate submissions:

Step Action Result
POSTForm submits to submit()Data received
Validaterun() checks dataPass or fail
SaveDatabase insert or updateRecord stored
Flashdataset_flashdata()Message stored in session
Redirectredirect('members/manage')Browser receives 302
GETBrowser requests manage pageSuccess message displays

If the user refreshes, they see the manage page (GET) — no resubmission warning.

URL Structure

URLMethodAction
/members/managemanage()List all records
/members/createcreate()New record form (empty)
/members/create/5create()Edit record form (ID 5)
/members/submitsubmit()Create new record
/members/submit/5submit()Update record ID 5
/members/confirm_delete/5confirm_delete()Confirm delete ID 5
  • Two model methods only: get_data_from_post() and get_data_from_db() handle all data loading
  • Single validation location: Always validate in submit(), never in create()
  • Consistent checkbox handling: Use (int) (bool) post('field', true) for all checkboxes
  • Flashdata for success: Always use set_flashdata() before redirecting
  • Always redirect after POST: Prevents duplicate submissions on refresh
  • URL conventions: Use /create for forms, /submit for processing