Skip to content

Commit 65a85f8

Browse files
authored
Prioritize getXXX() and setXXX() over magic properties (#396)
1 parent f44fe59 commit 65a85f8

File tree

4 files changed

+47
-25
lines changed

4 files changed

+47
-25
lines changed

src/Trait/MagicPropertiesTrait.php

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use function in_array;
1919
use function method_exists;
2020
use function property_exists;
21-
use function ucfirst;
2221

2322
/**
2423
* Trait to define magic methods to access values of an ActiveRecord instance.
@@ -62,6 +61,11 @@ trait MagicPropertiesTrait
6261
*/
6362
public function __get(string $name)
6463
{
64+
if (method_exists($this, $getter = "get$name")) {
65+
/** Read getter, e.g., getName() */
66+
return $this->$getter();
67+
}
68+
6569
if ($this->hasProperty($name)) {
6670
return $this->get($name);
6771
}
@@ -70,17 +74,12 @@ public function __get(string $name)
7074
return $this->getRelatedRecords()[$name];
7175
}
7276

73-
if (method_exists($this, $getter = 'get' . ucfirst($name))) {
74-
/** Read getter, e.g., getName() */
75-
return $this->$getter();
76-
}
77-
78-
if (method_exists($this, 'get' . ucfirst($name) . 'Query')) {
77+
if (method_exists($this, "get{$name}Query")) {
7978
/** Read relation query getter, e.g., getUserQuery() */
8079
return $this->retrieveRelation($name);
8180
}
8281

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

@@ -131,19 +130,19 @@ public function __unset(string $name): void
131130
*/
132131
public function __set(string $name, mixed $value): void
133132
{
134-
if ($this->hasProperty($name)) {
135-
parent::set($name, $value);
133+
if (method_exists($this, $setter = "set$name")) {
134+
$this->$setter($value);
136135
return;
137136
}
138137

139-
if (method_exists($this, $setter = 'set' . ucfirst($name))) {
140-
$this->$setter($value);
138+
if ($this->hasProperty($name)) {
139+
parent::set($name, $value);
141140
return;
142141
}
143142

144143
if (
145-
method_exists($this, 'get' . ucfirst($name))
146-
|| method_exists($this, 'get' . ucfirst($name) . 'Query')
144+
method_exists($this, "get$name")
145+
|| method_exists($this, "get{$name}Query")
147146
) {
148147
throw new InvalidCallException('Setting read-only property: ' . static::class . '::' . $name);
149148
}
@@ -184,24 +183,24 @@ public function set(string $propertyName, mixed $value): void
184183
*/
185184
public function isProperty(string $name, bool $checkVars = true): bool
186185
{
187-
return method_exists($this, 'get' . ucfirst($name))
188-
|| method_exists($this, 'set' . ucfirst($name))
189-
|| method_exists($this, 'get' . ucfirst($name) . 'Query')
186+
return method_exists($this, "get$name")
187+
|| method_exists($this, "set$name")
188+
|| method_exists($this, "get{$name}Query")
190189
|| ($checkVars && property_exists($this, $name))
191190
|| $this->hasProperty($name);
192191
}
193192

194193
public function canGetProperty(string $name, bool $checkVars = true): bool
195194
{
196-
return method_exists($this, 'get' . ucfirst($name))
197-
|| method_exists($this, 'get' . ucfirst($name) . 'Query')
195+
return method_exists($this, "get$name")
196+
|| method_exists($this, "get{$name}Query")
198197
|| ($checkVars && property_exists($this, $name))
199198
|| $this->hasProperty($name);
200199
}
201200

202201
public function canSetProperty(string $name, bool $checkVars = true): bool
203202
{
204-
return method_exists($this, 'set' . ucfirst($name))
203+
return method_exists($this, "set$name")
205204
|| ($checkVars && property_exists($this, $name))
206205
|| $this->hasProperty($name);
207206
}

tests/MagicActiveRecordTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Yiisoft\ActiveRecord\Tests;
66

7+
use DateTimeImmutable;
78
use DivisionByZeroError;
89
use ReflectionException;
910
use Yiisoft\ActiveRecord\ActiveQuery;
@@ -882,4 +883,17 @@ public function testRelationNames(): void
882883
'items2',
883884
], $customer->relationNames());
884885
}
886+
887+
public function testGetSetMethodsPriority(): void
888+
{
889+
$this->checkFixture($this->db(), 'order');
890+
891+
$datetime = DateTimeImmutable::createFromFormat('U', '1325502201');
892+
893+
$order = new Order();
894+
$order->created_at = $datetime;
895+
896+
$this->assertSame(1_325_502_201, $order->get('created_at'));
897+
$this->assertEquals($datetime, $order->created_at);
898+
}
885899
}

tests/Stubs/MagicActiveRecord/Customer.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ public function getTableName(): string
3535
return 'customer';
3636
}
3737

38-
public function getName(): string
39-
{
40-
return $this->get('name');
41-
}
42-
4338
public function getProfileQuery(): ActiveQuery
4439
{
4540
return $this->hasOne(Profile::class, ['id' => 'profile_id']);

tests/Stubs/MagicActiveRecord/Order.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord;
66

7+
use DateTimeImmutable;
8+
use DateTimeInterface;
79
use Yiisoft\ActiveRecord\ActiveQuery;
810
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord;
911

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

31+
public function getCreated_at(): DateTimeImmutable
32+
{
33+
return DateTimeImmutable::createFromFormat('U', (string) $this->get('created_at'));
34+
}
35+
36+
public function setCreated_at(DateTimeInterface|int $createdAt): void
37+
{
38+
$this->set('created_at', $createdAt instanceof DateTimeInterface
39+
? $createdAt->getTimestamp()
40+
: $createdAt);
41+
}
42+
2943
public function setVirtualCustomerId(string|int|null $virtualCustomerId = null): void
3044
{
3145
$this->virtualCustomerId = $virtualCustomerId;

0 commit comments

Comments
 (0)