Skip to content

Feat/存储过程 #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@

https://github.com/Tencent/APIJSON


### 开发进度

1. ✅最基本CRUD 包括批量写入 批量更新 批量删除
1. ✅最基本CRUD 包括批量写入 批量更新 批量删除 存储过程调用
2. ✅支持@column @having @order @group @combine
3. ✅支持运算符 {}, !{}, &{}, |{}, }{@, $, %, ~
4. ✅支持多表查询、一对一查询、一对多查询、数组内多对多查询
5. ✅支持数组内count/page
6. ✅支持debug标签可返回语句执行

待完成:<b>复杂查询</b>, 存储过程调用,远程函数,权限,标签

待完成:<b>复杂查询</b>,Join查询,远程函数,权限,标签

### 如何使用

Expand All @@ -52,7 +50,7 @@ APIJSON通用文档(增删改查说明):https://github.com/Tencent/APIJSON

拉取该项目, 配置mysql数据库, 配置文件路径:`config\autoload\databases.php`

然后在项目目录执行:(需机器有:docker)
然后在项目目录执行:(需宿主机有:docker)

```shell
# 打包镜像
Expand All @@ -61,7 +59,7 @@ docker build -t hyperf-apijson:v1 .
docker run -dit --name hyperf-apijson -p 9501:9501 hyperf-apijson:v1
```

如果需要进行开发调试,使用Hyperf的Docker环境
如果需要进行开发调试,使用Hyperf的Docker镜像 - <b>本项目可作为你的给Hyperf基础项目,可在该项目基础上进行业务开发,几乎没有互相冲突</b>

```shell
docker run -dit --name hyperf-apijson -v {项目目录}:/opt/www -p 9501:9501 hyperf/hyperf:8.0-alpine-v3.12-swoole
Expand All @@ -70,6 +68,8 @@ docker run -dit --name hyperf-apijson -v {项目目录}:/opt/www -p 9501:9501 hy
进入到docker环境执行 (如果composer下载不动 可以修改到阿里镜像源 Mac下建议本地开发):
```shell
cd /opt/www

composer update

php bin/hyperf.php start
```
17 changes: 17 additions & 0 deletions app/ApiJson/Entity/ConditionEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ConditionEntity
protected array $group = [];
protected array $order = [];
protected array $having = [];
protected string $procedure = "";

/**
* @param array $condition 条件
Expand Down Expand Up @@ -155,6 +156,22 @@ public function getOrder(): array
return $this->order;
}

/**
* @param string $procedure
*/
public function setProcedure(string $procedure): void
{
$this->procedure = $procedure;
}

/**
* @return string
*/
public function getProcedure(): string
{
return $this->procedure;
}

protected function log(array $condition)
{
$this->changeLog[] = [
Expand Down
23 changes: 23 additions & 0 deletions app/ApiJson/Handle/FunctionProcedureHandle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\ApiJson\Handle;

class FunctionProcedureHandle extends AbstractHandle
{
protected string $keyWord = '@procedure()';

public function buildModel()
{
if (!in_array($this->keyWord, array_keys($this->condition->getCondition()))) {
return;
}

foreach (array_filter($this->condition->getCondition(), function($key){
return $key == $this->keyWord;
}, ARRAY_FILTER_USE_KEY) as $key => $value)
{
$this->condition->setProcedure($value);
$this->unsetKey[] = $this->keyWord;
}
}
}
15 changes: 11 additions & 4 deletions app/ApiJson/Method/GetMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,32 @@ protected function validateCondition(): bool

protected function process()
{
$handle = new Handle($this->tableEntity->getConditionEntity(), $this->tableEntity);
$handle->build();

$queryMany = $this->isQueryMany();
if (!$queryMany) {
$this->tableEntity->getConditionEntity()->setLimit(1);
}

$handle = new Handle($this->tableEntity->getConditionEntity(), $this->tableEntity);
$handle->build();

//该事件鼓励是做语句缓存或者事件触发 不赞成修改语句做法 修改语句应在更上层的QueryHandle事件
$event = new QueryExecuteBefore($this->query->toSql(), $this->method);
ApplicationContext::getContainer()->get(EventDispatcherInterface::class)->dispatch($event);

if(is_null($event->result)) {
$result = $this->query->all();

$queryEvent = new QueryResult($result);
$queryEvent = new QueryResult($result, $this->query->toSql());
ApplicationContext::getContainer()->get(EventDispatcherInterface::class)->dispatch($queryEvent);

$result = $queryEvent->result;

if (!empty($this->tableEntity->getConditionEntity()->getProcedure())) {
foreach ($result as $i => $item) {
$result[$i]['procedure'] = $this->query->callProcedure($item);
}
}

} else {
$result = $event->result;
}
Expand Down
44 changes: 44 additions & 0 deletions app/ApiJson/Model/MysqlQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,50 @@ public function getBindings(): array
return $this->db->getBindings();
}

public function callProcedure(array $dataItem, bool $query = true): array
{
if (empty($this->conditionEntity->getProcedure())) {
return [];
}
$count = -1;
$list = []; //默认值

$procedure = $this->conditionEntity->getProcedure();
$rule = '/(?<functionName>.+)\((?<args>.+?)\)/';
preg_match($rule, $procedure, $match);
if (empty($match['functionName'])) {
return [];
}
$args = array_map('trim', explode(',', $match['args']));

$callArgs = [];
foreach ($args as $arg) {
if (in_array($arg, array_keys($dataItem))) {
$callArgs[] = $dataItem[$arg];
} else if ($arg == '@limit') {
$callArgs[] = $this->conditionEntity->getLimit();
} else if ($arg == '@offset') {
$callArgs[] = $this->conditionEntity->getOffset();
} else {
$callArgs[] = $arg;
}
}

$sql = sprintf("CALL %s(%s)", $match['functionName'], join(',', $callArgs));

if ($query) {
$list = Db::select($sql);
} else {
$count = Db::affectingStatement($sql);
}

return [
'count' => $count,
'update' => !$query,
'list' => $list,
];
}

protected function buildQuery(bool $query = true)
{
if ($this->build) return;
Expand Down
2 changes: 2 additions & 0 deletions app/ApiJson/Parse/Handle.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use App\ApiJson\Handle\FunctionLimitHandle;
use App\ApiJson\Handle\FunctionOffsetHandle;
use App\ApiJson\Handle\FunctionOrderHandle;
use App\ApiJson\Handle\FunctionProcedureHandle;
use App\ApiJson\Handle\WhereBetweenHandle;
use App\ApiJson\Handle\WhereExistsHandle;
use App\ApiJson\Handle\WhereHandle;
Expand Down Expand Up @@ -54,6 +55,7 @@ class Handle
* @var AbstractHandle[]
*/
protected array $methodRules = [
FunctionProcedureHandle::class,
FunctionColumnHandle::class,
FunctionHavingHandle::class,
FunctionOffsetHandle::class,
Expand Down
3 changes: 2 additions & 1 deletion app/ApiJson/Parse/Parse.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class Parse
{
protected array $tagColumn = [
'tag' => null,
'debug' => false
'debug' => false,
'other' => []
];

protected array $globalKey = [
Expand Down
2 changes: 1 addition & 1 deletion app/Event/ApiJson/QueryResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
class QueryResult
{
public function __construct(public array $result)
public function __construct(public array $result, public string $sql)
{
}
}
11 changes: 10 additions & 1 deletion app/Event/StatementComplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class StatementComplete
*/
public $connection;

/**
* The query result
*
* @var array|false
*/
public $result;

/**
* The PDO statement.
*
Expand All @@ -30,11 +37,13 @@ class StatementComplete
* Create a new event instance.
*
* @param \Hyperf\Database\Connection $connection
* @param array|false $result
* @param \PDOStatement $statement
*/
public function __construct($connection, $statement)
public function __construct($connection, $result, $statement)
{
$this->statement = $statement;
$this->result = $result;
$this->connection = $connection;
}
}
30 changes: 0 additions & 30 deletions app/Listener/DbPreparedListener.php

This file was deleted.

15 changes: 5 additions & 10 deletions app/Listener/QueryResultTryToJsonListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

namespace App\Listener;

use App\Constants\ConfigCode;
use App\Event\ApiJson\QueryResult;
use App\Event\StatementComplete;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Utils\Context;

/**
* @Listener
Expand All @@ -17,18 +15,15 @@ class QueryResultTryToJsonListener implements ListenerInterface
public function listen(): array
{
return [
QueryResult::class,
StatementComplete::class,
];
}

public function process(object $event)
{
if (!$event instanceof QueryResult) return;

$statement = Context::get(ConfigCode::DB_QUERY_STATEMENT);
if (empty($statement)) {
return;
}
if (!$event instanceof StatementComplete) return;
if (empty($event->result)) return;
$statement = $event->statement;

$columnCount = count(array_keys(current($event->result)));
$columnMeta = [];
Expand Down
19 changes: 10 additions & 9 deletions class_map/Hyperf/Database/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,9 @@ public function select(string $query, array $bindings = [], bool $useReadPdo = t

$statement->execute();

$response = $statement->fetchAll();
$result = $statement->fetchAll();

$this->complete($statement);

return $response;
return $this->complete($result, $statement);
});
}

Expand Down Expand Up @@ -318,9 +316,9 @@ public function cursor(string $query, array $bindings = [], bool $useReadPdo = t
// Next, we'll execute the query against the database and return the statement
// so we can return the cursor. The cursor will use a PHP generator to give
// back one row at a time without using a bunch of memory to render them.
$statement->execute();
$result = $statement->execute();

$this->complete($statement);
$this->complete($result, $statement);

return $statement;
});
Expand Down Expand Up @@ -990,12 +988,15 @@ protected function prepared(PDOStatement $statement)
return $statement;
}

protected function complete(PDOStatement $statement)
protected function complete($result, PDOStatement $statement)
{
$this->event(new StatementComplete(
$event = new StatementComplete(
$this,
$result,
$statement
));
);
$this->event($event);
return $event->result;
}

/**
Expand Down
Loading