carono / yii2-pivot
Trait for pivoting models
Fund package maintenance!
Opencollective
yiisoft
Installs: 0
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:yii2-extension
pkg:composer/carono/yii2-pivot
Requires
- php: ^8.1
- yiisoft/yii2: ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.89.1
- maglnet/composer-require-checker: ^4.7.1
- phpunit/phpunit: ^10.5.46
- rector/rector: ^2.0.16
- roave/infection-static-analysis-plugin: ^1.35
- spatie/phpunit-watcher: ^1.24
- vimeo/psalm: ^5.26.1 || ^6.10.3
This package is auto-updated.
Last update: 2026-01-07 11:54:33 UTC
README
PivotTrait is a Yii2 ActiveRecord trait that helps work with “pivot” (junction) tables in many-to-many relations: it can find/get pivot rows, stage pivot changes in an internal storage, and then persist them (insert/update) or delete them.
What it provides
- Query helpers:
findPivot($model, $pivotClass)/getPivot($model, $pivotClass, $condition = [])to build/query a single pivot record between “this” model and a related model.findPivots($pivotClass)/getPivots($pivotClass, $condition = [])to query all pivot rows for the current model (by its PK).
- In-memory staging (“storage”) of pivot operations:
storagePivot($model, $pivotClass, $attributes = [])andstoragePivots($models, $pivotClass, $attributes = [])store related models (and optional extra pivot attributes) keyed byspl_object_hash.getPivotStorage(),getStoragePivots($pivotClass),getStoragePivotAttribute($model, $pivotClass),clearStorage($pivotClass)to inspect/clear staged data.
- Persistence helpers:
savePivots($clear = false, $condition = [])iterates stored pivots and writes them, optionally clearing existing pivots first.addPivot($model, $pivotClass, $attributes = [])upserts a pivot row: if found by key condition it updates attributes, otherwise inserts a new row.deletePivot($model, $pivotClass, $condition = [])deletes a single pivot row for a given related model (plus extra condition).
How pivot keys are detected
The trait builds a pivot “condition” like: [pivot_main_fk => this->PK, pivot_slave_fk => relatedModel->PK].
Pivot key field names are resolved by checking the pivot table schema primary keys and trying to match foreign keys to the involved tables; if it cannot uniquely match by FK, it falls back to the first PK column as “main” and second PK column as “slave”.
Usage examples
1) Upsert a pivot row directly
class User extends \yii\db\ActiveRecord { use PivotTrait; } $user = User::findOne(1); $role = Role::findOne(5); // Upsert pivot row (user_id, role_id) with extra attributes. $user->addPivot($role, UserRole::class, ['created_at' => time()]);
This will update an existing UserRole record matching the computed condition, or create a new one otherwise.
2) Stage multiple pivots, then save them
$user->storagePivots([$role1, $role2], UserRole::class, ['created_at' => time()]); $user->savePivots(); // writes all staged items $user->clearStorage(UserRole::class);
Staging stores models + attributes in an internal storage array, and savePivots() persists them by calling addPivot() for each entry.
3) Replace all pivots for a class (clear then insert)
$user->storagePivots($newRoles, UserRole::class); $user->savePivots(true); // $clear=true => delete existing pivots first, then add staged ones
When $clear is true, the trait deletes existing pivot rows for that pivot class before adding the staged ones.
Notes / assumptions
- The trait assumes both the current model and related models have a single-column primary key (it uses
primaryKey()[0]). - The pivot table is expected to have a composite primary key with two columns (the code accesses
$pks[0]and$pks).
If you share the pivot AR class (the junction ActiveRecord) and the two related AR models, a more concrete README-style snippet can be written with real class/table/column names.