156 lines
3.4 KiB
Markdown
156 lines
3.4 KiB
Markdown
# mfBaseModelV2
|
|
|
|
Modern PHP 8+ base model with typed properties and automatic journaling.
|
|
|
|
## Basic Usage
|
|
|
|
```php
|
|
class ADBNetzgebiet extends mfBaseModelV2 {
|
|
protected static string $__tableName = 'Netzgebiet';
|
|
protected static string $__primaryKey = 'id'; // default
|
|
|
|
public int $id;
|
|
public ?string $name = null;
|
|
public ?string $extref = null;
|
|
public int $create;
|
|
public int $edit;
|
|
}
|
|
```
|
|
|
|
## Custom Database
|
|
|
|
```php
|
|
protected static ?array $__databaseConfig = [
|
|
'host' => ADDRESSDB_DBHOST,
|
|
'user' => ADDRESSDB_DBUSER,
|
|
'pass' => ADDRESSDB_DBPASS,
|
|
'name' => ADDRESSDB_DBNAME
|
|
];
|
|
```
|
|
|
|
## Static Methods
|
|
|
|
```php
|
|
$model = MyModel::get(123); // by ID, returns ?static
|
|
$model = MyModel::getFirst(['name' => 'foo']); // first match
|
|
$all = MyModel::getAll($filter, $limit, $offset, $order);
|
|
$all = MyModel::search($filter); // alias for getAll
|
|
$count = MyModel::count($filter);
|
|
```
|
|
|
|
## Filter Operators
|
|
|
|
| Prefix | SQL | Example |
|
|
|--------|-----|---------|
|
|
| (none) | LIKE %...% | `['name' => 'foo']` |
|
|
| `=` | = exact | `['=name' => 'foo']` |
|
|
| `!` | != / NOT IN | `['!status' => 'deleted']` |
|
|
| `>` `<` `>=` `<=` | comparison | `['>create' => $timestamp]` |
|
|
|
|
**Special values:**
|
|
```php
|
|
['status' => null] // IS NULL
|
|
['!status' => null] // IS NOT NULL
|
|
['id' => [1, 2, 3]] // IN (1, 2, 3)
|
|
['!id' => [1, 2, 3]] // NOT IN (1, 2, 3)
|
|
```
|
|
|
|
## Ordering
|
|
|
|
```php
|
|
MyModel::getAll([], null, 0, ['column' => 'name', 'dir' => 'ASC']);
|
|
```
|
|
|
|
## Instance Methods
|
|
|
|
```php
|
|
$model->save(); // insert or update
|
|
$model->delete();
|
|
$model->isLoaded();
|
|
$model->getId();
|
|
$model->toArray();
|
|
$model->toJson();
|
|
$model->getJournalHistory(); // returns change history
|
|
```
|
|
|
|
## Hooks
|
|
|
|
```php
|
|
public function validate(): array {
|
|
$errors = [];
|
|
if (empty($this->name)) $errors[] = 'Name required';
|
|
return $errors; // empty = valid
|
|
}
|
|
|
|
protected function beforeSave(bool $isInsert): bool {
|
|
return true; // false cancels save
|
|
}
|
|
|
|
protected function afterSave(bool $isInsert, array $changes): void {
|
|
// $changes = ['field' => ['old' => x, 'new' => y]]
|
|
}
|
|
```
|
|
|
|
## Journaling
|
|
|
|
Automatic change tracking to `Journal` table. Configure field labels:
|
|
|
|
```php
|
|
protected static array $__journalFieldMap = [
|
|
'name' => 'Name',
|
|
'extref' => 'External Reference',
|
|
];
|
|
```
|
|
|
|
Disable per model:
|
|
```php
|
|
protected static bool $__enableJournaling = false;
|
|
```
|
|
|
|
## Auto-timestamps
|
|
|
|
If properties exist, they're set automatically on save:
|
|
- `create`, `create_by` - on insert
|
|
- `edit`, `edit_by` - on insert/update
|
|
|
|
## Magic Properties with Intellisense
|
|
|
|
Use `@property-read` for lazy-loaded relations:
|
|
|
|
```php
|
|
/**
|
|
* @property-read ADBNetzgebietRelations $relations
|
|
*/
|
|
class ADBNetzgebiet extends mfBaseModelV2 {
|
|
private ?ADBNetzgebietRelations $__relations = null;
|
|
|
|
public function __get(string $name) {
|
|
if ($name === 'relations') {
|
|
return $this->__relations ??= $this->loadRelations();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function loadRelations(): ADBNetzgebietRelations {
|
|
// ...
|
|
}
|
|
}
|
|
```
|
|
|
|
Typed relation class for IDE support:
|
|
|
|
```php
|
|
class ADBNetzgebietRelations {
|
|
/** @var array{id: int, name: string}[] */
|
|
public array $networks = [];
|
|
/** @var array{id: int, name: string}[] */
|
|
public array $campaigns = [];
|
|
}
|
|
```
|
|
|
|
Usage with full autocomplete:
|
|
```php
|
|
$model = ADBNetzgebiet::get(1);
|
|
$model->relations->networks; // IDE knows this is array{id: int, name: string}[]
|
|
```
|