Skip to content

Latest commit

 

History

History
179 lines (129 loc) · 6.61 KB

getting-started-model.md

File metadata and controls

179 lines (129 loc) · 6.61 KB
sidebar_position 1

Getting Started

Defining the Model

The Model is a class will represent the data that retrieved and want to save into the database.

The Model can be:

  • a simple class with public properties
  • a class with getter and setter
  • a mix of both

Determining the Property Name:

Micro ORM determines the property name based on the following rules:

I'll convert that information into a table for you.

Property Visibility Property Name Determination
Public Property name is used directly
Protected or Private Property name is determined based on the getter/setter method name

Example:

public ?int $name = null;  // Property name is 'name' 

protected ?int $id = null; // Property name is 'id'

public function getId(): ?int   // Getter and setter are necessary.
{
    return $this->id;
}
public function setId(?int $id): void
{
    $this->id = $id;
}

Requirements for the properties in the Model class:

Property Characteristic Requirement Example
Property with type Must be nullable with default value set (null preferred) public ?int $id = null;
Property without type No need to set default value public $id;
Protected/Private property Must have getter and setter public methods protected ?int $id = null;
public function getId(): ?int {...};
public function setId(?int $id): void {...};

Backed enum properties

A property (or a setter parameter) typed with a backed enum is stored as the enum's value and loaded back as the enum, so the column holds 'PAID' and the model holds Status::Paid:

enum Status: string
{
    case Pending = 'PENDING';
    case Paid = 'PAID';
}

#[TableAttribute(tableName: 'orders')]
class Order
{
    #[FieldAttribute(primaryKey: true)]
    public ?int $id = null;

    #[FieldAttribute]
    public ?Status $status = null;
}

A value in the database that the enum does not have throws a ValueError when the row is loaded. The conversion is done by byjg/serializer; a pure (non-backed) enum is not supported.

Property Mapping Strategy with the Database

Strategy Description Example
Direct Matching The ORM matches entity property names to their corresponding database field names A property named userid would map to a database column named userid
Field Mapping The ORM matches entity property names to their corresponding field mapping database field names A property named userId would map to a database column named user_id if stated in the field mapping

Field Mapping Methods

Method Description
Mapper class Define mappings using the Mapper class
Attributes Define mappings using PHP 8.3+ attributes

See also: Controlling the data for advanced mapping

When to use each Mapper or Attribute?

Both produce the same Mapper. The difference is where the mapping lives:

  • Attributes put the mapping on the model. It is the simplest option when you own the class.
  • A Mapper object keeps the mapping outside the model, so the model has no database knowledge. Use it for legacy or third-party classes you cannot change, or when the domain model must stay free of database concerns.

See Choosing a Pattern for how this combines with the Repository and Active Record.

Example

Let's say we have a model with the following properties and side by side with the database fields:

Model Property Database Field
id id
name name
companyId company_id

And we want to map the Model properties to the database fields using Attributes:

#[TableAttribute(tableName: 'mytable')]
class MyModel
{
    #[FieldAttribute(primaryKey: true)]
    public ?int $id = null;

    #[FieldAttribute()]
    public ?string $name = null;

    #[FieldAttribute(fieldName: 'company_id')]
    public ?int $companyId = null;
}

and the table:

CREATE TABLE `mytable`
(
    `id`         int(11) NOT NULL AUTO_INCREMENT,
    `name`       varchar(255) DEFAULT NULL,
    `company_id` int(11)      DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

In this example, we have a class MyModel with three properties: id, name, and companyId.

  • The id property is marked as a primary key.
  • The name property is a direct match with the database field - No mapping is needed.
  • The companyId property is a field with a different name in the database company_id.
  • The TableAttribute is used to define the table name in the database.

Connect the Model with the repository

After defining the Model, you can connect the Model with the repository.

$dbDriver = Factory::getDbInstance('mysql://user:password@server/schema');
$repository = new Repository(DatabaseExecutor::using($dbDriver), MyModel::class);

Querying the database

You can query the database using the repository.

$myModel = $repository->get(1);

or

$query = Query::getInstance()
    ->field('name')
    ->where('company_id = :cid', ['cid' => 1]);

$result = $repository->getByQuery($query);