Skip to content

Início / Optitravel / Models

Creating Your Model

Introduction

Each model represents a specific type of data and the logic that goes with it. It usually maps to a single database table and takes care of fetching, saving, and updating that data.

You should create a model whenever you need to work with a particular kind of data — like users, products, bookings, and so on. If your feature needs to read or write to a table, then it's a good idea to create a model for it.

Where to Create?

Models should always be created in the includes/classes/Models directory and placed under the App\Models namespace. Each file must be named after the class it contains and must use the .php extension. For example, if you create a User model, the file must be named User.php.

Model directory

Model directoy

How to Create?

Continuing with the previous example — after creating the file (User.php) — the next step is to define your model class. This process is quite straightforward.

First, you need to declare the class namespace (App\Models) so it can be loaded automatically via autoloading. Then, you create the class itself, and it must extend the base Model class provided by the framework. This base Model class is the heart of the system when it comes to database operations — it contains all the necessary methods for interacting with your tables.

After that, you should specify the name of the database table the model represents using the $table property, and list the allowed columns with the $allowedColumns property. These columns are the only ones the system will be able to read from or write to. This adds a layer of protection and helps improve performance by avoiding unnecessary data handling.

Here's what the User model might look like:

Namespace App\Models;

/**
 * Class short description
 *
 * @author  Author <author email>
 * @since   year/month(ex:2025/05)
 * @version year/month(ex:2025/05)
 */
Class User extends Model{

    protected $table = 'users';
    protected $primaryKey = 'id'; 
    protected $allowedColumns = ['id', 'name', 'username', 'password', 'email', 'status', 'lang', 'system_id', 'access_level','create_time','last_change_time'];

    public $id;
    public $name;
    public $username;
    public $password;
    public $email;
    public $status;
    public $lang;
    public $system_id;
    public $access_level;
    public $create_time;
    public $last_change_time;

}

$table

Specifies the database table that this model primarily works with.

$primaryKey

This is the name of the column that uniquely identifies the records in this table. This is used with methods like find() to know what column to match the specified value to.

$allowedColumns

This array should be updated with the columns names that can be used for the find(), insert(), update(), etc methods. Any field names other than these will be discarded. This helps to protect against just taking input from a form and throwing it all at the model, resulting in potential vulnerabilities and poor performance.

Defining Relationships

Starting from the latest version, your models can now define relationships, just like in Laravel. This makes it easier to navigate related data and encapsulate relationship logic within your model classes.

Supported Relationship Methods

You can currently use the following methods to define relationships:

  • hasOne($relatedModel, $foreignKey, $localKey)

  • hasMany($relatedModel, $foreignKey, $localKey)

  • These methods return a related model or a list of related models, depending on the type of relationship.

Relationship Examples

  • hasMany
namespace App\Models;

class Template extends Model
{
    protected $table = 'templates';
    protected $primaryKey = 'id';
    protected $allowedColumns = ['id', 'name', 'type'];

    public $id;
    public $name;
    public $type;

    /**
     * Get all users that belong to this template.
     */
    public function members()
    {
        return $this->hasMany('User', 'user_template', 'template');
    }
}

In this example:

'User' refers to the related model class App\Models\User.

'user_template' is the foreign key in the users table that links back to the template.

'template' is the local key in the current model (Template).

  • hasOne
namespace App\Models;

class Profile extends Model
{
    protected $table = 'profiles';
    protected $primaryKey = 'id';
    protected $allowedColumns = ['id', 'user_id', 'bio'];

    public $id;
    public $user_id;
    public $bio;

    /**
     * Get the user associated with this profile.
     */
    public function user()
    {
        return $this->hasOne('User', 'id', 'user_id');
    }
}

This defines a one-to-one relationship:

The profile "has one" user.

'id' is the primary key in the related model (User).

'user_id' is the foreign key in the profiles table.

Usage Example

$userGroupModel = new \App\Models\Template();

// Find the group and automatically load its related members
$group = $userGroupModel->find($params['id'])->with(['members']);

foreach ($group->members as $user) {
    echo $user->name . "<br>";
}
$profileModel = new \App\Models\Profile();

// Find the profile and automatically load its related user
$profile = $profileModel->find(5)->with(['user']);

echo $profile->user->email;

Notes

The with() method eagerly loads the defined relationships, allowing you to access them directly as properties (e.g., $group->members, $profile->user).

You must declare the relationship methods (members(), user(), etc.) in the model class for them to be recognized by with().

You can pass multiple relationships to with() like ->with(['members', 'permissions']) if needed.

Don't Modify the Model Base Class

The Model class is the backbone of how your models interact with the database. It handles things like fetching data, inserting new records, updating existing ones, and more. Because it's used by all models in your project, you should never edit this file directly.

If you change something in the base Model, it might break all the other models that rely on it — even if it works for just one specific case. That can cause bugs that are hard to debug and maintain later on.

If you need to customize how your model behaves, it's better to extend the Model class in your own model file, and override only what you need there. That way, the core stays stable and your changes stay isolated.

Don’t touch Model.php unless you’re working on the framework itself.

Good Practices

Here are some simple tips to keep your models clean, consistent, and easy to maintain:

  • Keep it simple: Models should focus on data access and basic logic related to that data. Try to avoid placing complex business logic inside them — that’s better handled in controllers or services.

  • Use meaningful names: Give your models clear names that match the table they represent. For example, User, Product, or Reservation.

  • Match table structure: Make sure the $allowedColumns array only contains real columns from your database. This avoids errors and improves performance.

  • Avoid unnecessary fields: Only declare properties in the model that you’ll actually use. No need to mirror every single column if it’s never accessed or changed.

  • Document your model: Add a short PHPDoc block at the top of your class with author, date, and a quick description — it helps others (and future you) understand what the model is for.

  • Use snake_case for database columns (like created_at, user_id).

  • Use camelCase or snake_case for class properties in PHP — just be consistent throughout your codebase.

  • Class names should use PascalCase (e.g., User, UserProfile, ProductOrder).


(Última atualização: 13/05/2025)