一 准备阶段
1.1 watcher .
说明:hyperf 是cli 模式运行,在dev 环境下,每改一行代码,需要重启服务,会很折腾,安装watcher 改善这个问题。
步骤
-
安装
composer require hyperf/watcher --dev #发布配置 php bin/hyperf.php vendor:publish hyperf/watcher # 去 .watcher.php 中查看配置。 -
修改启动命令
# 容器下 ENTRYPOINT ["php", "/data/project/hyperf/bin/hyperf.php", "server:watch"] #或者 直接cli php bin/hyperf.php server:watch -
效果。 当修改代码后,程序会扫描到代码改动
[DEBUG] Hyperf\Watcher\Driver\ScanFileDriver Watching: Total:47, Change:1, Add:0, Delete:0.
Class reload success.
Stop server...
Stop server success.
Start server ...
- 不爽的地方。
- 如果机器性能太拉,就很慢。
- 改 .env 文件,和删文件会失效,改vendor 后要重启。
1.2 环境变量
-
mysql && redis 配置 。
.env 文件下。
#redis REDIS_HOST=172.88.0.82 REDIS_AUTH=(null) REDIS_PORT=6379 REDIS_DB=1 #mysql DB_DRIVER=mysql DB_HOST=172.88.0.83 DB_PORT=3306 DB_DATABASE=api DB_USERNAME=root DB_PASSWORD=123456 DB_CHARSET=utf8mb4 DB_PREFIX=edu_ -
.env 设置与读取。
#.env 下添加一行。 ENV_TEST="here is env test info" echo env("ENV_TEST");
1.3 配置config
- config 配置,与使用。
#设置
config.php
"test_config" => "test_config_value"
-
用法
2.1 用法1 。(注入config)
#[Inject]
protected ConfigInterface $config;
public function index()
{
$tag = $this->config->get("test_config");
2.2 用法2 。Annotation 使用注解。
use Hyperf\Config\Annotation\Value;
class IndexController extends AbstractController
{
#[Value('test_config')]
private $test_config;
public function index()
{
echo $this->test_config
}
- 常用套路,先 env ,然后config
//先读 .env 文件中的LOGIN_TTL 如果没有则为 7200
'login_ttl' => env('LOGIN_TTL', 7200),
1.4 日志
-
安装
composer require hyperf/logger -
配置 。
config/autoload/logger.php
<?php
declare(strict_types=1);
use Monolog\Handler;
use Monolog\Formatter;
use Monolog\Logger;
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyptyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
return [
'default' => [
'handlers' =>
[
[
'class' => \Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => Logger::INFO,
],
'formatter' => [
'class' => Formatter\LineFormatter::class,
'constructor' => [
'format' => "||%datetime%||%channel%||%level_name%||%message%||%context%||%extra%\n",
'dateFormat' => null,
'allowInlineLineBreaks' => true,
],
],
],
[
'class' => Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf-debug.log',
'level' => Logger::DEBUG,
],
'formatter' => [
'class' => Formatter\JsonFormatter::class,
'constructor' => [
'format' => "||%datetime%||%channel%||%level_name%||%message%||%context%||%extra%\n",
'batchMode' => Formatter\JsonFormatter::BATCH_MODE_JSON,
'appendNewline' => true,
],
],
],
]
],
];
用法。
//注入
protected LoggerInterface $logger;
public function __construct(LoggerFactory $loggerFactory)
{
// 第一个参数对应日志的 name, 第二个参数对应 config/autoload/logger.php 内的 key
$this->logger = $loggerFactory->get('log', 'default');
}
//使用。
$this->logger->info("info content");
$this->logger->debug("debug config");
//带数组使用。
$this->logger->info("create a user", ["name" => "a", "age"=>18]);
日志内容 。
||2023-07-15T23:43:00.954081+08:00||log||INFO||info content||[]||[]
||2023-07-15T23:45:25.003792+08:00||log||INFO||create a user||{"name":"a","age":18}||[]
1.5 常量
- 定义
#[Constants]
class ErrorCode extends AbstractConstants
{
/**
* @Message("请不要重复申请")
*/
public const APPLY_REPEAT= 702;
- 使用
echo ErrorCode::UPLOAD_ERROR;
echo ErrorCode::getMessage( ErrorCode::UPLOAD_ERROR);
二 控制器开发
2.1 路由
用法1 配置
Router::get('/v1/test/{id}', 'App\Controller\TestController::index');
Router::post('/v1/apply', 'App\Controller\ApplyController::apply');
#同时支持。
Router::addRoute(['GET', 'POST'], '/v1/test2', 'App\Controller\TestController::test2');
定义一组路由。
Router::addGroup('/user/',function (){
Router::get('index','App\Controller\UserController@index');
Router::post('store','App\Controller\UserController@store');
Router::get('update','App\Controller\UserController@update');
Router::post('delete','App\Controller\UserController@delete');
});
2.2 请求Request
- 创建对象。
use Hyperf\HttpServer\Contract\RequestInterface;
abstract class AbstractController
{
#[Inject]
protected RequestInterface $request;
- 用法。
获取 query
$getArr = $request->query();
//获取表单提交post,和postjson
$data = $request->all();
//获取文件上传
$file = $request->file('file');
$file->moveTo('/foo/bar.jpg');
2.3 response
- 创建response
use Hyperf\HttpServer\Contract\ResponseInterface;
abstract class AbstractController
{
#[Inject]
protected ResponseInterface $response;
- 使用
#控制器返回数组即可
return [
"code" => 0,
"msg" => "here is333333444"
];
三 存储 mysql,redis
3.1 mysql .
- 事务。
use Hyperf\DbConnection\Db;
Db::beginTransaction();
try{
// Do something...
Db::commit();
} catch(\Throwable $ex){
Db::rollBack();
}
- 常用的insert ,update
//获取是否存在
$has_apply = Db::table('apply')->where(
[
['status', '=', Enum::APPLY_STATUS_PENDING],
['mobile', '=', $mobile],
]
)->exists();
//插入数据,返回id.
$apply_id = Db::table('apply')->insertGetId( $applyData );
//更新数据。
Db::table('apply')->where('id', $apply_id)->update(['status' => Enum::APPLY_STATUS_OK]);
//删除数据 ,慎用。
Db::table('apply')->where('id', $apply_id)->delete();
-
查询
- 配置为 数组返回 .
# DbQueryExecutedListener.php public function process(object $event): void { if ($event instanceof StatementPrepared) { $event->statement->setFetchMode(PDO::FETCH_ASSOC); } }- 取数据.
//where 用法和update 一致。 //判断是否申请过 $has_apply = Db::table('apply')->where( [ ['status', '=', Enum::APPLY_STATUS_PENDING], ['mobile', '=', $mobile], ] )->exists(); //单行。 $apply_row = Db::table('apply')->where('id', $apply_id)->first(); //多行 (注意是对象集) $users = Db::table('user')->get();- 直接sql .
#有时候查询条件复杂,跨多表, 又不存在mysql oracle 的切换场景,直接sql才是best practise. //查询多行。 $table = env("DB_PREFIX", "")."user"; $sql = sprintf("select * from %s where id >0", $table); $users = Db::select($sql); // 返回array //查询单行。 $sql = sprintf("select * from %s where id =1", $table); $user = Db::selectOne($sql); // 返回array
3.2 redis
$redis = $this->container->get(\Redis::class);
$redis->set("a", 1);
$redis->setex($redisKey,3,1);
4 计划任务 。
- 安装
composer require hyperf/crontab
- 配置.
<?php
use Hyperf\Crontab\Crontab;
return [
// 是否开启定时任务
'enable' => true,
'crontab' => [
// Callback类型定时任务(默认)
(new Crontab())->setName('Foo')->setRule('* * * * *')->setCallback([App\Task\FooTask::class, 'execute'])->setMemo('这是一个示例的定时任务'),
],
];
查看日志
还可以用注解来定义。
5 command
生成命令文件
php bin/hyperf.php gen:command FooCommand
修改对应的 FooCommand.php
执行命令。
php bin/hyperf.php demo:command