Skip to content

Commit d824993

Browse files
authored
Fix "IndexBy" functional (#470)
1 parent a4e35f3 commit d824993

13 files changed

Lines changed: 61 additions & 59 deletions

composer.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"roave/infection-static-analysis-plugin": "^1.35",
4141
"spatie/phpunit-watcher": "^1.24",
4242
"vimeo/psalm": "^5.26.1 || ^6.8.8",
43-
"vlucas/phpdotenv": "^5.6.2",
4443
"yiisoft/aliases": "^2.0",
4544
"yiisoft/arrays": "^3.2",
4645
"yiisoft/cache": "^3.1",
@@ -74,8 +73,7 @@
7473
"autoload-dev": {
7574
"psr-4": {
7675
"Yiisoft\\ActiveRecord\\Tests\\": "tests"
77-
},
78-
"files": ["tests/bootstrap.php"]
76+
}
7977
},
8078
"extra": {
8179
"branch-alias": {

src/AbstractActiveRecord.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ public function link(string $relationName, ActiveRecordInterface $linkModel, arr
497497
$indexBy = $relation->getIndexBy();
498498
if ($indexBy !== null) {
499499
if ($indexBy instanceof Closure) {
500-
$index = $indexBy($linkModel->propertyValues());
500+
$index = $indexBy($linkModel);
501501
} else {
502502
$index = $linkModel->get($indexBy);
503503
}

src/ActiveQuery.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@
100100
* query join condition.
101101
*
102102
* @psalm-type ModelClass = ActiveRecordInterface|class-string<ActiveRecordInterface>
103-
* @psalm-import-type IndexKey from ArArrayHelper
103+
* @psalm-import-type IndexBy from QueryInterface
104104
*
105-
* @psalm-property IndexKey|null $indexBy
105+
* @psalm-property IndexBy|null $indexBy
106106
* @psalm-suppress ClassMustBeFinal
107107
*/
108108
class ActiveQuery extends Query implements ActiveQueryInterface

src/ActiveQueryInterface.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
* represents a relation between two active record classes and will return related records only.
2222
*
2323
* A class implementing this interface should also use {@see ActiveQueryTrait} and {@see ActiveRelationTrait}.
24-
*
25-
* @psalm-import-type IndexKey from ArArrayHelper
2624
*/
2725
interface ActiveQueryInterface extends QueryInterface
2826
{

src/ArArrayHelper.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Closure;
88
use Traversable;
9+
use Yiisoft\Db\Query\QueryInterface;
910

1011
use function array_combine;
1112
use function array_key_exists;
@@ -21,7 +22,7 @@
2122
* Array manipulation methods for ActiveRecord.
2223
*
2324
* @psalm-type Row = ActiveRecordInterface|array
24-
* @psalm-type IndexKey = string|Closure(Row):array-key
25+
* @psalm-import-type IndexBy from QueryInterface
2526
*/
2627
final class ArArrayHelper
2728
{
@@ -139,7 +140,7 @@ public static function getValueByPath(ActiveRecordInterface|array $array, string
139140
*
140141
* @psalm-template TRow of Row
141142
* @psalm-param array<TRow> $rows
142-
* @psalm-param IndexKey|null $indexBy
143+
* @psalm-param IndexBy|null $indexBy
143144
* @psalm-return array<TRow>
144145
*/
145146
public static function index(array $rows, Closure|string|null $indexBy = null): array

tests/.env

Lines changed: 0 additions & 23 deletions
This file was deleted.

tests/ActiveRecordTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,4 +1610,25 @@ public function testLinkWithNonPrimaryKeyFields(): void
16101610
);
16111611
$article->link('comments', $comment);
16121612
}
1613+
1614+
public function testLinkWithIndexByAsClosure(): void
1615+
{
1616+
$this->reloadFixtureAfterTest();
1617+
1618+
$customer = Customer::query()->findByPk(1);
1619+
$this->assertNotNull($customer);
1620+
1621+
$existingOrders = $customer->getOrderItemsIndexedByClosure();
1622+
1623+
$newOrder = new Order();
1624+
$newOrder->setCreatedAt(time());
1625+
$newOrder->setTotal(150.0);
1626+
$customer->link('orderItemsIndexedByClosure', $newOrder);
1627+
1628+
$expectedIndex = 'order_' . $newOrder->getId();
1629+
$updatedOrders = $customer->getOrderItemsIndexedByClosure();
1630+
$this->assertArrayHasKey($expectedIndex, $updatedOrders);
1631+
$this->assertSame($newOrder, $updatedOrders[$expectedIndex]);
1632+
$this->assertCount(\count($existingOrders) + 1, $updatedOrders);
1633+
}
16131634
}

tests/Stubs/ActiveRecord/Customer.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function relationQuery(string $name): ActiveQueryInterface
5656
'orders2' => $this->getOrders2Query(),
5757
'orderItems' => $this->getOrderItemsQuery(),
5858
'orderItems2' => $this->getOrderItems2Query(),
59+
'orderItemsIndexedByClosure' => $this->getOrderItemsIndexedByClosureQuery(),
5960
'items2' => $this->getItems2Query(),
6061
'ordersUsingInstance' => $this->hasMany(new Order(), ['customer_id' => 'id']),
6162
default => parent::relationQuery($name),
@@ -256,6 +257,18 @@ public function getOrderItems2Query(): ActiveQuery
256257
->via('ordersNoOrder');
257258
}
258259

260+
public function getOrderItemsIndexedByClosure(): array
261+
{
262+
return $this->relation('orderItemsIndexedByClosure');
263+
}
264+
265+
public function getOrderItemsIndexedByClosureQuery(): ActiveQuery
266+
{
267+
return $this
268+
->hasMany(Order::class, ['customer_id' => 'id'])
269+
->indexBy(fn (Order $order) => 'order_' . $order->getId());
270+
}
271+
259272
public function getItems2(): array
260273
{
261274
return $this->relation('items2');

tests/Support/MssqlHelper.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ final class MssqlHelper extends ConnectionHelper
1414
{
1515
public function createConnection(): ConnectionInterface
1616
{
17-
$database = getenv('YII_MSSQL_DATABASE');
18-
$host = getenv('YII_MSSQL_HOST');
19-
$port = getenv('YII_MSSQL_PORT');
20-
$user = getenv('YII_MSSQL_USER');
21-
$password = getenv('YII_MSSQL_PASSWORD');
17+
$database = getenv('YII_MSSQL_DATABASE') ?: 'ar-test';
18+
$host = getenv('YII_MSSQL_HOST') ?: '127.0.0.1';
19+
$port = getenv('YII_MSSQL_PORT') ?: '1433';
20+
$user = getenv('YII_MSSQL_USER') ?: 'SA';
21+
$password = getenv('YII_MSSQL_PASSWORD') ?: 'YourStrong!Passw0rd';
2222

2323
$pdoDriver = new Driver(
2424
"sqlsrv:Server=$host,$port;Database=$database;TrustServerCertificate=true",

tests/Support/MysqlHelper.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ final class MysqlHelper extends ConnectionHelper
1414
{
1515
public function createConnection(): ConnectionInterface
1616
{
17-
$database = getenv('YII_MYSQL_DATABASE');
18-
$host = getenv('YII_MYSQL_HOST');
19-
$port = getenv('YII_MYSQL_PORT');
20-
$user = getenv('YII_MYSQL_USER');
21-
$password = getenv('YII_MYSQL_PASSWORD');
17+
$database = getenv('YII_MYSQL_DATABASE') ?: 'ar-test';
18+
$host = getenv('YII_MYSQL_HOST') ?: '127.0.0.1';
19+
$port = getenv('YII_MYSQL_PORT') ?: '3306';
20+
$user = getenv('YII_MYSQL_USER') ?: 'yii';
21+
$password = getenv('YII_MYSQL_PASSWORD') ?: 'q1w2e3r4';
2222

2323
$pdoDriver = new Driver("mysql:host=$host;dbname=$database;port=$port", $user, $password);
2424
$pdoDriver->charset('UTF8MB4');

0 commit comments

Comments
 (0)