Skip to content

Commit

Permalink
增加setInc和setDec方法用于数值字段的自增和自减操作 并支持延迟写入
Browse files Browse the repository at this point in the history
  • Loading branch information
liu21st committed Feb 24, 2023
1 parent abea788 commit 70f775a
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,9 @@ public function db($scope = []): Query

$query->model($this)
->json($this->json, $this->jsonAssoc)
->setFieldType(array_merge($this->schema, $this->jsonType));
->setFieldType(array_merge($this->schema, $this->jsonType))
->setKey($this->getKey())
->lazyFields($this->lazyFields);

// 软删除
if (property_exists($this, 'withTrashed') && !$this->withTrashed) {
Expand Down
48 changes: 47 additions & 1 deletion src/db/BaseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace think\db;

use Closure;
use Psr\SimpleCache\CacheInterface;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException as Exception;
Expand Down Expand Up @@ -203,6 +204,41 @@ public function getName(): string
return $this->name ?: $this->model->getName();
}

/**
* 设置主键值.
*
* @param mixed $key 主键值
*
* @return $this
*/
public function setKey($key)
{
$this->options['key'] = $key;

return $this;
}

/**
* 获取主键值.
* @param array $data 数据
*
* @return mixed
*/
public function getKey(array $data = [])
{
if (!empty($data)) {
$pk = $this->getPk();
if (is_string($pk) && isset($data[$pk])) {
$id = $data[$pk];
} else {
$id = null;
}
return $id;
}

return $this->getOptions('key');
}

/**
* 获取数据库的配置参数.
*
Expand Down Expand Up @@ -835,6 +871,16 @@ public function more(int $limit, int|string $lastId = null, string $key = null,
];
}

/**
* 获取当前的缓存对象
*
* @return CacheInterface|null
*/
public function getCache()
{
return $this->getConnection()->getCache();
}

/**
* 查询缓存 数据为空不缓存.
*
Expand All @@ -847,7 +893,7 @@ public function more(int $limit, int|string $lastId = null, string $key = null,
*/
public function cache($key = true, $expire = null, $tag = null, bool $always = false)
{
if (false === $key || !$this->getConnection()->getCache()) {
if (false === $key || !$this->getCache()) {
return $this;
}

Expand Down
135 changes: 135 additions & 0 deletions src/db/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace think\db;

use PDOStatement;
use think\db\exception\DbException as Exception;

/**
* PDO数据查询类.
Expand Down Expand Up @@ -387,6 +388,140 @@ public function dec(string $field, float $step = 1)
return $this;
}

/**
* 设置延迟写入字段 用于实时获取缓存数据
*
* @param array $fields 延迟写入字段
*
* @return $this
*/
public function lazyFields(array $fields)
{
$this->options['lazy_fields'] = $fields;

return $this;
}

/**
* 字段值增长(支持延迟写入)
*
* @param string $field 字段名
* @param int $step 步进值
* @param int $lazyTime 延迟时间(秒)
*
* @return int|false
*/
public function setInc(string $field, int $step = 1, $lazyTime = 0)
{
if (empty($this->options['where']) && $this->model) {
$this->where($this->model->getWhere());
}

if (empty($this->options['where'])) {
// 如果没有任何更新条件则不执行
throw new Exception('miss update condition');
}

if ($lazyTime > 0) {
$guid = $this->getLazyFieldCacheKey($field);
$step = $this->lazyWrite('inc', $guid, $step, $lazyTime);
if (false === $step) {
return true;
}
}

return $this->inc($field, $step)->update();
}

/**
* 字段值减少(支持延迟写入)
*
* @param string $field 字段名
* @param int $step 步进值
* @param int $lazyTime 延迟时间(秒)
*
* @return int|false
*/
public function setDec(string $field, int $step = 1, int $lazyTime = 0)
{
if (empty($this->options['where']) && $this->model) {
$this->where($this->model->getWhere());
}

if (empty($this->options['where'])) {
// 如果没有任何更新条件则不执行
throw new Exception('miss update condition');
}

if ($lazyTime > 0) {
$guid = $this->getLazyFieldCacheKey($field);
$step = $this->lazyWrite('dec', $guid, $step, $lazyTime);
if (false === $step) {
return true;
}
return $this->inc($field, $step)->update();
}

return $this->dec($field, $step)->update();
}

/**
* 延时更新检查 返回false表示需要延时
* 否则返回实际写入的数值
* @access protected
* @param string $type 自增或者自减
* @param string $guid 写入标识
* @param int $step 写入步进值
* @param int $lazyTime 延时时间(s)
* @return false|integer
*/
protected function lazyWrite(string $type, string $guid, int $step, int $lazyTime)
{
$cache = $this->getCache();
if (!$cache->has($guid . '_time')) {
// 计时开始
$cache->set($guid . '_time', time());
$cache->$type($guid, $step);
} elseif (time() > $cache->get($guid . '_time') + $lazyTime) {
// 删除缓存
$value = $cache->$type($guid, $step);
$cache->delete($guid);
$cache->delete($guid . '_time');
return 0 === $value ? false : $value;
} else {
// 更新缓存
$cache->$type($guid, $step);
}

return false;
}

/**
* 获取延迟写入字段值.
*
* @param string $field 字段名称
* @param mixed $id 主键值
*
* @return int
*/
protected function getLazyFieldValue(string $field, $id = null): int
{
return (int) $this->getCache()->get($this->getLazyFieldCacheKey($field, $id));
}

/**
* 获取延迟写入字段的缓存Key
*
* @param string $field 字段名
* @param mixed $id 主键值
*
* @return string
*/
protected function getLazyFieldCacheKey(string $field, $id = null): string
{
return 'lazy_' . $this->getTable() . '_' . $field . '_' . ($id ?: $this->getKey());
}

/**
* 获取当前的查询标识.
*
Expand Down
8 changes: 8 additions & 0 deletions src/db/concern/ModelRelationQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,14 @@ protected function resultToModel(array &$result): void
$this->jsonModelResult($result);
}

// 实时读取延迟数据
if (!empty($this->options['lazy_fields'])) {
$id = $this->getKey($result);
foreach ($this->options['lazy_fields'] as $field) {
$result[$field] += $this->getLazyFieldValue($field, $id);
}
}

$result = $this->model->newInstance(
$result,
!empty($this->options['is_resultSet']) ? null : $this->getModelUpdateCondition($this->options),
Expand Down
8 changes: 8 additions & 0 deletions src/db/concern/ResultOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ protected function result(array &$result): void
$this->jsonResult($result);
}

// 实时读取延迟数据
if (!empty($this->options['lazy_fields'])) {
$id = $this->getKey($result);
foreach ($this->options['lazy_fields'] as $field) {
$result[$field] += $this->getLazyFieldValue($field, $id);
}
}

// 查询数据处理
foreach ($this->options['filter'] as $filter) {
$result = call_user_func_array($filter, [$result, $this->options]);
Expand Down
5 changes: 5 additions & 0 deletions src/db/concern/WhereQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public function where($field, $op = null, $condition = null)
return $this;
}

$pk = $this->getPk();
if ((is_null($condition) || '=' == $op) && is_string($pk) && $pk == $field ) {
$this->options['key'] = is_null($condition) ? $op : $condition;
}

$param = func_get_args();
array_shift($param);

Expand Down
7 changes: 7 additions & 0 deletions src/model/concern/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ trait Attribute
*/
private $withAttr = [];

/**
* 数据表延迟写入的字段
*
* @var array
*/
protected $lazyFields = [];

/**
* 获取模型对象的主键.
*
Expand Down

0 comments on commit 70f775a

Please sign in to comment.