Skip to content

Commit

Permalink
implement the interface ArrayableInterface for BaseActiveRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
niqingyang committed Dec 9, 2023
1 parent 41c6691 commit 12c3300
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 11 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"require": {
"php": "^8.0",
"ext-json": "*",
"yiisoft/arrays": "^3.0",
"yiisoft/db": "^1.1",
"yiisoft/factory": "^1.0"
},
Expand Down
12 changes: 11 additions & 1 deletion src/ActiveRecordInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,16 @@ public function populateRecord(array|object $row): void;

/**
* Serializes the active record into its array implementation with attribute name as a key, and it values as value.
*
* @param array $fields the fields that the output array should contain. Fields not specified
* in {@see fields()} will be ignored. If this parameter is empty, all fields as specified
* in {@see fields()} will be returned.
* @param array $expand the additional fields that the output array should contain.
* Fields not specified in {@see extraFields()} will be ignored. If this parameter is empty, no extra fields
* will be returned.
* @param bool $recursive Whether to recursively return array representation of embedded objects.
*
* @return array The array representation of the object.
*/
public function toArray(): array;
public function toArray(array $fields = [], array $expand = [], bool $recursive = true): array;
}
33 changes: 23 additions & 10 deletions src/BaseActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use IteratorAggregate;
use ReflectionException;
use Throwable;
use Yiisoft\Arrays\ArrayableInterface;
use Yiisoft\Arrays\ArrayableTrait;
use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -40,8 +43,9 @@
* @template-implements ArrayAccess<int, mixed>
* @template-implements IteratorAggregate<int>
*/
abstract class BaseActiveRecord implements ActiveRecordInterface, IteratorAggregate, ArrayAccess
abstract class BaseActiveRecord implements ActiveRecordInterface, IteratorAggregate, ArrayAccess, ArrayableInterface
{
use ArrayableTrait;
use BaseActiveRecordTrait;

private array $attributes = [];
Expand Down Expand Up @@ -1266,19 +1270,28 @@ public function getTableName(): string
return $this->tableName;
}

public function toArray(): array
/**
* @inheritDoc
*/
public function toArray(array $fields = [], array $expand = [], bool $recursive = true): array
{
$data = [];

foreach ($this->fields() as $key => $value) {
if ($value instanceof Closure) {
/** @var mixed */
$data[$key] = $value($this);
} else {
/** @var mixed */
$data[$value] = $this[$value];
foreach ($this->resolveFields($fields, $expand) as $field => $definition) {
$attribute = $definition instanceof Closure ? $definition($this, $field) : $definition;

if ($recursive) {
$nestedFields = $this->extractFieldsFor($fields, $field);
$nestedExpand = $this->extractFieldsFor($expand, $field);
if ($attribute instanceof ArrayableInterface) {
$attribute = $attribute->toArray($nestedFields, $nestedExpand);
} elseif (is_array($attribute) && ($nestedExpand || $nestedFields)) {
$attribute = $this->filterAndExpand($attribute, $nestedFields, $nestedExpand);
}
}
$data[$field] = $attribute;
}
return $data;

return $recursive ? ArrayHelper::toArray($data) : $data;
}
}
22 changes: 22 additions & 0 deletions tests/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerClosureField;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerForArrayable;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerWithAlias;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Dog;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Item;
Expand All @@ -20,6 +21,7 @@
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\OrderItemWithNullFK;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Type;
use Yiisoft\ActiveRecord\Tests\Support\Assert;
use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidCallException;
Expand Down Expand Up @@ -763,4 +765,24 @@ public function testToArrayWithClosure(): void
$customer->toArray(),
);
}

public function testToArrayForArrayable(): void
{
$this->checkFixture($this->db, 'customer', true);

$customerQuery = new ActiveQuery(CustomerForArrayable::class, $this->db);
$customer = $customerQuery->findOne(1);

$this->assertSame(
[
'id' => 1,
'email' => 'user1@example.com',
'name' => 'user1',
'address' => 'address1',
'status' => 'active',
'profile_id' => 1,
],
ArrayHelper::toArray($customer),
);
}
}
22 changes: 22 additions & 0 deletions tests/Driver/Oracle/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use Yiisoft\ActiveRecord\ActiveQuery;
use Yiisoft\ActiveRecord\Tests\Driver\Oracle\Stubs\Customer;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerClosureField;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerForArrayable;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Type;
use Yiisoft\ActiveRecord\Tests\Support\OracleHelper;
use Yiisoft\Arrays\ArrayHelper;

final class ActiveRecordTest extends \Yiisoft\ActiveRecord\Tests\ActiveRecordTest
{
Expand Down Expand Up @@ -166,4 +168,24 @@ public function testToArrayWithClosure(): void
$customer->toArray(),
);
}

public function testToArrayForArrayable(): void
{
$this->checkFixture($this->db, 'customer', true);

$customerQuery = new ActiveQuery(CustomerForArrayable::class, $this->db);
$customer = $customerQuery->findOne(1);

$this->assertSame(
[
'id' => 1,
'email' => 'user1@example.com',
'name' => 'user1',
'address' => 'address1',
'status' => 'active',
'profile_id' => 1,
],
ArrayHelper::toArray($customer),
);
}
}
22 changes: 22 additions & 0 deletions tests/Driver/Pgsql/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\BoolAR;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerClosureField;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerForArrayable;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\DefaultPk;
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\UserAR;
use Yiisoft\ActiveRecord\Tests\Support\PgsqlHelper;
use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Db\Expression\ArrayExpression;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Expression\JsonExpression;
Expand Down Expand Up @@ -381,4 +383,24 @@ public function testToArrayWithClosure(): void
$customer->toArray(),
);
}

public function testToArrayForArrayable(): void
{
$this->checkFixture($this->db, 'customer', true);

$customerQuery = new ActiveQuery(CustomerForArrayable::class, $this->db);
$customer = $customerQuery->findOne(1);

$this->assertSame(
[
'id' => 1,
'email' => 'user1@example.com',
'name' => 'user1',
'address' => 'address1',
'status' => 'active',
'profile_id' => 1,
],
ArrayHelper::toArray($customer),
);
}
}
31 changes: 31 additions & 0 deletions tests/Stubs/ActiveRecord/CustomerForArrayable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord;

use Yiisoft\ActiveRecord\ActiveRecord;

/**
* Class CustomerClosureField.
*
* @property int $id
* @property string $name
* @property string $email
* @property string $address
* @property int $status
*/
class CustomerForArrayable extends ActiveRecord
{
public function getTableName(): string
{
return 'customer';
}

public function toArray(array $fields = [], array $expand = [], bool $recursive = true): array
{
$data = parent::toArray($fields, $expand, $recursive);

$data['status'] = $this->status == 1 ? 'active' : 'inactive';

return $data;
}
}

0 comments on commit 12c3300

Please sign in to comment.