Trongate PHP Framework Docs
Introduction
Quick Start
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
Security
Tips And Best Practices

Loading Modules From Models

Most of the time, model files only need database access. That's their job.

But sometimes you need a model to use another module - email sending, file processing, API calls, payment gateways, etc.

Trongate v2 lets you do this explicitly with $this->module().

Heads up: This is an edge case. Most models won't need to load and use other modules. If you're just using your model files for database queries, you can skip this page entirely.


The Syntax

To use a module from within a model file, explicitly load it first:

PHP
<?php
// In Users_model.php
class Users_model extends Model {
    
    public function send_welcome_email($user) {
        // Load the email module
        $this->module('email_sender');
        
        // Now use it
        $this->email_sender->send(
            $user->email, 
            'Welcome to Our Site!', 
            $this->build_message($user)
        );
    }
    
    private function build_message($user) {
        return "Hello {$user->name}, welcome aboard!";
    }
}

That's it. Call $this->module('whatever') before using $this->whatever.


Database vs. Module: The Key Difference

There's an important distinction to understand:

Database Access (No module() call needed)

PHP
// These work automatically - no module() call required
$users = $this->db->get('id', 'users');              // default database
$stats = $this->analytics->get('page_views');        // analytics database
$stock = $this->warehouse->get_where(42, 'items');   // warehouse database

Module Usage (Requires explicit loading)

PHP
// Must call module() first
$this->module('tax');
$total = $this->tax->calculate($amount);

$this->module('payment_processor');
$this->payment_processor->charge($customer, $amount);

Why the difference? Database groups are defined in config/database.php, so Trongate knows they're databases. Modules must be explicitly loaded to signal your intent to use a module rather than access a database.


Complete Example

Here's a realistic scenario: processing an order that requires database queries, tax calculation, and email sending.

PHP
<?php
class Orders_model extends Model {
    
    public function process_order($order_id) {
        // 1. Fetch order from database (automatic)
        $order = $this->db->get_where($order_id, 'orders');
        
        if (!$order) {
            return false;
        }
        
        // 2. Calculate tax using Tax module (requires loading)
        $this->module('tax');
        $tax_amount = $this->tax->calculate($order->subtotal, $order->state);
        
        // 3. Update order total in database (automatic)
        $update_data = [
            'tax_amount' => $tax_amount,
            'total' => $order->subtotal + $tax_amount,
            'processed_at' => time()
        ];
        $this->db->update($order_id, $update_data, 'orders');
        
        // 4. Send confirmation email (requires loading)
        $this->module('email_sender');
        $this->email_sender->send(
            $order->customer_email,
            'Order Confirmation',
            $this->build_confirmation_email($order, $tax_amount)
        );
        
        // 5. Log to analytics database (automatic)
        $analytics_data = [
            'order_id' => $order_id,
            'amount' => $update_data['total'],
            'timestamp' => time()
        ];
        $this->analytics->insert($analytics_data, 'order_events');
        
        return true;
    }
    
    private function build_confirmation_email($order, $tax_amount) {
        $message = "Thank you for your order #" . $order->id . "\n\n";
        $message .= "Subtotal: $" . number_format($order->subtotal, 2) . "\n";
        $message .= "Tax: $" . number_format($tax_amount, 2) . "\n";
        $message .= "Total: $" . number_format($order->subtotal + $tax_amount, 2);
        return $message;
    }
}

In this example:

  • $this->db works automatically (default database)
  • $this->analytics works automatically (configured database group)
  • $this->tax requires $this->module('tax') first
  • $this->email_sender requires $this->module('email_sender') first

Loading Multiple Modules

If you need several modules, load them all at the start of your method for clarity:

PHP
public function complex_operation($data) {
    // Load all required modules upfront
    $this->module('tax');
    $this->module('email_sender');
    $this->module('payment_processor');
    $this->module('inventory');
    
    // Now use them
    $tax = $this->tax->calculate($data['amount']);
    $this->payment_processor->charge($data['customer'], $tax);
    // ... etc
}

Common Use Cases

You'll typically need $this->module() in models when:

  • Sending emails after database operations
  • Processing payments and updating order records
  • Calling external APIs based on database data
  • Generating PDFs or files from database content
  • Complex calculations that live in separate modules (tax, shipping, discounts)
  • Logging or notifications after data changes

Keep it simple: If your model is loading 5+ modules, consider whether some logic belongs in the controller instead. Models should focus on data operations.


What About Controllers?

Controllers work differently. They support both explicit and automatic module loading:

PHP
// In a controller - both styles work:

// Style 1: Explicit (optional)
$this->module('tax');
$total = $this->tax->calculate($amount);

// Style 2: Automatic (recommended in v2)
$total = $this->tax->calculate($amount);  // loads automatically

In models, you must use explicit $this->module() calls. This keeps the distinction clear: databases are automatic, modules are explicit.


Troubleshooting

Error: "Undefined property: Model::$something"

You tried to use a module without loading it first.

Fix: Add $this->module('something') before using $this->something.

Error: "Module controller not found"

The module doesn't exist or isn't named correctly.

Check:

  • Module directory exists: modules/whatever/
  • Controller file exists: modules/whatever/Whatever.php
  • Class name matches: class Whatever extends Trongate

Best Practices

  • Load modules at the start of your method for clarity
  • Database access never needs module() calls
  • If you forget to load a module, the error message will remind you
  • Keep models focused on data - don't turn them into mini-applications
  • When in doubt, put complex orchestration in the controller

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