Skip to content

Implement 'belongs to' relations in models #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 12, 2025
10 changes: 6 additions & 4 deletions src/generator/default/dbmodel.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,14 @@ public function get<?= $relation->getCamelName() ?>()
<?php endif;?>
}
<?php endforeach; ?>
<?php $i = 1; foreach ($model->inverseRelations as $relationName => $relation): ?>
<?php $i = 1; $usedRelationNames = [];
foreach ($model->belongsToRelations as $relationName => $relation): ?><?php $number = in_array($relation->getCamelName(), $usedRelationNames) ? $i : '' ?>

public function get<?= $relation->getCamelName().($i===1 ? '' : $i) ?>()
# belongs to relation
public function get<?= $relation->getCamelName() . ($number) ?>()
{
return $this-><?= $relation->getMethod() ?>(\<?= trim($relationNamespace, '\\') ?>\<?= $relation->getClassName() ?>::class, <?php
echo $relation->linkToString() ?>)->inverseOf('<?= $relation->getInverse() ?>');
echo $relation->linkToString() ?>);
}
<?php $i++; endforeach; ?>
<?php $i++; $usedRelationNames[] = $relation->getCamelName(); endforeach; ?>
}
41 changes: 15 additions & 26 deletions src/lib/AttributeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class AttributeResolver
*/
public array $relations = [];

/**
* @var array keys contains class names and value contains array of belongs to relations
*/
public array $belongsToRelations = [];

/**
* @var NonDbRelation[]|array
*/
Expand All @@ -60,11 +65,6 @@ class AttributeResolver

private ?Config $config;

/**
* @var AttributeRelation[]|array
*/
public array $inverseRelations = [];

public function __construct(string $schemaName, ComponentSchema $schema, JunctionSchemas $junctions, ?Config $config = null)
{
$this->schemaName = $schemaName;
Expand Down Expand Up @@ -232,6 +232,7 @@ protected function resolveProperty(
->setForeignKeyColumnName($property->fkColName)
->setFakerStub($this->guessFakerStub($attribute, $property))
->setTableName($this->componentSchema->resolveTableName($this->schemaName));

if ($property->isReference()) {
if ($property->isVirtual()) {
throw new InvalidDefinitionException('References not supported for virtual attributes');
Expand Down Expand Up @@ -277,12 +278,17 @@ protected function resolveProperty(
$relation->onDeleteFkConstraint = $property->onDeleteFkConstraint;
if ($property->isRefPointerToSelf()) {
$relation->asSelfReference();
} else { # belongs to relations https://github.com/php-openapi/yii2-openapi/issues/90
$belongsToRelation = Yii::createObject(
AttributeRelation::class,
[$this->schemaName, $this->tableName, $this->schemaName]
)
->asHasOne([$attribute->columnName => $fkProperty->getName()]);
$this->belongsToRelations[$property->getRefClassName()][] = $belongsToRelation;
}
$this->relations[$property->getName()] = $relation;
if (!$property->isRefPointerToSelf()) {
$this->addInverseRelation($relatedClassName, $attribute, $property, $fkProperty);
}
}

if (!$property->isReference() && !$property->hasRefItems()) {
[$min, $max] = $property->guessMinMax();
$attribute->setIsVirtual($property->isVirtual())
Expand Down Expand Up @@ -338,6 +344,7 @@ protected function resolveProperty(
->asHasMany([$foreignPk => $this->componentSchema->getPkName()]);
return;
}

$relatedClassName = $property->getRefClassName();
$relatedTableName = $property->getRefSchema()->resolveTableName($relatedClassName);
if ($this->catchManyToMany(
Expand Down Expand Up @@ -518,22 +525,4 @@ public static function relationName(string $propertyName, ?string $fkColumnName)
}
return $relationName;
}

/**
* @throws InvalidConfigException
*/
public function addInverseRelation(
string $relatedClassName,
Attribute $attribute,
PropertySchema $property,
PropertySchema $fkProperty
): void {
$inverseRelation = Yii::createObject(
AttributeRelation::class,
[$this->schemaName, $this->tableName, $this->schemaName]
)
->asHasOne([$attribute->columnName => $fkProperty->getName()]);
$inverseRelation->setInverse($property->getName());
$this->inverseRelations[$relatedClassName][] = $inverseRelation;
}
}
11 changes: 4 additions & 7 deletions src/lib/SchemaToDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,15 @@ public function prepareModels(): array
/** @var AttributeResolver $resolver */
$resolver = Yii::createObject(AttributeResolver::class, [$schemaName, $schema, $junctions, $this->config]);

// $models[$schemaName] = $resolver->resolve();
$resolvers[$schemaName] = $resolver;
$models[$schemaName] = $resolvers[$schemaName]->resolve();
}

// handle inverse relation
// handle belongs to relation
foreach ($resolvers as $aResolver) {
foreach ($aResolver->inverseRelations as $name => $relations) {
foreach ($relations as $relation) {
/** @var AttributeRelation $relation */
$models[$name]->inverseRelations[] = $relation;
}
foreach ($aResolver->belongsToRelations as $name => $relations) {
/** @var AttributeRelation[] $relations */
$models[$name]->belongsToRelations = [...$models[$name]->belongsToRelations, ...$relations];
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/lib/items/DbModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,6 @@ class DbModel extends BaseObject
*/
public array $many2many = [];

/**
* @var array|AttributeRelation[] inverse relations
*/
public array $inverseRelations = [];

public array $junctionCols = [];

/**
Expand All @@ -91,9 +86,9 @@ class DbModel extends BaseObject
public bool $descriptionIsComment = false;

/**
* @var array Automatically generated scenarios from the model 'x-scenarios'.
* @var AttributeRelation[] belongs to relations
*/
private $_scenarios;
public array $belongsToRelations = [];

/**
* @var bool
Expand All @@ -103,6 +98,11 @@ class DbModel extends BaseObject
*/
public $drop = false;

/**
* @var array Automatically generated scenarios from the model 'x-scenarios'.
*/
private $_scenarios;

public function getTableAlias(): string
{
return '{{%' . $this->tableName . '}}';
Expand Down
3 changes: 2 additions & 1 deletion tests/specs/blog/models/base/Category.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ public function getPosts()
return $this->hasMany(\app\models\Post::class, ['category_id' => 'id'])->inverseOf('category');
}

# belongs to relation
public function getPost()
{
return $this->hasOne(\app\models\Post::class, ['category_id' => 'id'])->inverseOf('category');
return $this->hasOne(\app\models\Post::class, ['category_id' => 'id']);
}
}
3 changes: 2 additions & 1 deletion tests/specs/blog/models/base/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ public function getComments()
return $this->hasMany(\app\models\Comment::class, ['post_id' => 'uid'])->inverseOf('post');
}

# belongs to relation
public function getComment()
{
return $this->hasOne(\app\models\Comment::class, ['post_id' => 'uid'])->inverseOf('post');
return $this->hasOne(\app\models\Comment::class, ['post_id' => 'uid']);
}
}
8 changes: 5 additions & 3 deletions tests/specs/blog/models/base/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ public function rules()
];
}

# belongs to relation
public function getPost()
{
return $this->hasOne(\app\models\Post::class, ['created_by_id' => 'id'])->inverseOf('created_by');
return $this->hasOne(\app\models\Post::class, ['created_by_id' => 'id']);
}

public function getComment2()
# belongs to relation
public function getComment()
{
return $this->hasOne(\app\models\Comment::class, ['author_id' => 'id'])->inverseOf('author');
return $this->hasOne(\app\models\Comment::class, ['author_id' => 'id']);
}
}
3 changes: 2 additions & 1 deletion tests/specs/blog_v2/models/base/Category.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ public function getPosts()
return $this->hasMany(\app\models\Post::class, ['category_id' => 'id'])->inverseOf('category');
}

# belongs to relation
public function getPost()
{
return $this->hasOne(\app\models\Post::class, ['category_id' => 'id'])->inverseOf('category');
return $this->hasOne(\app\models\Post::class, ['category_id' => 'id']);
}
}
3 changes: 2 additions & 1 deletion tests/specs/blog_v2/models/base/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ public function getTags()
->viaTable('posts2tags', ['post_id' => 'id']);
}

# belongs to relation
public function getComment()
{
return $this->hasOne(\app\models\Comment::class, ['post_id' => 'id'])->inverseOf('post');
return $this->hasOne(\app\models\Comment::class, ['post_id' => 'id']);
}
}
8 changes: 5 additions & 3 deletions tests/specs/blog_v2/models/base/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ public function rules()
];
}

# belongs to relation
public function getPost()
{
return $this->hasOne(\app\models\Post::class, ['created_by_id' => 'id'])->inverseOf('created_by');
return $this->hasOne(\app\models\Post::class, ['created_by_id' => 'id']);
}

public function getComment2()
# belongs to relation
public function getComment()
{
return $this->hasOne(\app\models\Comment::class, ['user_id' => 'id'])->inverseOf('user');
return $this->hasOne(\app\models\Comment::class, ['user_id' => 'id']);
}
}
3 changes: 2 additions & 1 deletion tests/specs/fk_col_name/app/models/base/Delivery.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ public function rules()
];
}

# belongs to relation
public function getWebhook()
{
return $this->hasOne(\app\models\Webhook::class, ['redelivery_of' => 'id'])->inverseOf('redelivery_of');
return $this->hasOne(\app\models\Webhook::class, ['redelivery_of' => 'id']);
}
}
3 changes: 2 additions & 1 deletion tests/specs/fk_col_name/app/models/base/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ public function rules()
];
}

# belongs to relation
public function getWebhook()
{
return $this->hasOne(\app\models\Webhook::class, ['user_id' => 'id'])->inverseOf('user');
return $this->hasOne(\app\models\Webhook::class, ['user_id' => 'id']);
}
}
6 changes: 4 additions & 2 deletions tests/specs/fk_col_name_index/app/models/base/Delivery.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ public function rules()
];
}

# belongs to relation
public function getWebhook()
{
return $this->hasOne(\app\models\Webhook::class, ['redelivery_of' => 'id'])->inverseOf('redelivery_of');
return $this->hasOne(\app\models\Webhook::class, ['redelivery_of' => 'id']);
}

# belongs to relation
public function getWebhook2()
{
return $this->hasOne(\app\models\Webhook::class, ['rd_abc_2' => 'id'])->inverseOf('rd2');
return $this->hasOne(\app\models\Webhook::class, ['rd_abc_2' => 'id']);
}
}
3 changes: 2 additions & 1 deletion tests/specs/fk_col_name_index/app/models/base/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ public function rules()
];
}

# belongs to relation
public function getWebhook()
{
return $this->hasOne(\app\models\Webhook::class, ['user_id' => 'id'])->inverseOf('user');
return $this->hasOne(\app\models\Webhook::class, ['user_id' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public function rules()
];
}

# belongs to relation
public function getContact()
{
return $this->hasOne(\app\models\Contact::class, ['mailing_id' => 'id'])->inverseOf('mailing');
return $this->hasOne(\app\models\Contact::class, ['mailing_id' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ public function rules()
return [];
}

# belongs to relation
public function getOrder()
{
return $this->hasOne(\app\models\Order::class, ['invoice_id' => 'id'])->inverseOf('invoice');
return $this->hasOne(\app\models\Order::class, ['invoice_id' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public function rules()
];
}

# belongs to relation
public function getContact()
{
return $this->hasOne(\app\models\Contact::class, ['account_id' => 'id'])->inverseOf('account');
return $this->hasOne(\app\models\Contact::class, ['account_id' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,21 @@ public function getAccounts()
return $this->hasMany(\app\models\Account::class, ['user_id' => 'id'])->inverseOf('user');
}

# belongs to relation
public function getAccount()
{
return $this->hasOne(\app\models\Account::class, ['user_id' => 'id'])->inverseOf('user');
return $this->hasOne(\app\models\Account::class, ['user_id' => 'id']);
}

# belongs to relation
public function getAccount2()
{
return $this->hasOne(\app\models\Account::class, ['user2_id' => 'id'])->inverseOf('user2');
return $this->hasOne(\app\models\Account::class, ['user2_id' => 'id']);
}

# belongs to relation
public function getAccount3()
{
return $this->hasOne(\app\models\Account::class, ['user3' => 'id'])->inverseOf('user3');
return $this->hasOne(\app\models\Account::class, ['user3' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ public function rules()
];
}

# belongs to relation
public function getPost()
{
return $this->hasOne(\app\models\Post::class, ['user' => 'id'])->inverseOf('user');
return $this->hasOne(\app\models\Post::class, ['user' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ public function rules()
];
}

# belongs to relation
public function getInvoice()
{
return $this->hasOne(\app\models\Invoice::class, ['animal_id' => 'id'])->inverseOf('animal');
return $this->hasOne(\app\models\Invoice::class, ['animal_id' => 'id']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ public function rules()
];
}

# belongs to relation
public function getInvoice()
{
return $this->hasOne(\app\models\Invoice::class, ['fruit_id' => 'id'])->inverseOf('fruit');
return $this->hasOne(\app\models\Invoice::class, ['fruit_id' => 'id']);
}
}
Loading