Skip to content

Version 6.0.0

Choose a tag to compare

@visavi visavi released this 28 Aug 16:17
· 1 commit to master since this release

Ломающие изменения

Модель снова строка таблицы, Record убран. Пятая версия разделила модель
на три класса и оставила поведение строки без места: колонка принадлежала
Record, поэтому всё, что строка умеет сказать о себе, приходилось держать
классом рядом с моделью. Одна таблица — два файла, и чем меньше модель, тем
дороже обходилось разделение.

Модель объявляет таблицу и, прочитанная, держит значения одной строки. Что
строка умеет отвечать — метод модели, рядом с колонками.

class Article extends Model
{
    public string $table = 'articles.csv';

    public function excerpt(int $words = 30): string
    {
        return implode(' ', array_slice(explode(' ', $this->text), 0, $words));
    }
}

$article = Article::query()->find(1);   // Article
$article->excerpt();

Найденное пятой версией осталось: строка не несёт условий. where(),
orderBy(), limit() принадлежат Query, поэтому строка не читает таблицу
сама по себе, а связь по-прежнему только метод, объявивший возврат Relation.

find(), first(), get(), cursor(), create() и связи отдают модель.
fresh(), save(), delete(), update(), key(), toArray(),
relationLoaded() и newQuery() — те же методы на модели. RecordMapper стал
RowMapper.

Строка несёт декларацию вместе со значениями, поэтому стоит немного дороже
записи: около 790 байт против 690 на пяти колонках, 377 МБ против 347 на
500 000 строк, прочитанных целиком. Чтение страницы, обход cursor() и подсчёт
не изменились.

Ничего не читается из окружения. resolveCurrentPage() лез в $_GET,
поэтому orm, читающая csv, имела мнение о http, а ответ зависел от того, где
выполняется код: консольная команда, воркер очереди и тест получали то, что
оставил после себя последний запрос. Страницу называет page() или резолвер
приложения, без них имеется в виду первая.

// один раз, в бутстрапе приложения
Pagination::resolvePageUsing(static fn (string $name) => $_GET[$name] ?? 1);

links() и встроенный шаблон Bootstrap 5 убраны. Orm везла в комплекте
разметку под css-фреймворк, а рендер вместе с буферизацией вывода жил в
библиотеке данных. Навигацию отдаёт pages() объектами Page, печатает её
приложение:

echo $view->render('pagination', ['pages' => $articles->pages()]);

Экранирование ушло туда же, где печать: Page::$url — обычная строка,
экранирует её тот шаблон, который её выводит.

Collection::__toString() убран. Печать коллекции возвращала
Collection@0000..., так что <?= $stories ?> в шаблоне тихо давал хеш вместо
ошибки.

Добавлено

  • save() вставляет строку, у которой ещё нет ключа, поэтому собранная
    руками модель пишется так же, как прочитанная.
$article = new Article();
$article->title = 'Новый заголовок';
$article->save();               // вставлена, ключ выдала таблица
  • Model::newRow() — строка таблицы с заданными значениями, и
    Model::primaryKey() — имя колонки, в которой лежат ключи.
  • Table::primaryKey() — та же колонка, в единственном классе, который
    владеет колонками. Раньше правило «ключ — первая колонка» знали Query,
    TableWriter, RowMapper и Model, каждый сам по себе.

Исправлено

pluck() больше не теряет строки с пустой колонкой. array_column()
спрашивает у объекта __isset(), а он для null отвечает false, поэтому строка
с пустым значением выпадала из результата вместе со своим ключом: таблица
настроек из 43 строк, одна из которых пустая, отдавала 42. Значения читаются
напрямую, пустая колонка остаётся на своём месте со значением null.

Обновление

composer require visavi/motor-orm:^6.0

Требуется PHP 8.5. Формат файлов таблиц не менялся — миграция данных не нужна.