Skip to content
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

Add MagicRelationsTrait::relationNames() method #371

Merged
merged 2 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 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,36 @@ 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.
*
* @throws ReflectionException
* @return string[]
*/
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;
}
}
31 changes: 31 additions & 0 deletions tests/MagicActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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\Customer;
Expand Down Expand Up @@ -948,4 +949,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());
}
}
Loading