yiisoft/active-record
Active Record ORM for PHP in the Yii3 ecosystem. Map database tables to classes, perform CRUD operations, define relationships, and build queries through a familiar object-oriented API on top of yiisoft/db. A lightweight choice for ActiveRecord-style persistence.
yiisoft/active-record is a standalone ActiveRecord implementation, not an Eloquent replacement. Treat it as a query/relation layer you can wire into Laravel when you want Yii-style AR behavior or are integrating Yii-derived code.
Minimal setup:
yiisoft/db and the appropriate DB driver:
composer require yiisoft/active-record yiisoft/db
Yiisoft\Db\Connection\ConnectionInterface singleton in a Laravel service provider.yiisoft/config plugin, so if you already use yiisoft/config, start there; otherwise bind the connection manually in Laravel.tableName() and a relation.Where to look first:
ActiveRecord / AbstractActiveRecord for property mapping, dirty tracking, hooks, and get().ActiveQuery for query construction.JoinWith for relation joins and closure-based join constraints.yiisoft/db connection for transactions, logging, and command execution.First practical use case: map an existing table to an AR class, define a hasMany relation, then query with find() and joinWith() in a read path. This gives you the package’s main value: relation-aware query building without adopting Eloquent.
Model and relation definitions
hasOne() / hasMany().Relation joins
joinWith() with string relation names for simple joins.$relations parameter is now explicitly typed as array<string|callable(ActiveQueryInterface):void>. Type-hint closures against ActiveQueryInterface, not a concrete ActiveQuery:
->joinWith([
'customer' => function (ActiveQueryInterface $query) {
$query->andWhere(['active' => true]);
},
])
Upsert and sync workflows
upsert() for import/sync jobs where rows may already exist.$updateProperties = false now works as insert-only.upsert() are prioritized during updates.Soft delete
SoftDelete support for archival flows.SoftDelete with an initiated custom date. If you set a custom deletion timestamp, re-test delete/restore paths.Hooks
beforeSave / afterSave-style hook logic small and deterministic.Performance-sensitive reads
ActiveRecord::get() was optimized in 1.1.0. Use it for primary-key lookups in hot paths, but benchmark against your own data and indexes.joinWith() or batch queries where appropriate.Laravel integration
yiisoft/db connection into your service layer and use it for transactions.yiisoft/config, adopt the new default plugin config as a baseline and override only what you need.JoinWith. The signature is now array<string|callable(ActiveQueryInterface):void>. If you type-hinted a closure parameter as ActiveQuery, change it to ActiveQueryInterface to stay compatible.upsert() edge cases. $updateProperties = false now inserts only, and associative values win during updates. Re-check sync jobs that pass both associative values and update-column lists.AbstractActiveRecord::markPropertyChanged() no longer checks for an empty string. If your code relied on empty-string changes being ignored, verify update statements and optimistic-locking behavior.^1.1. Still run your relation, upsert, soft-delete, and hook tests because several behavior fixes can expose assumptions.yiisoft/db logger to inspect SQL. When a relation or upsert behaves unexpectedly, log the generated command and compare it with the related class’s query configuration.How can I help you explore Laravel packages today?