Skip to content

Commit 554b72b

Browse files
Fix #166: Fix factory duplicate connection (#167)
1 parent aa256db commit 554b72b

3 files changed

Lines changed: 89 additions & 49 deletions

File tree

src/ActiveRecordFactory.php

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,23 @@ public function __construct(Factory $factory)
2525
* Allows you to create an active record instance through the factory.
2626
*
2727
* @param string $arClass active record class.
28-
* @param ConnectionInterface $connection the database connection used for creating active record instances.
28+
* @param ConnectionInterface|null $db the database connection used for creating active record instances.
2929
*
3030
* @throws InvalidConfigException
3131
*
3232
* @return ActiveRecordInterface
3333
*/
34-
public function createAR(string $arClass, ConnectionInterface $connection = null): ActiveRecordInterface
34+
public function createAR(string $arClass, ConnectionInterface $db = null): ActiveRecordInterface
3535
{
36-
return $this->factory->create(
37-
[
38-
'class' => $arClass,
39-
'__construct()' => ['db' => $connection ?? $this->getConnection()],
40-
]
41-
);
36+
$params = [
37+
'class' => $arClass,
38+
];
39+
40+
if ($db) {
41+
$params['__construct()']['db'] = $db;
42+
}
43+
44+
return $this->factory->create($params);
4245
}
4346

4447
/**
@@ -55,17 +58,20 @@ public function createAR(string $arClass, ConnectionInterface $connection = null
5558
public function createQueryTo(
5659
string $arClass,
5760
string $queryClass = null,
58-
ConnectionInterface $connection = null
61+
ConnectionInterface $db = null
5962
): ActiveQueryInterface {
60-
return $this->factory->create(
61-
[
62-
'class' => $queryClass ?? ActiveQuery::class,
63-
'__construct()' => [
64-
$arClass,
65-
$connection ?? $this->getConnection(),
66-
],
67-
]
68-
);
63+
$params = [
64+
'class' => $queryClass ?? ActiveQuery::class,
65+
'__construct()' => [
66+
'modelClass' => $arClass,
67+
],
68+
];
69+
70+
if ($db) {
71+
$params['__construct()']['db'] = $db;
72+
}
73+
74+
return $this->factory->create($params);
6975
}
7076

7177
/**
@@ -82,28 +88,19 @@ public function createQueryTo(
8288
public function createRedisQueryTo(
8389
string $arClass,
8490
string $queryClass = null,
85-
ConnectionInterface $connection = null
91+
ConnectionInterface $db = null
8692
): ActiveQueryInterface {
87-
return $this->factory->create(
88-
[
89-
'class' => $queryClass ?? RedisActiveQuery::class,
90-
'__construct()' => [
91-
$arClass,
92-
$connection ?? $this->getConnection(),
93-
],
94-
]
95-
);
96-
}
93+
$params = [
94+
'class' => $queryClass ?? RedisActiveQuery::class,
95+
'__construct()' => [
96+
'modelClass' => $arClass,
97+
],
98+
];
9799

98-
/**
99-
* Returns the active connection at the factory.
100-
*
101-
* @throws InvalidConfigException
102-
*
103-
* @return ConnectionInterface
104-
*/
105-
public function getConnection(): ConnectionInterface
106-
{
107-
return $this->factory->create(ConnectionInterface::class);
100+
if ($db) {
101+
$params['__construct()']['db'] = $db;
102+
}
103+
104+
return $this->factory->create($params);
108105
}
109106
}

tests/ActiveRecordFactoryTest.php

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerWithConstructor;
1212
use Yiisoft\ActiveRecord\Tests\Stubs\Redis\Customer as RedisCustomer;
1313
use Yiisoft\ActiveRecord\Tests\Stubs\Redis\CustomerQuery as RedisCustomerQuery;
14-
use Yiisoft\Db\Sqlite\Connection as SqliteConnection;
14+
use Yiisoft\Db\Mysql\Connection as MysqlConnection;
15+
use Yiisoft\Db\Redis\Connection as RedisConnection;
1516

1617
/**
1718
* @group main
@@ -27,6 +28,15 @@ public function testCreateAR(): void
2728
$this->assertInstanceOf(Customer::class, $customerAR);
2829
}
2930

31+
public function testCreateARWithConnection(): void
32+
{
33+
$customerAR = $this->arFactory->createAR(Customer::class, $this->redisConnection);
34+
$db = $this->getInaccessibleProperty($customerAR, 'db', true);
35+
36+
$this->assertInstanceOf(RedisConnection::class, $db);
37+
$this->assertInstanceOf(Customer::class, $customerAR);
38+
}
39+
3040
public function testCreateQueryTo(): void
3141
{
3242
/** example create active query */
@@ -40,6 +50,16 @@ public function testCreateQueryTo(): void
4050
$this->assertInstanceOf(CustomerQuery::class, $customerQuery);
4151
}
4252

53+
public function testCreateQueryToWithConnection(): void
54+
{
55+
/** example create active query */
56+
$customerQuery = $this->arFactory->createQueryTo(Customer::class, CustomerQuery::class, $this->mysqlConnection);
57+
$db = $this->getInaccessibleProperty($customerQuery, 'db', true);
58+
59+
$this->assertInstanceOf(MysqlConnection::class, $db);
60+
$this->assertInstanceOf(ActiveQuery::class, $customerQuery);
61+
}
62+
4363
public function testCreateRedisQueryTo(): void
4464
{
4565
/** example create redis active query */
@@ -53,14 +73,6 @@ public function testCreateRedisQueryTo(): void
5373
$this->assertInstanceOf(RedisCustomerQuery::class, $customerQuery);
5474
}
5575

56-
public function testGetConnection(): void
57-
{
58-
/** connection default */
59-
$connection = $this->arFactory->getConnection();
60-
61-
$this->assertInstanceOf(SqliteConnection::class, $connection);
62-
}
63-
6476
public function testGetArInstanceWithConstructor(): void
6577
{
6678
$this->checkFixture($this->sqliteConnection, 'customer', true);

tests/TestCase.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Psr\EventDispatcher\EventDispatcherInterface;
1010
use Psr\EventDispatcher\ListenerProviderInterface;
1111
use Psr\Log\LoggerInterface;
12+
use ReflectionClass;
1213
use ReflectionException;
1314
use ReflectionObject;
1415
use Yiisoft\ActiveRecord\ActiveRecordFactory;
@@ -25,11 +26,11 @@
2526
use Yiisoft\Db\Pgsql\Connection as PgsqlConnection;
2627
use Yiisoft\Db\Redis\Connection as RedisConnection;
2728
use Yiisoft\Db\Sqlite\Connection as SqliteConnection;
29+
use Yiisoft\Definitions\Reference;
2830
use Yiisoft\Di\Container;
2931
use Yiisoft\Di\ContainerConfig;
3032
use Yiisoft\EventDispatcher\Dispatcher\Dispatcher;
3133
use Yiisoft\EventDispatcher\Provider\Provider;
32-
use Yiisoft\Definitions\Reference;
3334
use Yiisoft\Factory\Factory;
3435
use Yiisoft\Log\Logger;
3536
use Yiisoft\Profiler\Profiler;
@@ -122,6 +123,36 @@ protected function checkFixture(ConnectionInterface $db, string $tablename, bool
122123
}
123124
}
124125

126+
/**
127+
* Gets an inaccessible object property.
128+
*
129+
* @param object $object
130+
* @param string $propertyName
131+
* @param bool $revoke whether to make property inaccessible after getting.
132+
*
133+
* @return mixed
134+
*/
135+
protected function getInaccessibleProperty(object $object, string $propertyName, bool $revoke = true)
136+
{
137+
$class = new ReflectionClass($object);
138+
139+
while (!$class->hasProperty($propertyName)) {
140+
$class = $class->getParentClass();
141+
}
142+
143+
$property = $class->getProperty($propertyName);
144+
145+
$property->setAccessible(true);
146+
147+
$result = $property->getValue($object);
148+
149+
if ($revoke) {
150+
$property->setAccessible(false);
151+
}
152+
153+
return $result;
154+
}
155+
125156
/**
126157
* Invokes a inaccessible method.
127158
*

0 commit comments

Comments
 (0)