Skip to content

Commit

Permalink
Add MagicRelationsTrait::relationNames() method
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Jul 4, 2024
1 parent 8b686a0 commit 3d75d25
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/Trait/MagicRelationsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@
use Yiisoft\ActiveRecord\ActiveRecordInterface;
use Yiisoft\Db\Exception\InvalidArgumentException;

use function get_class_methods;
use function is_a;
use function lcfirst;
use function method_exists;
use function str_ends_with;
use function str_starts_with;
use function substr;
use function ucfirst;

/**
* Trait to define {@see ActiveRecordInterface::relationQuery()} method to access relation queries of an ActiveRecord
* instance.
* instance. Also, it defines {@see ActiveRecordInterface::relationNames()} method to get names of all relations
* defined in the ActiveRecord class.
*/
trait MagicRelationsTrait
{
Expand Down Expand Up @@ -75,4 +79,37 @@ public function relationQuery(string $name): ActiveQueryInterface

return $this->$getter();
}

/**
* Returns names of all relations defined in the ActiveRecord class using getter methods with `get` prefix and
* `Query` suffix.
*
* @return string[]
*
* @throws ReflectionException
*/
public function relationNames(): array
{
$methods = get_class_methods($this);

$relations = [];

foreach ($methods as $method) {
if (str_starts_with($method, 'get') && str_ends_with($method, 'Query')) {
$reflection = new ReflectionMethod($this, $method);
$type = $reflection->getReturnType();

if (
$type === null
|| !is_a('\\' . $type->getName(), ActiveQueryInterface::class, true)
) {
continue;
}

$relations[] = lcfirst(substr($method, 3, -5));
}
}

return $relations;
}
}
32 changes: 32 additions & 0 deletions tests/MagicActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use DivisionByZeroError;
use ReflectionException;
use Yiisoft\ActiveRecord\ActiveQuery;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Alpha;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Animal;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Cat;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Category;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Customer;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\CustomerClosureField;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\CustomerForArrayable;
Expand Down Expand Up @@ -948,4 +950,34 @@ public function testGetDirtyAttributesWithProperties(): void
$customer->getDirtyAttributes(['id', 'email', 'address', 'unknown']),
);
}

public function testRelationNames(): void
{
$this->checkFixture($this->db(), 'animal');

$animal = new Animal();

$this->assertEmpty($animal->relationNames());

$alpha = new Alpha();

$this->assertSame(['betas'], $alpha->relationNames());

$customer = new Customer();

$this->assertSame([
'profile',
'ordersPlain',
'orders',
'ordersNoOrder',
'expensiveOrders',
'ordersWithItems',
'expensiveOrdersWithNullFK',
'ordersWithNullFK',
'orders2',
'orderItems',
'orderItems2',
'items2',
], $customer->relationNames());
}
}

0 comments on commit 3d75d25

Please sign in to comment.