mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-01 11:17:54 +08:00
Merge pull request #1435 from wuwu123/master
Added config `use_default_value` for model-cache.
This commit is contained in:
commit
b769c88a24
@ -14,14 +14,16 @@ composer require hyperf/model-cache
|
||||
|
||||
模型缓存的配置在 `databases` 中。示例如下
|
||||
|
||||
| 配置 | 类型 | 默认值 | 备注 |
|
||||
|:---------------:|:------:|:---------------------------------------------:|:---------------------------------------:|
|
||||
| handler | string | Hyperf\ModelCache\Handler\RedisHandler::class | 无 |
|
||||
| cache_key | string | `mc:%s:m:%s:%s:%s` | `mc:缓存前缀:m:表名:主键 KEY:主键值` |
|
||||
| prefix | string | db connection name | 缓存前缀 |
|
||||
| ttl | int | 3600 | 超时时间 |
|
||||
| empty_model_ttl | int | 60 | 查询不到数据时的超时时间 |
|
||||
| load_script | bool | true | Redis 引擎下 是否使用 evalSha 代替 eval |
|
||||
| 配置 | 类型 | 默认值 | 备注 |
|
||||
|:-----------------:|:------:|:---------------------------------------------:|:---------------------------------------:|
|
||||
| handler | string | Hyperf\ModelCache\Handler\RedisHandler::class | 无 |
|
||||
| cache_key | string | `mc:%s:m:%s:%s:%s` | `mc:缓存前缀:m:表名:主键 KEY:主键值` |
|
||||
| prefix | string | db connection name | 缓存前缀 |
|
||||
| pool | string | default | 缓存池 |
|
||||
| ttl | int | 3600 | 超时时间 |
|
||||
| empty_model_ttl | int | 60 | 查询不到数据时的超时时间 |
|
||||
| load_script | bool | true | Redis 引擎下 是否使用 evalSha 代替 eval |
|
||||
| use_default_value | bool | false | 是否使用数据库默认值 |
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -51,6 +53,7 @@ return [
|
||||
'ttl' => 3600 * 24,
|
||||
'empty_model_ttl' => 3600,
|
||||
'load_script' => true,
|
||||
'use_default_value' => false,
|
||||
]
|
||||
],
|
||||
];
|
||||
@ -136,3 +139,11 @@ $models = User::findManyFromCache($ids);
|
||||
// 删除用户数据 并自动删除缓存
|
||||
User::query(true)->where('gender', '>', 1)->delete();
|
||||
```
|
||||
|
||||
### 使用默认值
|
||||
|
||||
线上使用模型缓存时,如果已经建立了对应缓存,这时又因为逻辑变更,添加了新的字段,并且默认值不是 `0` `空字符` `null` 这类数据时,
|
||||
|
||||
在数据查询时,就会导致从缓存中查出来的数据与数据库中的不一致。
|
||||
|
||||
这种情况,我们可以修改 `use_default_value` 为 `true`,并添加 `Hyperf\DbConnection\Listener\InitTableCollectorListener` 到 `listener.php` 配置中就可以解决。
|
||||
|
@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Hyperf\Database\Query\Processors;
|
||||
|
||||
use Hyperf\Database\Schema\Column;
|
||||
|
||||
class MySqlProcessor extends Processor
|
||||
{
|
||||
/**
|
||||
@ -27,6 +29,26 @@ class MySqlProcessor extends Processor
|
||||
}, $results);
|
||||
}
|
||||
|
||||
public function processColumns($results)
|
||||
{
|
||||
$columns = [];
|
||||
foreach ($results as $i => $value) {
|
||||
$item = (object) $value;
|
||||
$columns[$i] = new Column(
|
||||
$item->table_schema,
|
||||
$item->table_name,
|
||||
$item->column_name,
|
||||
$item->ordinal_position,
|
||||
$item->column_default,
|
||||
$item->is_nullable === 'YES',
|
||||
$item->data_type,
|
||||
$item->column_comment
|
||||
);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the results of a column type listing query.
|
||||
*
|
||||
|
@ -13,6 +13,7 @@ declare(strict_types=1);
|
||||
namespace Hyperf\Database\Query\Processors;
|
||||
|
||||
use Hyperf\Database\Query\Builder;
|
||||
use Hyperf\Database\Schema\Column;
|
||||
|
||||
class Processor
|
||||
{
|
||||
@ -54,4 +55,17 @@ class Processor
|
||||
{
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Column[]
|
||||
*/
|
||||
public function processColumns(array $results)
|
||||
{
|
||||
$columns = [];
|
||||
foreach ($results as $item) {
|
||||
$columns[] = new Column(...array_values($item));
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +147,22 @@ class Builder
|
||||
return $this->connection->getPostProcessor()->processColumnListing($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
$results = $this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileColumns(),
|
||||
[
|
||||
$this->connection->getDatabaseName(),
|
||||
]
|
||||
);
|
||||
return $this->connection->getPostProcessor()->processColumns($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a table on the schema.
|
||||
*
|
||||
|
111
src/database/src/Schema/Column.php
Normal file
111
src/database/src/Schema/Column.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?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\Schema;
|
||||
|
||||
class Column
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $schema;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $position;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $default;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isNullable;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $comment;
|
||||
|
||||
public function __construct(string $schema, string $table, string $name, int $position, $default, bool $isNullable, string $type, string $comment)
|
||||
{
|
||||
$this->schema = $schema;
|
||||
$this->table = $table;
|
||||
$this->name = $name;
|
||||
$this->position = $position;
|
||||
$this->default = $default;
|
||||
$this->isNullable = $isNullable;
|
||||
$this->type = $type;
|
||||
$this->comment = $comment;
|
||||
}
|
||||
|
||||
public function getSchema(): string
|
||||
{
|
||||
return $this->schema;
|
||||
}
|
||||
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getPosition(): int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
public function isNullable(): bool
|
||||
{
|
||||
return $this->isNullable;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getComment(): string
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
}
|
@ -53,6 +53,14 @@ class MySqlGrammar extends Grammar
|
||||
return 'select `column_name`, `data_type`, `column_comment` from information_schema.columns where `table_schema` = ? and `table_name` = ? order by ORDINAL_POSITION';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the query to determine the list of columns.
|
||||
*/
|
||||
public function compileColumns(): string
|
||||
{
|
||||
return 'select `table_schema`, `table_name`, `column_name`, `ordinal_position`, `column_default`, `is_nullable`, `data_type`, `column_comment` from information_schema.columns where `table_schema` = ? order by ORDINAL_POSITION';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a create table command.
|
||||
*
|
||||
|
@ -50,6 +50,21 @@ class MySqlBuilder extends Builder
|
||||
return $this->connection->getPostProcessor()->processColumnListing($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
$results = $this->connection->select(
|
||||
$this->grammar->compileColumns(),
|
||||
[$this->connection->getDatabaseName()]
|
||||
);
|
||||
|
||||
return $this->connection->getPostProcessor()->processColumns($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column type listing for a given table.
|
||||
*
|
||||
|
@ -12,7 +12,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace HyperfTest\Database;
|
||||
|
||||
use Hyperf\Database\Connection;
|
||||
use Hyperf\Database\ConnectionResolverInterface;
|
||||
use Hyperf\Database\Query\Processors\MySqlProcessor;
|
||||
use Hyperf\Database\Schema\Column;
|
||||
use Hyperf\Database\Schema\Grammars\MySqlGrammar;
|
||||
use Hyperf\Database\Schema\MySqlBuilder;
|
||||
use HyperfTest\Database\Stubs\ContainerStub;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@ -35,4 +41,20 @@ class MySqlProcessorTest extends TestCase
|
||||
|
||||
$this->assertEquals($expected, $processor->processColumnListing($listing));
|
||||
}
|
||||
|
||||
public function testProcessColumns()
|
||||
{
|
||||
$container = ContainerStub::getContainer();
|
||||
|
||||
/** @var Connection $connection */
|
||||
$connection = $container->get(ConnectionResolverInterface::class)->connection();
|
||||
$connection->setSchemaGrammar(new MySqlGrammar());
|
||||
$builder = new MySqlBuilder($connection);
|
||||
|
||||
$columns = $builder->getColumns();
|
||||
|
||||
$this->assertTrue(is_array($columns));
|
||||
$this->assertTrue(count($columns) > 0);
|
||||
$this->assertInstanceOf(Column::class, $columns[0]);
|
||||
}
|
||||
}
|
||||
|
53
src/database/tests/Stubs/ContainerStub.php
Normal file
53
src/database/tests/Stubs/ContainerStub.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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 HyperfTest\Database\Stubs;
|
||||
|
||||
use Hyperf\Database\ConnectionResolver;
|
||||
use Hyperf\Database\ConnectionResolverInterface;
|
||||
use Hyperf\Database\Connectors\ConnectionFactory;
|
||||
use Hyperf\Database\Connectors\MySqlConnector;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Mockery;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
class ContainerStub
|
||||
{
|
||||
public static function getContainer()
|
||||
{
|
||||
$container = Mockery::mock(ContainerInterface::class);
|
||||
ApplicationContext::setContainer($container);
|
||||
|
||||
$container->shouldReceive('has')->andReturn(true);
|
||||
$container->shouldReceive('get')->with('db.connector.mysql')->andReturn(new MySqlConnector());
|
||||
$connector = new ConnectionFactory($container);
|
||||
|
||||
$dbConfig = [
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => 'hyperf',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
];
|
||||
|
||||
$connection = $connector->make($dbConfig);
|
||||
|
||||
$resolver = new ConnectionResolver(['default' => $connection]);
|
||||
|
||||
$container->shouldReceive('get')->with(ConnectionResolverInterface::class)->andReturn($resolver);
|
||||
|
||||
return $container;
|
||||
}
|
||||
}
|
63
src/db-connection/src/Collector/TableCollector.php
Normal file
63
src/db-connection/src/Collector/TableCollector.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?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\DbConnection\Collector;
|
||||
|
||||
use Hyperf\Database\Schema\Column;
|
||||
|
||||
class TableCollector
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* @param Column[] $columns
|
||||
*/
|
||||
public function set(string $pool, string $table, array $columns)
|
||||
{
|
||||
$this->data[$pool][$table] = $columns;
|
||||
}
|
||||
|
||||
public function add(string $pool, Column $column)
|
||||
{
|
||||
$this->data[$pool][$column->getTable()][$column->getName()] = $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Column[]
|
||||
*/
|
||||
public function get(string $pool, ?string $table = null): array
|
||||
{
|
||||
if ($table === null) {
|
||||
return $this->data[$pool] ?? [];
|
||||
}
|
||||
|
||||
return $this->data[$pool][$table] ?? [];
|
||||
}
|
||||
|
||||
public function has(string $pool, ?string $table = null): bool
|
||||
{
|
||||
return ! empty($this->get($pool, $table));
|
||||
}
|
||||
|
||||
public function getDefaultValue(string $connectName, string $table): array
|
||||
{
|
||||
$tablseData = $this->get($connectName, $table);
|
||||
$list = [];
|
||||
foreach ($tablseData as $column) {
|
||||
$list[$column->getName()] = $column->getDefault();
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
<?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\DbConnection\Listener;
|
||||
|
||||
use Hyperf\Command\Event\BeforeHandle;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Contract\ContainerInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Database\ConnectionResolverInterface;
|
||||
use Hyperf\DbConnection\Collector\TableCollector;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\Framework\Event\AfterWorkerStart;
|
||||
use Hyperf\Process\Event\BeforeProcessHandle;
|
||||
|
||||
class InitTableCollectorListener implements ListenerInterface
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @var ConfigInterface
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var StdoutLoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var TableCollector
|
||||
*/
|
||||
protected $collector;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $container->get(ConfigInterface::class);
|
||||
$this->logger = $container->get(StdoutLoggerInterface::class);
|
||||
$this->collector = $container->get(TableCollector::class);
|
||||
}
|
||||
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
BeforeHandle::class,
|
||||
AfterWorkerStart::class,
|
||||
BeforeProcessHandle::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function process(object $event)
|
||||
{
|
||||
try {
|
||||
$databases = $this->config->get('databases', []);
|
||||
$pools = array_keys($databases);
|
||||
foreach ($pools as $name) {
|
||||
$this->initTableCollector($name);
|
||||
}
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->logger->error((string) $throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public function initTableCollector($pool)
|
||||
{
|
||||
if ($this->collector->has($pool)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection = $this->container->get(ConnectionResolverInterface::class)->connection($pool);
|
||||
|
||||
$columns = $connection->getSchemaBuilder()->getColumns();
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$this->collector->add($pool, $column);
|
||||
}
|
||||
}
|
||||
}
|
27
src/db-connection/tests/TableCollectorTest.php
Normal file
27
src/db-connection/tests/TableCollectorTest.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?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 HyperfTest\DbConnection;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
class TableCollectorTest extends TestCase
|
||||
{
|
||||
public function testExample()
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ return [
|
||||
'ttl' => 3600 * 24,
|
||||
'empty_model_ttl' => 3600,
|
||||
'load_script' => true,
|
||||
'use_default_value' => false,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -45,6 +45,12 @@ class Config
|
||||
*/
|
||||
protected $emptyModelTtl = 60;
|
||||
|
||||
/**
|
||||
* Whether to use default value when resolved from cache.
|
||||
* @var bool
|
||||
*/
|
||||
protected $useDefaultValue = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
@ -72,6 +78,9 @@ class Config
|
||||
if (isset($values['empty_model_ttl'])) {
|
||||
$this->emptyModelTtl = $values['empty_model_ttl'];
|
||||
}
|
||||
if (isset($values['use_default_value'])) {
|
||||
$this->useDefaultValue = (bool) $values['use_default_value'];
|
||||
}
|
||||
}
|
||||
|
||||
public function getCacheKey(): string
|
||||
@ -85,6 +94,17 @@ class Config
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isUseDefaultValue(): bool
|
||||
{
|
||||
return $this->useDefaultValue;
|
||||
}
|
||||
|
||||
public function setUseDefaultValue(bool $useDefaultValue): Config
|
||||
{
|
||||
$this->useDefaultValue = $useDefaultValue;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrefix(): string
|
||||
{
|
||||
return $this->prefix;
|
||||
|
@ -15,6 +15,7 @@ namespace Hyperf\ModelCache;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Database\Model\Collection;
|
||||
use Hyperf\DbConnection\Collector\TableCollector;
|
||||
use Hyperf\DbConnection\Model\Model;
|
||||
use Hyperf\ModelCache\Handler\HandlerInterface;
|
||||
use Hyperf\ModelCache\Handler\RedisHandler;
|
||||
@ -37,10 +38,17 @@ class Manager
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var TableCollector
|
||||
*/
|
||||
protected $collector;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->logger = $container->get(StdoutLoggerInterface::class);
|
||||
$this->collector = $container->get(TableCollector::class);
|
||||
|
||||
$config = $container->get(ConfigInterface::class);
|
||||
if (! $config->has('databases')) {
|
||||
throw new \InvalidArgumentException('config databases is not exist!');
|
||||
@ -73,7 +81,9 @@ class Manager
|
||||
$key = $this->getCacheKey($id, $instance, $handler->getConfig());
|
||||
$data = $handler->get($key);
|
||||
if ($data) {
|
||||
return $instance->newFromBuilder($data);
|
||||
return $instance->newFromBuilder(
|
||||
$this->getAttributes($handler->getConfig(), $instance, $data)
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch it from database, because it not exist in cache handler.
|
||||
@ -143,7 +153,7 @@ class Manager
|
||||
}
|
||||
$map = [];
|
||||
foreach ($items as $item) {
|
||||
$map[$item[$primaryKey]] = $item;
|
||||
$map[$item[$primaryKey]] = $this->getAttributes($handler->getConfig(), $instance, $item);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
@ -236,4 +246,16 @@ class Manager
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getAttributes(Config $config, Model $model, array $data)
|
||||
{
|
||||
if (! $config->isUseDefaultValue()) {
|
||||
return $data;
|
||||
}
|
||||
$defaultData = $this->collector->getDefaultValue(
|
||||
$model->getConnectionName(),
|
||||
$model->getTable()
|
||||
);
|
||||
return array_replace($defaultData, $data);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ namespace HyperfTest\ModelCache;
|
||||
use Hyperf\Config\Config;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\DbConnection\Collector\TableCollector;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use HyperfTest\ModelCache\Stub\ManagerStub;
|
||||
use HyperfTest\ModelCache\Stub\ModelStub;
|
||||
@ -43,6 +44,7 @@ class ManagerTest extends TestCase
|
||||
$container->shouldReceive('get')->once()->with(ConfigInterface::class)->andReturn(new Config($this->getConfig()));
|
||||
$container->shouldReceive('make')->with(ContainerInterface::class)->andReturn($container);
|
||||
$container->shouldReceive('get')->with(EventDispatcherInterface::class)->andReturn(null);
|
||||
$container->shouldReceive('get')->with(TableCollector::class)->andReturn(new TableCollector());
|
||||
|
||||
ApplicationContext::setContainer($container);
|
||||
|
||||
|
@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace HyperfTest\ModelCache;
|
||||
|
||||
use Hyperf\DbConnection\Listener\InitTableCollectorListener;
|
||||
use Hyperf\Redis\RedisProxy;
|
||||
use HyperfTest\ModelCache\Stub\ContainerStub;
|
||||
use HyperfTest\ModelCache\Stub\UserExtModel;
|
||||
@ -228,4 +229,25 @@ class ModelCacheTest extends TestCase
|
||||
$this->assertSame($model->getAttributes(), $model2->getAttributes());
|
||||
$this->assertEquals(array_keys($model->getAttributes()), array_keys($model3->getAttributes()));
|
||||
}
|
||||
|
||||
public function testWhenAddedNewColumn()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
$listener = new InitTableCollectorListener($container);
|
||||
$listener->process((object) []);
|
||||
|
||||
$model = UserHiddenModel::query()->find(1);
|
||||
$model->deleteCache();
|
||||
|
||||
$model = UserModel::findFromCache(1);
|
||||
$model = UserModel::findFromCache(1);
|
||||
$this->assertArrayHasKey('gender', $model->toArray());
|
||||
|
||||
/** @var \Redis $redis */
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
$redis->hDel('{mc:default:m:user}:id:1', 'gender');
|
||||
$model = UserModel::findFromCache(1);
|
||||
|
||||
$this->assertArrayHasKey('gender', $model->toArray());
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Database\ConnectionResolverInterface;
|
||||
use Hyperf\Database\Connectors\ConnectionFactory;
|
||||
use Hyperf\Database\Connectors\MySqlConnector;
|
||||
use Hyperf\DbConnection\Collector\TableCollector;
|
||||
use Hyperf\DbConnection\ConnectionResolver;
|
||||
use Hyperf\DbConnection\Frequency;
|
||||
use Hyperf\DbConnection\Pool\DbPool;
|
||||
@ -43,6 +44,7 @@ class ContainerStub
|
||||
public static function mockContainer()
|
||||
{
|
||||
$container = Mockery::mock(Container::class);
|
||||
$container->shouldReceive('get')->with(TableCollector::class)->andReturn(new TableCollector());
|
||||
|
||||
$factory = new PoolFactory($container);
|
||||
$container->shouldReceive('get')->with(PoolFactory::class)->andReturn($factory);
|
||||
@ -81,6 +83,7 @@ class ContainerStub
|
||||
'ttl' => 3600 * 24,
|
||||
'empty_model_ttl' => 3600,
|
||||
'load_script' => true,
|
||||
'use_default_value' => true,
|
||||
],
|
||||
'pool' => [
|
||||
'min_connections' => 1,
|
||||
|
Loading…
Reference in New Issue
Block a user