标题:【Swoole系列6.4】Hyperf操作数据库

文章目录
    分类:PHP 标签:Swoole

    Hyperf操作数据库

    对于一个 MVC 框架来说,连接操作各种数据库是最基本的功能。而对于 Swoole ,其实我们前面并没有讲很多关于数据库方面的东西,毕竟这不是我们这个系列的主要内容。但之前我们也讲过 连接池 相关的内容,如果小伙伴们不记得了,可以回去看看哦。

    连接操作 MySQL

    在 Hyperf 中,要操作 MySQL 数据库的话,和 Laravel 也非常类似,在 .env 文件中配置相关的连接信息。

    DB_DRIVER=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=test
    DB_USERNAME=root
    DB_PASSWORD=123456
    DB_CHARSET=utf8mb4
    DB_COLLATION=utf8mb4_unicode_ci
    DB_PREFIX=

    它的数据库配置文件在 config/autoload/databases.php 中,同样也可以配置多组配置。

    return [
        'default' => [
            'driver' => env('DB_DRIVER', 'mysql'),
            'host' => env('DB_HOST', 'localhost'),
            'database' => env('DB_DATABASE', 'hyperf'),
            'port' => env('DB_PORT', 3306),
            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => env('DB_CHARSET', 'utf8'),
            'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
            'prefix' => env('DB_PREFIX', ''),
            'pool' => [
                'min_connections' => 1,
                'max_connections' => 10,
                'connect_timeout' => 10.0,
                'wait_timeout' => 3.0,
                'heartbeat' => -1,
                'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
            ],
            'commands' => [
                'gen:model' => [
                    'path' => 'app/Model',
                    'force_casts' => true,
                    'inheritance' => 'Model',
                ],
            ],
        ],
    ];

    可以看到,在这个配置文件中,相比 Laravel 多了一些内容。从名字就可以看出,pool 相关的内容是连接池的配置。而 commands 则是生成 模型 类所需要使用的命令行配置。


    之前我们就一直说过,Hyperf 的数据库操作和模型本身就是基于 Laravel 的组件的,在官方文档上也说了它是基于 illuminate/database 实现的,查询构造器同样也是基于 Laravel Query Builder 。因此,接下来的内容就比较简单了。

    查询构造器

    // CREATE TABLE `db_test` (
    //   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    //   `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
    //   `sex` int(11) NOT NULL DEFAULT '0',
    //   PRIMARY KEY (`id`)
    // ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    Router::get('/db/add', function(){
        $data = [
            [
                'name'=>'Peter',
                'sex' => 1,
            ],
            [
                'name'=>'Tom',
                'sex' => 1,
            ],
            [
                'name'=>'Susan',
                'sex' => 2,
            ],
            [
                'name'=>'Mary',
                'sex' => 2,
            ],
            [
                'name'=>'Jim',
                'sex' => 1,
            ],
        ];
        foreach ($data as $v) {
            $insertId[] = \Hyperf\DbConnection\Db::table('db_test')->insertGetId($v);
        }
        return $insertId;
    });
    
    Router::get('/db/update', function(\Hyperf\HttpServer\Contract\RequestInterface $request){
        $data = [
            'name' => $request->input('name', ''),
            'sex' => $request->input('sex', 0),
            'id' => $request->input("id", 0),
        ];
    
        if($data['id'] < 1 || !$data['name'] || !in_array($data['sex'], [1, 2])){
            return '参数错误';
        }
    
        return \Hyperf\DbConnection\Db::table('db_test')->where("id", "=", $data['id'])->update($data);
    });
    
    Router::get('/db/delete', function(\Hyperf\HttpServer\Contract\RequestInterface $request){
        $id = $request->input('id', 0);
        if($id < 1){
            return '参数错误';
        }
    
        return \Hyperf\DbConnection\Db::table('db_test')->delete($id);
    });
    
    Router::get('/db/list', function (\Hyperf\HttpServer\Contract\RequestInterface $request) {
        $where = [];
        if($request->has("name")){
            $where[] = ['name', 'like', '%' . $request->input('name') . '%'];
        }
        if($request->has("sex")){
            $where[] = ['sex', '=', $request->input('sex')];
        }
    
        return \Hyperf\DbConnection\Db::table('db_test')
            ->select(['*'])
            ->where($where)
            ->orderBy('id', 'desc')
            ->limit(10)
            ->offset(0)
            ->get()
            ->toArray();
    });
    
    Router::get('/db/info', function (\Hyperf\HttpServer\Contract\RequestInterface $request, \Hyperf\HttpServer\Contract\ResponseInterface $response) {
        $id = (int)$request->input('id', 0);
        if($id < 1){
            return '参数错误';
        }
    
        return $response->json(\Hyperf\DbConnection\Db::table('db_test')->find($id));
    });

    一次性把增删改查的操作都给出了哦。使用的数据库表也是之前我们在讲 Laravel 系列时使用过的。非常明显地就可以看出,这一系列的操作,甚至是方法名以及参数都和我们 Laravel 中的查询构造器基本是一致的。不同的就是在 Hyperf 中,Db 后面这个字母是小写的,而在 Laravel 中则是两个大写字母。


    同时,在上面的例子中我们还看到了请求和响应对象相关的操作,如何获取请求参数,如何输出响应数据,并且还能指定为响应 json 格式。这两个注入对象参数在控制器中也是可以使用的,我们就不再单独去讲控制器啦。

    模型

    模型这一块其实也很简单,它也是基于 Laravel 的 Eloquent ORM 。我们先使用一个命令生成模型。

    php bin/hyperf.php gen:model db_test

    这样就会在 app/Model 目录下生成一个 DbTest.php 文件。

    class DbTest extends Model
    {
        protected $table = 'db_test';
        protected $fillable = [];
        protected $casts = ['id' => 'integer', 'sex' => 'integer'];
    }

    剩下的还需要多解释嘛,来一个简单的小例子吧。

    Router::get('/db/model/list', function (\Hyperf\HttpServer\Contract\RequestInterface $request) {
        $where = [];
        if($request->has("name")){
            $where[] = ['name', 'like', '%' . $request->input('name') . '%'];
        }
        if($request->has("sex")){
            $where[] = ['sex', '=', $request->input('sex')];
        }
    
        return \App\Model\DbTest::select()->where($where)
            ->orderBy('id', 'desc')
            ->limit(10)
            ->offset(0)
            ->get()
            ->toArray();
    });

    关于模型其它的操作就不演示了,非常简单方便,使用过 Laravel 的同学上手没难度的。

    连接操作 Redis

    MySQL 数据库的内容说完了,我们再来看看 Redis ,同样也不难,也是配置 .env 就可以直接使用了,不过我们还是看一下它的配置文件,在 config/autoload/redis.php 中。

    return [
        'default' => [
            'host' => env('REDIS_HOST', 'localhost'),
            'auth' => env('REDIS_AUTH', null),
            'port' => (int) env('REDIS_PORT', 6379),
            'db' => (int) env('REDIS_DB', 0),
            'pool' => [
                'min_connections' => 1,
                'max_connections' => 10,
                'connect_timeout' => 10.0,
                'wait_timeout' => 3.0,
                'heartbeat' => -1,
                'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
            ],
        ],
    ];

    和 MySQL 一样,也有连接池的配置。之前我们讲连接池的时候也是讲的 MySQL 和 Redis 的连接池,这里正好也对应上了。


    接下来也是两个简单的小例子。

    Router::get('/db/redis/set', function () {
        $redis = Hyperf\Utils\ApplicationContext::getContainer()->get(\Hyperf\Redis\Redis::class);
        return $redis->set("time", "看看现在时间 " . date("Y-m-d H:i:s"));
    });
    
    Router::get('/db/redis/get', function () {
        $container = Hyperf\Utils\ApplicationContext::getContainer();
    
        $redis = $container->get(\Hyperf\Redis\Redis::class);
    
        return $redis->get("time");
    });

    稍有不同的是,redis 对象的产生方式是需要从 ApplicationContext 这个应用上下文对象的静态方法中获取的。

    总结

    今天的内容非常简单,没有什么学习压力吧。一开始就说过了,这个框架的很多东西都和 Laravel 是一样一样的,而且我之前的项目甚至可以达到大部分的代码平行迁移过来。怎么说呢,百花齐放是好事,各种思想经验可以学习借鉴,但天下大同也不是什么坏事,对于业务应用来说会非常方便。


    有兴趣的小伙伴到这里其实就完全可以尝试尝试用 Hyperf 写一个小程序试试咯!


    测试代码:


    https://github.com/zhangyue0503/swoole/tree/main/6.%E6%A1%86%E6%9E%B6/hyperf-skeleton


    参考文档:


    https://hyperf.wiki/2.2/#/zh-cn/db/quick-start


    https://hyperf.wiki/2.2/#/zh-cn/redis

    视频链接

    微信文章地址:https://mp.weixin.qq.com/s/j0koqklh0_Mh60sSsIyfEg

    微信视频地址:https://mp.weixin.qq.com/s/pzjunB3n4T-I7TMjibCrQg

    B站视频地址:https://www.bilibili.com/video/BV1Hd4y1F7kF

    搜索
    关注