mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-02 19:58:22 +08:00
Added interface Synchronized to optimized mergeAttributesFromClassCasts.
This commit is contained in:
parent
f42c90b3a6
commit
021ae675c4
20
src/contract/src/Synchronized.php
Normal file
20
src/contract/src/Synchronized.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Contract;
|
||||
|
||||
interface Synchronized
|
||||
{
|
||||
/**
|
||||
* Whether the data has been synchronized.
|
||||
*/
|
||||
public function isSynchronized(): bool;
|
||||
}
|
62
src/database/src/Model/CastsValue.php
Normal file
62
src/database/src/Model/CastsValue.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Database\Model;
|
||||
|
||||
use Hyperf\Contract\Synchronized;
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
|
||||
abstract class CastsValue implements Synchronized, Arrayable
|
||||
{
|
||||
/**
|
||||
* @var Model
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isSynchronized;
|
||||
|
||||
public function __construct(Model $model, $itmes = [])
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->items = $itmes;
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->items[$name];
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->items[$name] = $value;
|
||||
$this->isSynchronized = false;
|
||||
$this->model->syncAttributes();
|
||||
$this->isSynchronized = true;
|
||||
}
|
||||
|
||||
public function isSynchronized(): bool
|
||||
{
|
||||
return $this->isSynchronized;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ use DateTimeInterface;
|
||||
use Hyperf\Contract\Castable;
|
||||
use Hyperf\Contract\CastsAttributes;
|
||||
use Hyperf\Contract\CastsInboundAttributes;
|
||||
use Hyperf\Contract\Synchronized;
|
||||
use Hyperf\Database\Model\JsonEncodingException;
|
||||
use Hyperf\Database\Model\Relations\Relation;
|
||||
use Hyperf\Utils\Arr;
|
||||
@ -1404,6 +1405,10 @@ trait HasAttributes
|
||||
protected function mergeAttributesFromClassCasts()
|
||||
{
|
||||
foreach ($this->classCastCache as $key => $value) {
|
||||
if ($value instanceof Synchronized && $value->isSynchronized()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$caster = $this->resolveCasterClass($key);
|
||||
|
||||
$this->attributes = array_merge(
|
||||
|
@ -14,7 +14,9 @@ namespace HyperfTest\Database;
|
||||
use Hyperf\Contract\Castable;
|
||||
use Hyperf\Contract\CastsAttributes;
|
||||
use Hyperf\Contract\CastsInboundAttributes;
|
||||
use Hyperf\Database\Model\CastsValue;
|
||||
use Hyperf\Database\Model\Model;
|
||||
use Hyperf\Utils\Arr;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@ -205,6 +207,24 @@ class DatabaseModelCustomCastingTest extends TestCase
|
||||
CastUsing::$castsAttributes = new UppercaseCaster();
|
||||
$this->assertSame($method->invokeArgs($model, ['cast_using']), $method->invokeArgs($model, ['cast_using']));
|
||||
}
|
||||
|
||||
public function testIsSynchronized()
|
||||
{
|
||||
$model = new TestModelWithCustomCast();
|
||||
$model->user = $user = new UserInfo($model, ['name' => 'Hyperf', 'gender' => 1]);
|
||||
$model->syncOriginal();
|
||||
|
||||
$attributes = $model->getAttributes();
|
||||
$this->assertSame(['name' => 'Hyperf', 'gender' => 1], $attributes);
|
||||
|
||||
$user->name = 'Nano';
|
||||
$attributes = $model->getAttributes();
|
||||
$this->assertSame(['name' => 'Nano', 'gender' => 1], $attributes);
|
||||
|
||||
$this->assertSame(['name' => 'Nano'], $model->getDirty());
|
||||
$this->assertSame(2, UserInfoCaster::$setCount);
|
||||
$this->assertSame(0, UserInfoCaster::$getCount);
|
||||
}
|
||||
}
|
||||
|
||||
class TestModelWithCustomCast extends Model
|
||||
@ -223,6 +243,7 @@ class TestModelWithCustomCast extends Model
|
||||
*/
|
||||
protected $casts = [
|
||||
'address' => AddressCaster::class,
|
||||
'user' => UserInfoCaster::class,
|
||||
'password' => HashCaster::class,
|
||||
'other_password' => HashCaster::class . ':md5',
|
||||
'uppercase' => UppercaseCaster::class,
|
||||
@ -286,6 +307,28 @@ class AddressCaster implements CastsAttributes
|
||||
}
|
||||
}
|
||||
|
||||
class UserInfoCaster implements CastsAttributes
|
||||
{
|
||||
public static $setCount = 0;
|
||||
|
||||
public static $getCount = 0;
|
||||
|
||||
public function get($model, string $key, $value, array $attributes)
|
||||
{
|
||||
++self::$getCount;
|
||||
return new UserInfo($model, Arr::only($attributes, ['name', 'gender']));
|
||||
}
|
||||
|
||||
public function set($model, string $key, $value, array $attributes)
|
||||
{
|
||||
++self::$setCount;
|
||||
return [
|
||||
'name' => $value->name,
|
||||
'gender' => $value->gender,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class JsonCaster implements CastsAttributes
|
||||
{
|
||||
public function get($model, $key, $value, $attributes)
|
||||
@ -369,3 +412,11 @@ class Address
|
||||
$this->lineTwo = $lineTwo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @property string $name
|
||||
* @property int $gender
|
||||
*/
|
||||
class UserInfo extends CastsValue
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user