Explicit mapping
Map an existing table to ordinary PHP objects. Values are converted before your hydrator runs; partial reads return typed rows.
Typed PHP repositories with consistent translations and batch-loaded relations.
The application owns its schema and supplies $db, a DBAL Connection. For an existing products table with a generated integer id, sku, and decimal price:
use Doctrine\DBAL\Types\Types;
use Solo\Repository\Mapping;
use Solo\Repository\PageRequest;
use Solo\Repository\Repository;
/** @var Repository<stdClass> $products */
$products = new Repository($db, new Mapping(
table: 'products',
columns: ['id' => Types::INTEGER, 'sku' => Types::STRING, 'price' => Types::DECIMAL],
hydrate: static fn(array $row): stdClass => (object) $row,
));
$id = $products->insertGetId(['sku' => 'CHAIR', 'price' => '49.90']);
$products->update($id, ['price' => '59.90']);
$product = $products->read()->find($id);
$page = $products->read()->page(
new PageRequest(page: 1, perPage: 20, orderBy: ['price' => 'ASC']),
criteria: ['price >=' => '50.00'],
);Replace the object cast with your model constructor. Writes do not reread a model automatically; rows() supports projections without hydration. Read the getting-started guide and API reference for translations, relations, visibility, and transaction contracts.
PHP 8.3+, Doctrine DBAL ^4.3, and the matching PDO driver are required. The integration matrix covers SQLite, MySQL 8.4, MariaDB 12.3, and PostgreSQL 17.
composer require solophp/repositoryContinue with the getting-started guide.