Создание базовой модели

В CMS реализована простая модель. Мы честно признаем, что эта модель, нечто среднее между ELoquento от Laravel и библиотеки PDOx.

В целом модель обеспечивает необходимый набор дейтсвий с данными, при минимальных зависимостях.


Как создать модель?

Есть два способа создать модель.

1. Классический, когда вы в вашем модуле создает папку models. Затем в папке создаете файл с вашей моделью, описывая ее по правилам.

2. Более быстрый. Для этого вам необходимо создать таблицу данных в БД. Затем зайти в модуль GKG и там выбрать создание модели. В этом случае модель сгенерируется сама с описанием ваших данных.


Как выглядит модель


Модель это класс, котоорый наследуются от основной модели из ядра (Core).

Изначально модель может состоять всего лишь из этих строк:

<?php
namespace ВАШ ПУТЬ;

user core\Model;

class ВАШ КЛАСС extends Model {
 public $table = "Ваша таблица";
 public $sanitize = ['field1','field2']; // для полей получаемых от стороннего пользователя
 
}


По сути это все, что нужно для работы базовой модели.

Что может модель?

На самом деле многое, как пример:

Выборки:


Предположим нам нужно получить все записи из нашей таблицы:

 $model->getAll(); //вернет массив объектов

С ограничением по полям:

 $model->select(['id','name'])->getAll(); //вернет массив объектов только указанные поля

Получить одну запись по ID:

 $model->getOne('ID'); //вернет один объект

Получить выборку по условию:

 $model->where('id','>',5)->getAll();

Получить выборку с ограничением:

 $model->where('id','>',5)->limit(5)->getAll();

Множественные условия:

 $model->select(['name', 'id', 'alias', 'data_create'])
 ->where('visible', '=', 1)
 ->where('deleted', '=', 0)
 ->where('categories_id', '=', $catId)
 ->whereRaw('(data_end > NOW() or data_end is null) ')
 ->whereRaw('(data_create <= NOW() or data_create is null) ')
 ->orderBy('data_create DESC')
 ->getAll();

Выборка с группировкой:

Primes::instance()
 ->where(
 function ($q) use ($userId) {
 $q->where('to_user_id', intval($userId))
 ->where('user_id', User::current()->id);
 })
 ->where(
 function ($q) use ($userId) {
 $q->orWhere('to_user_id', User::current()->id)
 ->where('user_id', intval($userId));
 })
 ->getAll(); //если хотим увидеть запрос то getQuery()

Вставки:


Добавление записи:

 $m = new Model();

 $m->name = "Вася";

 $m->show = 'Y';

 $m->save();

Можно так:

 $model->insert('ARRAY OF DATA'); // где массив ключ значение


После любой вставки вам возвращается PK. Массовая вставка пока не предусмотрена, но решается вставкой в цикле.


Обновление:

Классическая схема подразумевает, что вы сначала получаете данные, а затем их обновляете.

Схема с получением данных:

$m = new Model();

$m->getOne(PK);

$m->name = 'Petro';

$m->save();

Ниже схема без получения данных:

  Три разных способа:

 $m = new Model();

 $m->name = 'Petro';

 $m->PK = 3; //ОБЯЗАТЕЛЬНО ПЕРЕДАЕМ Первичный ключ, иначе будет вставка

 $m->save();


$m->update($data); // где data это массив или объект данных содержащий PK


$m->save($data); //аналогично записи 2, но если в записи два всегда будет ошибка если нет PK, то в этом случае будет вставка.


Обновление в цикле

Иногда нам нужно делать операции в цикле или с большим объемом данных.  Операция не частая, но как вариант можно делать так:

$m = new Model();

foreach ($array as $item) {

 $m->clear()->update($item); //clear -- опусташает модель до первичного состояния, гарантируя отсутствие коллизий. В целом должно работать и без него.

}

Удаление:


Почистим табилицу:

 $m->truncate();

Удалим запись:

 $m->delete('PK');

Удалим все скрытые записи:

 $m->where('visible', 'n')->delete();

Удалим записи в диапазоне:

 $m->between('id', '5', '10')->delete();


Зависимости:


Предположим, что у нас есть статьи, и категории. В этом случае писать запрос на получение можно, но удобнее воспользоваться методами модели:

И так в классе Категории мы делаем связь с статьями:

class Category extends Model {

...

 public function articles()
 {
 return $this->hasMany(Article::instance(), 'categories_id');
 }

...

}

В классе статей делаем связь с категорией:

class Article extends Model {
...
/**
 * Связь к категории
 */
 public function category()
 {
 return $this->belongsTo(Categories::instance(), 'id');
 }

...
}


Соотвественно используя ту или иную модель, мы легко получаем связанные вещи, и только тогда, когда к ним обращаемся.


Кроссмодельные выборки


$model

 ->in('id', UserPermission::instance()->select(['permission_id']) //в условия можно передавать класс которые является инстансом модели

 ->where(['user_id' => USER::current()->id])) //условия можно передавать в виде массива, но в этом случае считается что условие будет `ключ` = `значению`

 ->getAll()


Фишечки:


В модели предусмотрены методы, которые могут ничего не возвращать, но модифицировать информацию самой модели:

beforeSave() // перед сохранением (например преобразовать урл)
afterSave() //после сохранения ( например провести тест, или проверить консистентность данных)

beforeInsert() //перед вставкой (например проверить права)
afterInsert() //после вставки (например сохранить картинку)

beforeSelect() //перед выборкой 
afterSelect() //после выборки

beforeUpdate() //перед обновлением
afterUpdate() //после обновления

beforeDelete() //перед удалением (например проверить зависимости)
afterDelete() //после удаления (например удалить картинку)

getQuery() //получить запрос (ставим вместо query, getAll, getOne и получаем вывод запроса на экран)

toArray() //результат в массив

toCollection() //результат в коллекцию