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