Skip to content

Repository files navigation

Model Package

Packagist PHP Version SupportPackagist VersionPackagist DownloadsComposer dependenciesTest workflowCodecov

Abstract Model for better data manipulation between code and database.

Dependencies

Database package: https://github.com/rancoud/Database

Installation

composer require rancoud/model

How to use it?

Extends Rancoud\Model\Model to your class.
You have to implement two abstract methods setFields and setTable.

  • setFields is for setting the fields in table
  • setTable is for setting the table in database
class User extends Model
{
protectedfunctionsetFields(): void
{
$this->fields = [
'id' => newField('int', ['not_null', 'unsigned', 'pk']),
'nickname' => newField('varchar', ['max:255', 'not_null'])
];
}
protectedfunctionsetTable(): void
{
$this->table = 'user';
}
}

What is Field?

Field represent a field in the table.
It have 3 arguments:

  1. field type
  2. rules
  3. default value

Field type

It support those field type

  • int
  • float
  • char
  • varchar
  • text
  • date
  • datetime
  • time
  • timestamp
  • year
  • enum:x,y,z (x,y,z represent each possible value)

Rules

  • pk : primary key
  • fk : foreign key
  • unsigned : only positive value
  • email : check if it is valid email
  • not_null : can't be null
  • max:x : max size (x is size)
  • min:x : min size (x is size)
  • range:x,y : min size + max size (x is min size, y is max size)

Custom rule

class MyRule extends CustomRule
{
publicfunctionapplyRule($value)
{
if ($value === 'azerty') {
thrownewFieldException('invalid azerty value');
}
return$value;
}
}

Default

When value is not setted it can be set with those argument

Helpers

It have methods for pagination, create, read, update and delete.

// $database is an instance of Rancoud\Database\Database$user = newUser($database);
$newId = $user->create(['nickname' => 'rancoud']);
$row = $user->one($newId);
// you will have an array representing data in database with correct types// here : ['id' => 1, 'nickname' => 'rancoud'];$rows = $user->all();
// here it's all rows in table : [ ['id' => 1, 'nickname' => 'rancoud'] ] $user->update(['nickname' => 'rancoud2'], $newId);
$user->delete($newId);

Model::all() accept an array with some keys that triggers specific actions

// $database is an instance of Rancoud\Database\Database$user = newUser($database);
// 50 rows using LIMIT 50 OFFSET 50$rows = $user->all(['page' => 1]);
// 10 rows using LIMIT 10 OFFSET 10$rows = $user->all(['count' => 10, 'page' => 1]);
// count rows in table$count = $user->all(['rows_count' => 1]);
// return all rows with no limit $count = $user->all(['no_limit' => 1]);
// change order by$count = $user->all(['order' => 'nickname']);
// change order by and order$count = $user->all(['order' => 'nickname|desc']);
// multiple change order by and order$count = $user->all(['order' => 'nickname|desc,id|asc']);

You can change values output in Model::all() with override functions:

  • getSqlAllSelectAndFillSqlParams(params: array)
  • getSqlAllJoinAndFillSqlParams(params: array)
  • getSqlAllWhereAndFillSqlParams(params: array)

Callbacks

You can add callback before and after create, update and delete.

$model->addBeforeCreate('a', function($sql, $params){
// for modifying sql and params use this return otherwise don'treturn [$sql, $params];
});
$model->addAfterCreate('a', function($newId, $params){
// for modifying params use this return otherwise don'treturn$params;
});
$model->addBeforeUpdate('a', function($sql, $params){
// for modifying sql and params use this return otherwise don'treturn [$sql, $params];
});
$model->addAfterUpdate('a', function($params){
// for modifying params use this return otherwise don'treturn$params;
});
$model->addBeforeDelete('a', function($sql, $params){
// for modifying sql and params use this return otherwise don'treturn [$sql, $params];
});
$model->addAfterDelete('a', function($params){
// for modifying params use this return otherwise don'treturn$params;
});

You can use JsonOutput trait for adding json format for the model.

Field Constructor

Settings

Mandatory

ParameterTypeDescription
typestringtype of field, values used : int | float | char | varchar | text | date | datetime | time | timestamp | year

Optionnals

ParameterTypeDefault valueDescription
rulesarray[]rules for checking values, values used : pk | fk | unsigned | email | not_null | max | min | range | Rancoud\Model\CustomRule
defaultmixedfalsedefault value when none given

Field Methods

  • isPrimaryKey(): bool
  • isForeignKey(): bool
  • isNotNull(): bool
  • getDefault(): mixed
  • formatValue(value: mixed): ?mixed

Model Constructor

Settings

Mandatory

ParameterTypeDescription
$database\Rancoud\Database\DatabaseDatabase Instance

Model Methods

General Commands

  • all(params: array, [validFields: array = []]): array|bool|int
  • one(id: mixed, [...ids: mixed = []]): array
  • create(args: array): bool|int
  • update(args: array, id: mixed, [...ids: mixed = []]): void
  • delete(id: mixed, [...ids: mixed = []]): void
  • getLastInsertId(): ?int

Database error

  • getDatabaseErrors(): ?array
  • getDatabaseLastError(): ?array

Callbacks

Add

  • addBeforeCreate(name: string, callback: mixed): void
  • addAfterCreate(name: string, callback: mixed): void
  • addBeforeUpdate(name: string, callback: mixed): void
  • addAfterUpdate(name: string, callback: mixed): void
  • addBeforeDelete(name: string, callback: mixed): void
  • addAfterDelete(name: string, callback: mixed): void

Remove

  • removeBeforeCreate(name: string): void
  • removeAfterCreate(name: string): void
  • removeBeforeUpdate(name: string): void
  • removeAfterUpdate(name: string): void
  • removeBeforeDelete(name: string): void
  • removeAfterDelete(name: string): void

Static Helper Methods

  • getCountPerPage(args: array): int
  • getLimitOffsetCount(args: array): array
  • getOrderByOrderField(args: array, [validFields: array = []]): array
  • getPageNumberForHuman(args: array): int
  • getPageNumberForSql(args: array): int
  • hasInvalidPrimaryKey(value: int): bool
  • hasLimit(args: array): bool
  • implodeOrder(orders: array): string
  • isRowsCount(args: array): bool
  • isValidFieldForOrderBy(field: string, [validFields: array = []]): bool

How to Dev

docker compose build && docker compose run lib composer ci for launching tests

Releases

Used by

Contributors

Languages