Skip to content

Commit

Permalink
Prioritize getXXX() and setXXX() over magic properties
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Jan 24, 2025
1 parent f44fe59 commit 9ef4c61
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 20 deletions.
39 changes: 19 additions & 20 deletions src/Trait/MagicPropertiesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use function in_array;
use function method_exists;
use function property_exists;
use function ucfirst;

/**
* Trait to define magic methods to access values of an ActiveRecord instance.
Expand Down Expand Up @@ -62,6 +61,11 @@ trait MagicPropertiesTrait
*/
public function __get(string $name)
{
if (method_exists($this, $getter = "get$name")) {
/** Read getter, e.g., getName() */
return $this->$getter();
}

if ($this->hasProperty($name)) {
return $this->get($name);
}
Expand All @@ -70,17 +74,12 @@ public function __get(string $name)
return $this->getRelatedRecords()[$name];
}

if (method_exists($this, $getter = 'get' . ucfirst($name))) {
/** Read getter, e.g., getName() */
return $this->$getter();
}

if (method_exists($this, 'get' . ucfirst($name) . 'Query')) {
if (method_exists($this, "get{$name}Query")) {
/** Read relation query getter, e.g., getUserQuery() */
return $this->retrieveRelation($name);
}

if (method_exists($this, 'set' . ucfirst($name))) {
if (method_exists($this, "set$name")) {
throw new InvalidCallException('Getting write-only property: ' . static::class . '::' . $name);
}

Expand Down Expand Up @@ -131,19 +130,19 @@ public function __unset(string $name): void
*/
public function __set(string $name, mixed $value): void
{
if ($this->hasProperty($name)) {
parent::set($name, $value);
if (method_exists($this, $setter = "set$name")) {
$this->$setter($value);
return;
}

if (method_exists($this, $setter = 'set' . ucfirst($name))) {
$this->$setter($value);
if ($this->hasProperty($name)) {
parent::set($name, $value);
return;
}

if (
method_exists($this, 'get' . ucfirst($name))
|| method_exists($this, 'get' . ucfirst($name) . 'Query')
method_exists($this, "get$name")
|| method_exists($this, "get{$name}Query")
) {
throw new InvalidCallException('Setting read-only property: ' . static::class . '::' . $name);
}
Expand Down Expand Up @@ -184,24 +183,24 @@ public function set(string $propertyName, mixed $value): void
*/
public function isProperty(string $name, bool $checkVars = true): bool
{
return method_exists($this, 'get' . ucfirst($name))
|| method_exists($this, 'set' . ucfirst($name))
|| method_exists($this, 'get' . ucfirst($name) . 'Query')
return method_exists($this, "get$name")
|| method_exists($this, "set$name")
|| method_exists($this, "get{$name}Query")
|| ($checkVars && property_exists($this, $name))
|| $this->hasProperty($name);
}

public function canGetProperty(string $name, bool $checkVars = true): bool
{
return method_exists($this, 'get' . ucfirst($name))
|| method_exists($this, 'get' . ucfirst($name) . 'Query')
return method_exists($this, "get$name")
|| method_exists($this, "get{$name}Query")
|| ($checkVars && property_exists($this, $name))
|| $this->hasProperty($name);
}

public function canSetProperty(string $name, bool $checkVars = true): bool
{
return method_exists($this, 'set' . ucfirst($name))
return method_exists($this, "set$name")
|| ($checkVars && property_exists($this, $name))
|| $this->hasProperty($name);
}
Expand Down
14 changes: 14 additions & 0 deletions tests/MagicActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\ActiveRecord\Tests;

use DateTimeImmutable;
use DivisionByZeroError;
use ReflectionException;
use Yiisoft\ActiveRecord\ActiveQuery;
Expand Down Expand Up @@ -882,4 +883,17 @@ public function testRelationNames(): void
'items2',
], $customer->relationNames());
}

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

$datetime = DateTimeImmutable::createFromFormat('U', '1325502201');

$order = new Order();
$order->created_at = $datetime;

$this->assertSame(1_325_502_201, $order->get('created_at'));
$this->assertEquals($datetime, $order->getCreated_at());
}
}
14 changes: 14 additions & 0 deletions tests/Stubs/MagicActiveRecord/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord;

use DateTimeImmutable;
use DateTimeInterface;
use Yiisoft\ActiveRecord\ActiveQuery;
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord;

Expand All @@ -26,6 +28,18 @@ public function getTableName(): string
return self::TABLE_NAME;
}

public function getCreated_at(): DateTimeImmutable
{
return DateTimeImmutable::createFromFormat('U', (string) $this->get('created_at'));
}

public function setCreated_at(DateTimeInterface|int $createdAt): void
{
$this->set('created_at', $createdAt instanceof DateTimeInterface
? $createdAt->getTimestamp()
: $createdAt);
}

public function setVirtualCustomerId(string|int|null $virtualCustomerId = null): void
{
$this->virtualCustomerId = $virtualCustomerId;
Expand Down

0 comments on commit 9ef4c61

Please sign in to comment.