|
4 | 4 | * @var string $namespace |
5 | 5 | * @var string $relationNamespace |
6 | 6 | **/ |
| 7 | +use cebe\yii2openapi\lib\items\AttributeRelation; |
7 | 8 | use yii\helpers\Inflector; |
8 | 9 | use yii\helpers\VarDumper; |
9 | 10 |
|
| 11 | +$allCoveredClasses = array_merge( |
| 12 | + array_map(fn($r) => $r->getClassName(), (array)$model->relations), |
| 13 | + array_map(fn($r) => $r->relatedClassName, (array)$model->many2many), |
| 14 | + array_map(fn($r) => $r->getClassName(), (array)$model->nonDbRelations) |
| 15 | +); |
| 16 | +/** |
| 17 | + * Resolve inverse relation method names from the FK column name of the other model. |
| 18 | + * Relations already covered by $model->relations, many2many, or nonDbRelations are skipped. |
| 19 | + * Relations from models declared with "x-table: false" are skipped (no real table, no FK). |
| 20 | + * |
| 21 | + * Naming logic (model being generated = e.g. "Lead", $modelSnake = "lead"): |
| 22 | + * 1. Take the FK column name from the other model (e.g. Order.customer_lead_id) |
| 23 | + * 2. Strip trailing "_id" → "customer_lead" |
| 24 | + * 3. Strip trailing "_<modelSnake>" → "customer" |
| 25 | + * 4. If a prefix remains, prepend it to the pluralized class name: |
| 26 | + * "customer" + "Orders" → getCustomerOrders() |
| 27 | + * If no prefix remains (plain FK like "lead_id"): |
| 28 | + * "" + "Orders" → getOrders() |
| 29 | + * |
| 30 | + * Examples: Order has three FK columns pointing to Lead ($model->name = "Lead"): |
| 31 | + * |
| 32 | + * FK column (on Order) | generated on Order | generated on Lead (inverse) |
| 33 | + * --------------------------|-------------------------|---------------------------- |
| 34 | + * lead_id | getLead() | getOrders() |
| 35 | + * customer_lead_id | getCustomerLead() | getCustomerOrders() |
| 36 | + * billing_lead_id | getBillingLead() | getBillingOrders() |
| 37 | + */ |
| 38 | +$modelSnake = Inflector::underscore($model->name); |
| 39 | +$inverseRelations = array_map(function (AttributeRelation $relation) use ($modelSnake): array { |
| 40 | + $inverseMethod = $relation->getMethod() === 'hasOne' ? 'hasMany' : 'hasOne'; |
| 41 | + $classBase = $inverseMethod === 'hasMany' ? Inflector::pluralize($relation->getCamelName()) : $relation->getCamelName(); |
| 42 | + $fkBase = preg_replace('/_id$/', '', $relation->getForeignName()); |
| 43 | + $prefix = preg_replace('/_?' . preg_quote($modelSnake, '/') . '$/', '', $fkBase); |
| 44 | + return [ |
| 45 | + 'relation' => $relation, |
| 46 | + 'inverseMethod' => $inverseMethod, |
| 47 | + 'inverseName' => $prefix !== '' ? Inflector::camelize($prefix) . $classBase : $classBase, |
| 48 | + ]; |
| 49 | +}, array_filter( |
| 50 | + (array)$model->belongsToRelations, |
| 51 | + fn(AttributeRelation $r) => !in_array($r->getClassName(), $allCoveredClasses) && $r->getTableName() !== '' |
| 52 | +)); |
10 | 53 | ?> |
11 | 54 | <?= '<?php' ?> |
12 | 55 |
|
|
45 | 88 | <?php foreach ($model->many2many as $relation): ?> |
46 | 89 | * @property array|\<?= trim($relationNamespace, '\\') ?>\<?= $relation->relatedClassName ?>[] $<?= Inflector::variablize($relation->name) ?> |
47 | 90 |
|
| 91 | +<?php endforeach; ?> |
| 92 | +<?php foreach ($inverseRelations as $inverse): ?> |
| 93 | +<?php if ($inverse['inverseMethod'] === 'hasOne'):?> |
| 94 | + * @property \<?= trim($relationNamespace, '\\') ?>\<?= $inverse['relation']->getClassName() ?> $<?= Inflector::variablize($inverse['inverseName']) ?> |
| 95 | + |
| 96 | +<?php else:?> |
| 97 | + * @property array|\<?= trim($relationNamespace, '\\') ?>\<?= $inverse['relation']->getClassName() ?>[] $<?= Inflector::variablize($inverse['inverseName']) ?> |
| 98 | + |
| 99 | +<?php endif?> |
48 | 100 | <?php endforeach; ?> |
49 | 101 | */ |
50 | 102 | abstract class <?= $model->getClassName() ?> extends \yii\db\ActiveRecord |
@@ -146,14 +198,17 @@ public function get<?= $relation->getCamelName() ?>() |
146 | 198 | <?php endif;?> |
147 | 199 | } |
148 | 200 | <?php endforeach; ?> |
149 | | -<?php $i = 1; $usedRelationNames = []; |
150 | | -foreach ($model->belongsToRelations as $relationName => $relation): ?><?php $number = in_array($relation->getCamelName(), $usedRelationNames) ? $i : '' ?> |
| 201 | +<?php foreach ($model->nonDbRelations as $nonDbRelation): ?> |
151 | 202 |
|
152 | | - # belongs to relation |
153 | | - public function get<?= $relation->getCamelName() . ($number) ?>() |
| 203 | + abstract public function get<?= $nonDbRelation->getCamelName() ?>(): \yii\db\ActiveQuery; |
| 204 | +<?php endforeach; ?> |
| 205 | +<?php foreach ($inverseRelations as $inverse): ?> |
| 206 | + |
| 207 | + # inverse relation |
| 208 | + public function get<?= $inverse['inverseName'] ?>() |
154 | 209 | { |
155 | | - return $this-><?= $relation->getMethod() ?>(\<?= trim($relationNamespace, '\\') ?>\<?= $relation->getClassName() ?>::class, <?php |
156 | | - echo $relation->linkToString() ?>); |
| 210 | + return $this-><?= $inverse['inverseMethod'] ?>(\<?= trim($relationNamespace, '\\') ?>\<?= $inverse['relation']->getClassName() ?>::class, <?php |
| 211 | + echo $inverse['relation']->linkToString() ?>); |
157 | 212 | } |
158 | | -<?php $i++; $usedRelationNames[] = $relation->getCamelName(); endforeach; ?> |
| 213 | +<?php endforeach; ?> |
159 | 214 | } |
0 commit comments