Skip to content

Version 5.2.0

Choose a tag to compare

@visavi visavi released this 05 Aug 10:30
· 8 commits to master since this release

Готовность к PHP 8.6

PHP 8.6 объявляет устаревшими SplFileObject::fgetcsv(), fputcsv(),
setCsvControl() и getCsvControl(). Csv — единственное, ради чего orm вообще
открывал файл, поэтому SplFileObject из пакета убран целиком.

На его месте MotorORM\CsvFile — SeekableIterator поверх обычного
дескриптора. Разбор csv остался за движком: процедурные fgetcsv() и
fputcsv() депрекейт не затрагивает.

Читает быстрее

Строки таблицы отдаёт генератор поверх fgetcsv, а не SplFileObject,
завёрнутый в LimitIterator и CallbackFilterIterator. Строка стоит одно
возобновление генератора вместо вызова каждого метода трёх итераторов.

На 50 000 строк, против того же кода на голом php:

операция было стало
выбрать строки по условию ×1.24 ×1.07
обойти всю таблицу ×1.38 ×1.23
десять последних с сортировкой ×0.80 ×0.73

На 500 000 строк: cursor() 890 → 785 мс, count() 633 → 551 мс,
paginate(10) 638 → 556 мс.

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

Model::file(), Model::createFile() и Table::file() возвращают CsvFile.
Csv-контроль теперь в конструкторе, а не в сеттере.

// 5.1
$file = $model->file();                        // SplFileObject

// 5.2
$file = $model->file();                        // MotorORM\CsvFile
$file->fputcsv(['id', 'title']);               // вызов тот же
foreach ($file->rows(1) as $line => $row) {}   // без заголовка, номер строки => строка

Table::rewrite() отдаёт замыканию номер строки, а не читаемый файл.

// 5.1
$table->rewrite(function (array &$current, SplFileObject $target, SplFileObject $source) {
    if ($source->key() === 0) { /* заголовок */ }
});

// 5.2
$table->rewrite(function (array &$current, CsvFile $target, int $line) {
    if ($line === 0) { /* заголовок */ }
});

paginate() и simplePaginate() больше не принимают страницу. Страницу
называет page() или берёт из ?page= запроса.

// 5.1
Article::query()->paginate(10, (int) ($_GET['page'] ?? 1));

// 5.2
Article::query()->paginate(10);          // страница из запроса
Article::query()->page(3)->paginate(10); // страница названа явно

setPageName() стал статическим и ничего не возвращает. Имя параметра
нужно знать до того, как появится страница строк, поэтому оно не может
принадлежать этой странице.

// 5.1
$articles->setPageName('p')->links();

// 5.2
Pagination::setPageName('p');

Добавлено

- Query::page() — страница пагинации, названная явно.
- PagedCollection::resolvePageUsing() — откуда берётся текущая страница.
Замыканию передаётся имя параметра, null возвращает чтение из query string.
- PagedCollection::resolveCurrentPage() — запрошенная страница, никогда
ниже первой.
- PagedCollection::pageName() — имя параметра страницы.
- with() принимает замыкание на связь. Связь, названная ключом замыкания,
сужается для одного этого чтения — как constrain() сужает каждое. Если есть
оба, условия складываются, объявленное первым.

Story::query()
    ->with([
        'user',
        'comments' => static fn (Query $query) => $query->where('approved', 1),
    ])
    ->get();

Обновление

composer require visavi/motor-orm:^5.2

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