hyperf 用法快速上手

1,057 阅读2分钟

一 准备阶段

1.1 watcher .

说明:hyperf 是cli 模式运行,在dev 环境下,每改一行代码,需要重启服务,会很折腾,安装watcher 改善这个问题。

步骤

  1. 安装

    composer require hyperf/watcher --dev
    #发布配置
    php bin/hyperf.php vendor:publish hyperf/watcher
    # 去 .watcher.php 中查看配置。
    
  2. 修改启动命令

    # 容器下
    ENTRYPOINT ["php", "/data/project/hyperf/bin/hyperf.php", "server:watch"]
    #或者 直接cli   
    php bin/hyperf.php server:watch
    
  3. 效果。 当修改代码后,程序会扫描到代码改动

    [DEBUG] Hyperf\Watcher\Driver\ScanFileDriver Watching: Total:47, Change:1, Add:0, Delete:0.
    Class reload success.
    Stop server...
    Stop server success.
    Start server ...
  1. 不爽的地方。
    1. 如果机器性能太拉,就很慢。
    2. 改 .env 文件,和删文件会失效,改vendor 后要重启。

1.2 环境变量

  1. 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_
    
  2. .env 设置与读取。

    #.env  下添加一行。
    ENV_TEST="here is env test info"
    
    echo  env("ENV_TEST");
    

1.3 配置config

  1. config 配置,与使用。
#设置
config.php
    "test_config" => "test_config_value"
  1. 用法

    ​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
   }
  1. 常用套路,先 env ,然后config
//先读 .env 文件中的LOGIN_TTL 如果没有则为 7200
'login_ttl' => env('LOGIN_TTL', 7200),

1.4 日志

  1. 安装

    composer require hyperf/logger
    
  2. 配置 。

    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 常量

  1. 定义
#[Constants]
class ErrorCode extends AbstractConstants
{
    /**
     * @Message("请不要重复申请")
     */
    public const APPLY_REPEAT= 702;

  1. 使用
    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

  1. 创建对象。
use Hyperf\HttpServer\Contract\RequestInterface;
abstract class AbstractController
{

    #[Inject]
    protected RequestInterface $request;
  1. 用法。
获取 query 
$getArr = $request->query();

//获取表单提交post,和postjson
$data = $request->all();

//获取文件上传
$file = $request->file('file');
$file->moveTo('/foo/bar.jpg');

2.3 response

  1. 创建response
use Hyperf\HttpServer\Contract\ResponseInterface;
abstract class AbstractController
{
    #[Inject]
    protected ResponseInterface $response;
  1. 使用
#控制器返回数组即可
      return [
            "code" => 0,
            "msg" => "here is333333444"
        ];

三 存储 mysql,redis

3.1 mysql .

  1. 事务。
use Hyperf\DbConnection\Db;
Db::beginTransaction();
try{
    // Do something...
    Db::commit();
} catch(\Throwable $ex){
    Db::rollBack();
}
  1. 常用的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();
  1. 查询

    1. 配置为 数组返回 .
    #  DbQueryExecutedListener.php
    public function process(object $event): void
    {
        if ($event instanceof StatementPrepared) {
            $event->statement->setFetchMode(PDO::FETCH_ASSOC);
        }
    }
    
    1. 取数据.
    //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();
    
    1. 直接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 计划任务 。

  1. 安装
composer require hyperf/crontab
  1. 配置.
<?php
use Hyperf\Crontab\Crontab;
return [
    // 是否开启定时任务
    'enable' => true,
    'crontab' => [
        // Callback类型定时任务(默认)
        (new Crontab())->setName('Foo')->setRule('* * * * *')->setCallback([App\Task\FooTask::class, 'execute'])->setMemo('这是一个示例的定时任务'),
    ],
];

查看日志 image.png

还可以用注解来定义。

5 command

生成命令文件

php bin/hyperf.php gen:command FooCommand

修改对应的 FooCommand.php

执行命令。

php bin/hyperf.php demo:command