This guide explains how the model loading system works in EasyAPP and the different ways you can access loaded models.
EasyAPP provides a flexible model loading system that supports multiple access patterns. When you load a model, it is:
- Instantiated - The model class is created with the registry
- Returned - The instance is returned to you directly
- Registered - The instance is automatically registered in the registry for magic access
This dual behavior gives you maximum flexibility in how you work with models.
Capture the returned instance in a variable:
$userModel = $this->load->model('user');
$users = $userModel->getAll();
$user = $userModel->getById(1);Advantages:
- Clear and explicit
- Easy to understand
- Good for multiple method calls
- Better for code completion in IDEs
Use When:
- You need multiple method calls on the same model
- Working in complex logic
- Code clarity is important
- Teaching/documenting code
Use the magic property access via registry:
$this->load->model('user');
$users = $this->model_user->getAll();
$user = $this->model_user->getById(1);Advantages:
- Concise syntax
- No variable declaration needed
- Familiar to users of other frameworks
Use When:
- Quick one-time access
- Prefer shorter syntax
- Already familiar with this pattern
Load and use immediately in one line:
$users = $this->load->model('user')->getAll();
$user = $this->load->model('user')->getById(1);Advantages:
- Most concise
- One-liner operations
- No variable pollution
Use When:
- Single method call needed
- One-time operations
- Functional programming style
When you call $this->load->model('user'), the framework:
- Resolves the path - Converts
'user'toapp/model/user.php - Checks cache - Returns cached instance if already loaded
- Includes the file - Requires the model file if not loaded
- Instantiates the model - Creates instance:
new ModelUser($registry) - Caches the instance - Stores in internal cache for reuse
- Registers in registry - Sets in registry with key
'user' - Returns the instance - Returns model object to caller
The registry key is generated by adding model_ prefix and replacing slashes with underscores:
$registryKey = 'model_' . str_replace('/', '_', $sanitizedRoute);Examples:
'user'→ Registry key:'model_user'→ Access:$this->model_user'common/helper'→ Registry key:'model_common_helper'→ Access:$this->model_common_helper'admin/user'→ Registry key:'model_admin_user'→ Access:$this->model_admin_user
Models registered in the registry are accessible via magic __get() method:
class Controller {
public function __get($key) {
return $this->registry->get($key);
}
}
// When you access $this->model_user
// It calls $this->__get('model_user')
// Which calls $this->registry->get('model_user')
// Which returns the registered model instanceclass ControllerUser extends Controller {
// Pattern 1: Multiple operations (RECOMMENDED)
public function index() {
$userModel = $this->load->model('user');
$users = $userModel->getAll();
$count = $userModel->count();
$active = $userModel->getActive();
$data = [
'users' => $users,
'count' => $count,
'active' => $active
];
$this->response->setOutput($this->load->view('user/list.html', $data));
}
// Pattern 2: Quick single access
public function delete() {
$userId = $this->request->get('id');
$this->load->model('user');
if ($this->model_user->delete($userId)) {
$this->response->json(['success' => true]);
}
}
// Pattern 3: One-liner
public function count() {
$count = $this->load->model('user')->count();
$this->response->json(['count' => $count]);
}
}Choose one primary pattern for your project and stick with it:
// ✓ GOOD: Consistent use of Pattern 1
class ControllerProduct extends Controller {
public function index() {
$productModel = $this->load->model('product');
$products = $productModel->getAll();
}
public function view() {
$productModel = $this->load->model('product');
$product = $productModel->getById($this->request->get('id'));
}
}
// ✗ AVOID: Mixing patterns unnecessarily
class ControllerProduct extends Controller {
public function index() {
$products = $this->load->model('product')->getAll(); // Pattern 3
}
public function view() {
$this->load->model('product'); // Pattern 2
$product = $this->product->getById($this->request->get('id'));
}
}For frequently used models, load in constructor:
class ControllerUser extends Controller {
private $userModel;
public function __construct($registry) {
parent::__construct($registry);
// Load once, use everywhere
$this->userModel = $this->load->model('user');
}
public function index() {
$users = $this->userModel->getAll();
}
public function view() {
$user = $this->userModel->getById($this->request->get('id'));
}
}class ControllerProduct extends Controller {
public function index() {
// Load model and get all products
$productModel = $this->load->model('product');
$products = $productModel->getAll();
$data['products'] = $products;
$this->response->setOutput($this->load->view('product/list.html', $data));
}
public function view() {
$id = $this->request->get('id');
// One-liner for single use
$product = $this->load->model('product')->getById($id);
if (!$product) {
$this->response->redirect('/404');
return;
}
$data['product'] = $product;
$this->response->setOutput($this->load->view('product/view.html', $data));
}
public function create() {
if ($this->request->server('REQUEST_METHOD') === 'POST') {
$productData = $this->request->post;
// Magic access for quick operation
$this->load->model('product');
$productId = $this->model_product->create($productData);
$this->response->redirect('/product/view?id=' . $productId);
return;
}
$this->response->setOutput($this->load->view('product/form.html'));
}
}class ModelOrder extends Model {
public function getWithDetails($orderId) {
// Get order
$order = $this->getById($orderId);
if (!$order) {
return null;
}
// Load related models
$userModel = $this->load->model('user');
$orderItemModel = $this->load->model('order_item');
// Get related data
$order['user'] = $userModel->getById($order['user_id']);
$order['items'] = $orderItemModel->getByOrderId($orderId);
return $order;
}
}class ServiceOrderService extends Service {
public function processOrder($orderData) {
// Load models in constructor or method
$orderModel = $this->load->model('order');
$inventoryModel = $this->load->model('inventory');
$paymentModel = $this->load->model('payment');
try {
// Check inventory
foreach ($orderData['items'] as $item) {
if (!$inventoryModel->checkAvailability($item['product_id'], $item['quantity'])) {
throw new Exception('Product not available');
}
}
// Create order
$orderId = $orderModel->create($orderData);
// Process payment
$paymentModel->process($orderId, $orderData['payment']);
// Update inventory
$inventoryModel->reserve($orderData['items']);
return $orderId;
} catch (Exception $e) {
$this->logger->error('Order processing failed: ' . $e->getMessage());
throw $e;
}
}
}class ControllerAdmin extends Controller {
public function dashboard() {
// Load models from subdirectories
$statsModel = $this->load->model('admin/stats');
$reportModel = $this->load->model('admin/report');
$data['stats'] = $statsModel->getDashboard();
$data['reports'] = $reportModel->getRecent();
// OR with magic access
$this->load->model('admin/stats');
$this->load->model('admin/report');
$data['stats'] = $this->model_admin_stats->getDashboard();
$data['reports'] = $this->model_admin_report->getRecent();
$this->response->setOutput($this->load->view('admin/dashboard.html', $data));
}
}The model loading system in EasyAPP provides three patterns for maximum flexibility:
- Explicit Variable -
$model = $this->load->model('name')- Recommended for clarity - Magic Access -
$this->load->model('name'); $this->model_name->method()- Concise syntax - Method Chaining -
$this->load->model('name')->method()- One-liners
All patterns work because the framework both returns the instance AND registers it in the registry with the model_ prefix.
Choose the pattern that best fits your coding style and project requirements, and use it consistently throughout your codebase.