The current repo belongs to Closed status, and some functions are restricted. For details, please refer to the description of repo status
13 Star 73 Fork 9

sethink / swoole-orm
Closed

 / 详情

关于Query类的改进

Backlog
Opened this issue  
2021-01-19 17:53

因为我们改动比较激进,我这边自行发布了衍生版本。

我在上次的提交中忘记了在协程go(function(){});的里面的错误不能直接抛出异常否则会导致整个协程退出,程序就长时间无响应,所以这块我在query方法里面进行了改进,麻烦作者看一下可否使用,可以的话麻烦作者自行更新了。

<?php
/**
 * @User: sethink
 */

namespace bangtech\swooleOrm\db;

use bangtech\swooleOrm\MysqlPool;
use chan;
use ErrorException;
use Exception;
use RuntimeException;
use Swoole\Coroutine\Mysql;

class Query
{
    //server
    protected $MysqlPool;
    //sql生成器
    protected $builder;

    //db参数
    protected $options = [
        'table' => '',
        'alias' => [],
        'where' => [],
        'whereNum' => 0,
        'field' => '*',
        'order' => [],
        'distinct' => false,
        'join' => '',
        'union' => '',
        'group' => '',
        'having' => '',
        'limit' => '',
        'lock' => false,
        'fetch_sql' => false,
        'data' => [],
        'prefix' => '',
        'setDefer' => true
    ];


    public function __construct()
    {
        // 创建Builder对象
        $this->builder = new Builder();
    }

    /**
     * @初始化
     *
     * @param $MysqlPool
     * @return $this
     */
    public function init(MysqlPool $MysqlPool): Query
    {
        $this->MysqlPool = $MysqlPool;
        $this->options['prefix'] = $MysqlPool->config['prefix'];
        $this->options['setDefer'] = $MysqlPool->config['setDefer'];
        return $this;
    }


    /**
     * @表名
     *
     * @param $tableName
     * @return $this
     */
    public function name($tableName = ''): Query
    {
        $this->options['table'] = $this->options['prefix'] . $tableName;
        return $this;
    }

    /**
     * @param string $tableName
     * @return $this
     */
    public function table($tableName = ''): Query
    {
        $this->options['table'] =  $tableName;
        return $this;
    }

    //暂未实现
//    public function alias()
//    {
//
//    }


    /**
     * @查询字段
     *
     * @param string $field
     * @return $this
     */
    public function field($field = ''): Query
    {
        if (empty($field)) {
            return $this;
        }
        $field_array = explode(',', $field);
        //去重
        $this->options['field'] = array_unique($field_array);
        return $this;
    }


    /**
     * @order by
     *
     * @param array $order
     * @return $this
     */
    public function order($order = []): Query
    {
        $this->options['order'] = $order;
        return $this;
    }


    /**
     * @group by
     *
     * @param string $group
     * @return $this
     */
    public function group($group = ''): Query
    {
        $this->options['group'] = $group;
        return $this;
    }


    /**
     * @having
     *
     * @param string $having
     * @return $this
     */
    public function having($having = ''): Query
    {
        $this->options['having'] = $having;
        return $this;
    }


    //暂未实现
//    public function join()
//    {
//
//    }


    /**
     * @distinct
     * @param $distinct
     * @return $this
     */
    public function distinct($distinct): Query
    {
        $this->options['distinct'] = $distinct;
        return $this;
    }


    /**
     * @获取sql语句
     *
     * @return $this
     */
    public function fetchSql(): Query
    {
        $this->options['fetch_sql'] = true;
        return $this;
    }


    /**
     * @where语句
     * @param $field
     * @param null $op
     * @param null $condition
     * @return $this
     */
    public function where($field, $op = null, $condition = null): Query
    {
        if (is_array($field)) {
            $whereArray = $field;
        } elseif (is_object($field)){
            $field($this);
            return $this;
        } else {
            if ($op != null && $condition == null){
                $condition = $op;
                $op = '=';
            }
            $whereArray = [
                $field => [$op != null ?: '=', $condition]
            ];
        }

        $this->options['where'][$this->options['whereNum']] = $whereArray;
        $this->options['whereNum']++;
        return $this;
    }


    /**
     * @lock加锁
     *
     * @param bool $lock
     * @return $this
     */
    public function lock($lock = false): Query
    {
        $this->options['lock'] = $lock;
        return $this;
    }


    /**
     * @设置是否返回结果
     *
     * @param bool $bool
     * @return $this
     */
    public function setDefer(bool $bool = true): Query
    {
        $this->options['setDefer'] = $bool;
        return $this;
    }


    /**
     * @查询一条数据
     *
     * @return array|mixed
     * @throws Exception
     */
    public function find()
    {
        $this->options['limit'] = 1;

        $result = $this->builder->select($this->options);

        if (!empty($this->options['fetch_sql'])) {
            return $this->getRealSql($result);
        }
        return $this->query($result);
    }


    /**
     * @查询
     *
     * @return bool|mixed
     * @throws Exception
     */
    public function select()
    {
        // 生成查询SQL
        $result = $this->builder->select($this->options);

        if (!empty($this->options['fetch_sql'])) {
            return $this->getRealSql($result);
        }

        return $this->query($result);
    }


    /**
     * @ 添加
     *
     * @param array $data
     * @return mixed|string
     * @throws Exception
     */
    public function insert($data = [])
    {
        $this->options['data'] = $data;

        $result = $this->builder->insert($this->options);

        if (!empty($this->options['fetch_sql'])) {
            return $this->getRealSql($result);
        }
        return $this->query($result);
    }

    /**
     * @param array $data
     * @return mixed|null
     * @throws Exception
     */
    public function insertAll($data = [])
    {
        $this->options['data'] = $data;

        $result = $this->builder->insertAll($this->options);

        if (!empty($this->options['fetch_sql'])) {
            return $this->getRealSql($result);
        }
        return $this->query($result);
    }


    /**
     * @param array $data
     * @return mixed|null
     * @throws Exception
     */
    public function update($data = [])
    {
        $this->options['data'] = $data;

        $result = $this->builder->update($this->options);

        if (!empty($this->options['fetch_sql'])) {
            return $this->getRealSql($result);
        }
        return $this->query($result);
    }


    /**
     * @return mixed|null
     * @throws Exception
     */
    public function delete()
    {
        // 生成查询SQL
        $result = $this->builder->delete($this->options);

        if (!empty($this->options['fetch_sql'])) {
            return $this->getRealSql($result);
        }

        return $this->query($result);
    }


    /**
     * @获取连接
     *
     * @return mixed
     */
    public function instance()
    {
        return $this->MysqlPool->get();
    }


    /**
     * $入池
     *
     * @param $mysql
     */
    public function put($mysql)
    {
        if ($mysql instanceof Mysql) {
            $this->MysqlPool->put($mysql);
        } else {
            throw new RuntimeException('传入的$mysql不属于该连接池');
        }
    }


    /**
     * @执行sql
     * @param $result
     * @return mixed
     * @throws Exception
     */
    public function query($result)
    {
        $chan = new chan(1);

        go(function () use ($chan, $result) {
            try {
                $dumpError = false;

                $mysql = $this->MysqlPool->get();

                if (is_string($result)) {
                    $rs = $mysql->query($result);

                    if ($rs === false) {
                        $dumpError = true;
                    }

                    if ($this->options['setDefer']) {
                        $chan->push([0,$rs]);
                    }
                } else {
                    $stmt = $mysql->prepare($result['sql']);

                    if ($stmt === false) {
                        $dumpError = true;
                    }

                    if ($stmt) {
                        $rs = $stmt->execute($result['sethinkBind']);

                        if ($rs === false) {
                            $dumpError = true;
                        }

                        if ($this->options['setDefer']) {
                            if ($this->options['limit'] == 1) {
                                if (count($rs) > 0) {
                                    $chan->push([0,$rs[0]]);
                                } else {
                                    $chan->push([0,null]);
                                }
                            } else {
                                if (strstr($result['sql'], 'INSERT INTO')) {
                                    $chan->push([0,$mysql->insert_id]);
                                } else {
                                    $chan->push([0,$rs]);
                                }
                            }
                        }
                    }
                }
                $this->put($mysql);

                if ($dumpError) {
                    $chan->push([1,[$mysql->error,$mysql->errno,new Exception($mysql->error,$mysql->errno)]]);
                }
            } catch (Exception $e) {
                if ($this->options['setDefer']) {
                    $chan->push([0,null]);
                }else{
                    $chan->push([1,[$e->getMessage(),$e->getCode(),$e->getPrevious()]]);
                }
            }

        });

        if ($this->options['setDefer']) {
            $res = $chan->pop();
            if ($res[0] === 0){
                return $res[1];
            }else{
                throw new Exception($res[1][0],$res[1][1],$res[1][2]);
            }

        }
        return null;
    }

    /**
     * @sql语句
     *
     * @param $result
     * @return mixed
     */
    protected function getRealSql($result)
    {
        if (count($result['sethinkBind']) > 0) {
            foreach ($result['sethinkBind'] as $v) {
                $result['sql'] = substr_replace($result['sql'], "'{$v}'", strpos($result['sql'], '?'), 1);
            }
        }

        return $result['sql'];
    }


    public function __destruct()
    {
        unset($this->MysqlPool);
        unset($this->builder);
        unset($this->options);
    }


}

Comments (1)

hepeichun created任务
hepeichun set related repository to sethink/swoole-orm
Expand operation logs

Sign in to comment

Status
Assignees
Milestones
Pull Requests
Successfully merging a pull request will close this issue.
Branches
Planed to start   -   Planed to end
-
Top level
Priority
参与者(1)
PHP
1
https://gitee.com/pipixia-pi/swoole-orm.git
git@gitee.com:pipixia-pi/swoole-orm.git
pipixia-pi
swoole-orm
swoole-orm

Search