MagratheaPHP2
Up to date Narrative last written —; no source changes since. Method signatures below are reflected live.

MagratheaModel — ORM Base Model

File: src/MagratheaModel.php Namespace: Magrathea2 Type: Abstract Class Implements: iMagratheaModel

The base class for all database-backed domain models. Provides field mapping, automatic CRUD operations, property access via __get/__set, serialization, and relationship definitions.


Interface: iMagratheaModel

Every model must satisfy:

interface iMagratheaModel {
    public function __construct($id);
    public function Save();
    public function Insert();
    public function Update();
    public function GetID();
}

Defining a Model

<?php
namespace App\Models;

use Magrathea2\MagratheaModel;

class Product extends MagratheaModel {

    // Required: database table name
    protected $dbTable = "products";

    // Optional: primary key column (default: "id")
    protected $dbPk = "id";

    // Required: column definitions [column_name => type]
    protected $dbValues = [
        "id"          => "int",
        "name"        => "string",
        "description" => "text",
        "price"       => "float",
        "stock"       => "int",
        "active"      => "boolean",
        "created_at"  => "datetime",
    ];

    // Optional: property aliases [alias => real_column]
    protected $dbAlias = [
        "title" => "name",   // $product->title is the same as $product->name
    ];

    // Optional: eager-loaded relations (loaded on construct)
    protected $autoLoad = null;
}

Supported Field Types

TypePHP typeNotes
intintInteger values
booleanboolStored as TINYINT(1)
stringstringVARCHAR, CHAR, etc.
textstringTEXT columns
floatfloatDECIMAL, FLOAT, DOUBLE
datetimestringMySQL datetime format (Y-m-d H:i:s)
datestringMySQL date format (Y-m-d) — see note below
uuidstringAuto-generated UUIDv7 on Insert() if left unset — see note below

date normalization: on Insert()/Update(), a date field's value is normalized to Y-m-d before binding. Accepted inputs: "YYYY-MM-DD", "YYYY-MM-DD HH:MM:SS", and ISO-8601 ("YYYY-MM-DDTHH:MM:SS.sssZ"). Anything else throws a MagratheaModelException. The date part is taken as written — no timezone conversion happens, so "1990-05-10T03:00:00.000Z" stores 1990-05-10 regardless of server timezone. That is the right behavior for birthdate-style fields, but clients east/west of UTC should prefer sending a plain "YYYY-MM-DD" to avoid off-by-one-day surprises.

uuid generation: on Insert()/InsertWithPk(), any field declared "uuid" in $dbValues that is still empty gets filled in with Uuid::V7() (src/Uuid.php) — a time-ordered RFC 9562 UUIDv7: a 48-bit millisecond timestamp prefix followed by 10 bytes from PHP's CSPRNG (random_bytes()), with the version/variant bits set per spec. A field that already has a value (set explicitly before Insert()) is left alone and never overwritten. Nothing regenerates it on Update() — UUIDs are treated as immutable once assigned.

Collision-safety is not enforced by the framework: there is no pre-insert uniqueness check and no catch/retry around a duplicate-key error on INSERT — a collision would surface as a rethrown DB exception. In practice this is safe because random_bytes(10) supplies enough entropy that a same-millisecond collision is statistically negligible, but the real backstop is the database: the uuid column must actually be declared PRIMARY KEY/UNIQUE in the schema for uniqueness to be guaranteed rather than merely "very likely."

Strict typing ($strictTypes)

By default, LoadObjectFromTableRow() assigns whatever the DB driver returns for each column with no type coercion — mysqli/PDO return every column as a string regardless of its SQL type, so numeric and boolean properties end up as strings unless the calling code casts them.

Set protected $strictTypes = true; on a model (or its Base class) to opt into typed hydration: values are cast to their declared $dbValues PHP type on load — int(int), boolean(bool), float(float). null is always left as null, and string/text/uuid/date/datetime fields are left untouched (the DB driver already returns those as strings). A value that can't be cast — schema drift, e.g. a non-numeric string landing in an int column — throws MagratheaModelException naming the field and value.

$strictTypes defaults to false and must be opted into per model; it does not change any existing model's behavior. Requires MagratheaPHP2 2.3.0+.


Properties

PropertyTypeDescription
$dbTablestringDatabase table name
$dbPkstringPrimary key column name
$dbValuesarrayColumn → type definitions
$dbAliasarrayAlias → column mappings
$relationsarrayRelated object definitions
$dirtyValuesarrayModified-but-not-saved fields
$autoLoadarray|nullRelations loaded in constructor
$strictTypesboolOpt-in typed hydration on load — see Strict typing above (default false)

Instantiation

// Empty model
$product = new Product();

// Load by primary key
$product = new Product(42);
// Equivalent to: SELECT * FROM products WHERE id = 42

Persistence Methods

Save(): int|bool

Smart save: calls Insert() if the model has no PK set, or Update() if it does.

// Create new record
$product = new Product();
$product->name  = "Widget";
$product->price = 9.99;
$newId = $product->Save(); // returns inserted ID

// Update existing record
$product = new Product(42);
$product->price = 12.99;
$product->Save(); // returns true

Insert(): int

Executes an INSERT and sets the PK on the model. Returns the new auto-increment ID.

$product = new Product();
$product->name = "New Product";
$id = $product->Insert();

InsertWithPk(): bool

Inserts a record that already has a PK set (e.g., UUID or custom integer).

$product = new Product();
$product->id   = 9999;
$product->name = "Special Product";
$product->InsertWithPk();

Update(): bool

Executes an UPDATE for the current model (uses PK in WHERE clause).

$product = new Product(42);
$product->name = "Updated Name";
$product->Update(); // UPDATE products SET name = 'Updated Name' WHERE id = 42

Delete(): bool

Deletes the record from the database.

$product = new Product(42);
$product->Delete(); // DELETE FROM products WHERE id = 42

Property Access

Models support both method-style and magic property access:

// Magic access (recommended)
echo $product->name;
$product->price = 19.99;

// Method access
echo $product->Get("name");
$product->Set("price", 19.99);

// Suppress missing-field exceptions
$val = $product->Get("nonexistent", true); // returns null instead of throwing

Setting the Primary Key

$product->SetPK(42);
echo $product->GetPK(); // 42
echo $product->GetID(); // same

Loading Methods

LoadObjectFromTableRow(array|object $row): void

Populates model properties from a database row (array or stdClass). Used internally by MagratheaModelControl. If $strictTypes is enabled, values are cast to their declared $dbValues type — see Strict typing above.

$row = Database::Instance()->QueryRow("SELECT * FROM products WHERE id = 1");
$product = new Product();
$product->LoadObjectFromTableRow($row);

Assign(array $data): MagratheaModel

Assign multiple properties from an associative array (e.g., from $_POST).

$product = new Product();
$product->Assign([
    "name"  => "Widget",
    "price" => 9.99,
]);
$product->Save();

GetById(mixed $id): void|object

Load the model data from the database by primary key. Throws MagratheaModelException if not found.

$product = new Product();
$product->GetById(42);

Introspection Methods

GetDbTable(): string

Returns the table name.

GetPkName(): string

Returns the primary key column name.

GetDbValues(): array

Returns the column definitions array.

GetFields(): array

Returns the list of column names.

GetFieldsForSelect(): string

Returns a comma-separated SQL field list with table prefix.

GetProperties(): array

Returns the model's current field values as an associative array.

IsEmpty(): bool

Returns true if the PK is not set (model not loaded from DB).

ModelName(): string

Returns the class short name.

Ref(): string

Returns a human-readable reference string (e.g., "Product#42").


Serialization

ToArray(): array

Returns all field values as an associative array.

$arr = $product->ToArray();
// ["id" => 42, "name" => "Widget", "price" => 9.99, ...]

ToJson(): array

Same as ToArray() but intended for JSON API responses. Relations are recursively serialized.

echo json_encode($product->ToJson());

ToString(): string / __toString(): string

echo $product; // uses __toString

Static Methods

GetDataTypeFromField(string $field): string

Returns the PHP type string for a field name.

IncludeAllModels(): void

Manually includes all model files (if needed outside the autoloader).


Getting the Next Available ID

GetNextID(): int

Returns MAX(pk) + 1 for the table. Useful when you need to know the next ID before inserting.

$nextId = $product->GetNextID();

Full Lifecycle Example

use App\Models\Product;

// 1. Create
$product = new Product();
$product->name  = "Gadget";
$product->price = 29.99;
$product->stock = 100;
$product->active = true;
$id = $product->Save();

echo "Created product #$id";

// 2. Read
$found = new Product($id);
echo $found->name;  // "Gadget"
echo $found->price; // 29.99

// 3. Update
$found->price = 24.99;
$found->Save();

// 4. Serialize
echo json_encode($found->ToJson());

// 5. Delete
$found->Delete();

Notes

Class Reference — MagratheaModel

Magrathea2\MagratheaModel implements Stringable abstract /home/platypusweb/platypusweb.com.br/site/magratheaphp2/src/MagratheaModel.php
Assign($data): Magrathea2\MagratheaModel

Gets an array of whatever and assign it to the properties of model

ParamTypeDefault
$data mixed required
Delete()

Deletes the object in database

Get($key, $supressException = false)

gets required property

ParamTypeDefault
$key mixed required
$supressException mixed false
GetAutoLoad()

Gets autoload objects

GetById($id)

Returns object by Id. If null, creates a null instance of the object. This will also load any related objects that are set as "autoload" internally. if an object with the given id can not be found, or any of the auto-load related objects can not be found an exception will be thrown.

ParamTypeDefault
$id mixed required
GetDbTable()

Gets table related to model

GetDbValues()

Gets array of table column values

GetFields(): array

Get fields from model

GetFieldsForSelect()

Prepare fields for this model for a select statement

GetID()

Gets id value

GetNextID()

Gets the next auto increment id for this object

GetPK()
GetPkName()

Gets PK Name

GetProperties(): array

Get all properties from model

Insert()

Inserts the object in database

InsertWithPk(): bool

Inserts the object, but the object alredy has the PK

IsEmpty(): bool

Checks if the object exists (id not null)

LoadObjectFromTableRow($row)

Receives an array with the columns and values and associates then internally into the object

ParamTypeDefault
$row mixed required
ModelName(): string

returns the name of the class without the namespace

Ref(): string

returns a string for identifying the object in a relation

Save()

Saves: Using a insert if pk is not set and an update if pk is set Basically, Inserts if id does not exists and updates if id does exists

Set($key, $value, $supressException = false)

Sets given property

ParamTypeDefault
$key mixed required
$value mixed required
$supressException mixed false
SetPK($value)

Sets PK

ParamTypeDefault
$value mixed required
ToArray()
ToJson()

Gets a Json

ToString()

To String! =)

Update()

Updates the object in database

static GetDataTypeFromField($field)

Get (Magrathea) data type from field

ParamTypeDefault
$field mixed required
static IncludeAllModels()

Include all classes presents on `Models` folder

Examples