Hyperf 常用组件
1. 数据库组件
1.1 Model 模型
定义模型
<?php
namespace App\Model;
use Hyperf\DbConnection\Model\Model;
class User extends Model
{
protected ?string $table = 'users';
protected string $primaryKey = 'id';
protected array $fillable = ['name', 'email', 'password'];
protected array $hidden = ['password'];
protected array $casts = [
'created_at' => 'datetime',
'is_active' => 'boolean',
];
}
基本操作
<?php
// 查询
$user = User::find(1);
$user = User::where('email', 'test@example.com')->first();
$users = User::where('status', 1)->get();
// 创建
$user = User::create([
'name' => 'John',
'email' => 'john@example.com',
'password' => password_hash('123456', PASSWORD_DEFAULT),
]);
// 更新
$user = User::find(1);
$user->name = 'Jane';
$user->save();
// 或者
User::where('id', 1)->update(['name' => 'Jane']);
// 删除
$user = User::find(1);
$user->delete();
// 或者
User::destroy(1);
User::where('status', 0)->delete();
关联关系
<?php
namespace App\Model;
use Hyperf\Database\Model\Relations\HasMany;
use Hyperf\Database\Model\Relations\BelongsTo;
class User extends Model
{
// 一对多:一个用户有多个订单
public function orders(): HasMany
{
return $this->hasMany(Order::class, 'user_id', 'id');
}
}
class Order extends Model
{
// 多对一:订单属于用户
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
}
// 使用
$user = User::find(1);
$orders = $user->orders; // 获取用户的所有订单
$order = Order::find(1);
$user = $order->user; // 获取订单的用户
1.2 查询构造器
<?php
use Hyperf\DbConnection\Db;
// 基本查询
$users = Db::table('users')->get();
$user = Db::table('users')->where('id', 1)->first();
// 条件查询
$users = Db::table('users')
->where('status', 1)
->where('age', '>', 18)
->orWhere('vip', true)
->get();
// 聚合查询
$count = Db::table('users')->count();
$max = Db::table('users')->max('age');
$avg = Db::table('users')->avg('score');
// 分组
$result = Db::table('orders')
->select('user_id', Db::raw('SUM(amount) as total'))
->groupBy('user_id')
->having('total', '>', 1000)
->get();
// 联表查询
$orders = Db::table('orders')
->join('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', 'users.name')
->get();
// 分页
$users = Db::table('users')->paginate(15);
// 事务
Db::transaction(function () {
Db::table('users')->update(['balance' => Db::raw('balance - 100')]);
Db::table('orders')->insert(['amount' => 100]);
});
1.3 数据库迁移
创建迁移
php bin/hyperf.php gen:migration create_users_table
编写迁移
<?php
use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 100);
$table->string('email', 100)->unique();
$table->string('password');
$table->tinyInteger('status')->default(1);
$table->timestamps();
$table->index('email');
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
}
运行迁移
php bin/hyperf.php migrate
php bin/hyperf.php migrate:rollback
php bin/hyperf.php migrate:refresh
2. 缓存组件
2.1 注解方式(推荐)
<?php
namespace App\Service;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\Cache\Annotation\CachePut;
use Hyperf\Cache\Annotation\CacheEvict;
class UserService
{
// 生成缓存
#[Cacheable(prefix: 'user', ttl: 3600, value: '#{id}')]
public function getUserById(int $id)
{
return Db::table('users')->find($id);
}
// 更新缓存
#[CachePut(prefix: 'user', ttl: 3600, value: '#{user.id}')]
public function updateUser(array $user)
{
Db::table('users')->where('id', $user['id'])->update($user);
return $user;
}
// 删除缓存
#[CacheEvict(prefix: 'user', value: '#{id}')]
public function deleteUser(int $id)
{
Db::table('users')->where('id', $id)->delete();
}
// 删除所有缓存
#[CacheEvict(prefix: 'user', all: true)]
public function deleteAllCache()
{
}
}
2.2 手动操作
<?php
use Hyperf\Redis\Redis;
use Hyperf\Di\Annotation\Inject;
class UserService
{
#[Inject]
private Redis $redis;
public function getUserById(int $id)
{
$key = "user:{$id}";
// 获取缓存
$cached = $this->redis->get($key);
if ($cached !== null) {
return json_decode($cached, true);
}
// 查询数据库
$user = Db::table('users')->find($id);
// 保存到缓存
$this->redis->setex($key, 3600, json_encode($user));
return $user;
}
}
2.3 缓存失效策略
<?php
// 设置过期时间
$redis->setex('key', 3600, 'value'); // 3600秒后过期
$redis->expire('key', 3600);
// 删除缓存
$redis->del('key');
$redis->del(['key1', 'key2', 'key3']);
// 模糊删除
$keys = $redis->keys('user:*');
if ($keys) {
$redis->del(...$keys);
}
3. 日志组件
3.1 基本使用
<?php
namespace App\Service;
use Hyperf\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;
class UserService
{
private LoggerInterface $logger;
public function __construct(LoggerFactory $loggerFactory)
{
// 获取日志实例(default 是配置名称)
$this->logger = $loggerFactory->get('default');
}
public function createUser(array $data)
{
$this->logger->debug('开始创建用户', $data);
try {
$user = User::create($data);
$this->logger->info('用户创建成功', ['id' => $user->id]);
return $user;
} catch (\Exception $e) {
$this->logger->error('用户创建失败', [
'exception' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
throw $e;
}
}
}
3.2 日志级别
<?php
$logger->emergency('系统不可用');
$logger->alert('必须立即采取行动');
$logger->critical('临界条件');
$logger->error('错误');
$logger->warning('警告');
$logger->notice('通知');
$logger->info('信息');
$logger->debug('调试');
3.3 配置多个日志
config/autoload/logger.php:
<?php
return [
'default' => [
'handler' => [
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => Monolog\Logger::DEBUG,
],
],
],
'sql' => [
'handler' => [
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/sql.log',
'level' => Monolog\Logger::INFO,
],
],
],
];
使用:
<?php
$defaultLogger = $loggerFactory->get('default');
$sqlLogger = $loggerFactory->get('sql');
4. 验证器
4.1 创建验证器
<?php
namespace App\Request;
use Hyperf\Validation\Request\FormRequest;
class UserRequest extends FormRequest
{
public function authorize(): bool
{
return true; // 是否有权限执行此请求
}
public function rules(): array
{
return [
'name' => 'required|string|max:100',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:6|confirmed',
'age' => 'required|integer|min:1|max:150',
'avatar' => 'nullable|image|max:2048', // 最大 2MB
];
}
public function messages(): array
{
return [
'name.required' => '姓名不能为空',
'email.required' => '邮箱不能为空',
'email.email' => '邮箱格式不正确',
'email.unique' => '邮箱已被注册',
'password.required' => '密码不能为空',
'password.min' => '密码长度不能少于 6 位',
'password.confirmed' => '两次密码输入不一致',
];
}
}
4.2 使用验证器
<?php
namespace App\Controller;
use App\Request\UserRequest;
class UserController
{
public function create(UserRequest $request)
{
// 如果验证失败,会自动返回 422 错误
// 验证通过后,可以获取数据
$data = $request->validated();
$user = User::create($data);
return ['id' => $user->id];
}
}
4.3 常用验证规则
<?php
return [
'name' => 'required', // 必填
'email' => 'required|email|unique:users', // 必填、邮箱格式、唯一
'age' => 'integer|between:1,150', // 整数、范围
'url' => 'url', // URL 格式
'ip' => 'ip', // IP 地址
'date' => 'date|after:2020-01-01', // 日期、晚于某日期
'amount' => 'numeric|min:0', // 数字、最小值
'status' => 'in:active,inactive', // 枚举值
'tags' => 'array', // 数组
'tags.*' => 'string', // 数组元素类型
];
4.4 自定义验证规则
<?php
namespace App\Request;
use Hyperf\Validation\Request\FormRequest;
use Hyperf\Validation\Rule;
class UserRequest extends FormRequest
{
public function rules(): array
{
return [
'phone' => ['required', 'regex:/^1[3-9]\d{9}$/'], // 手机号
'id_card' => ['required', function ($attribute, $value, $fail) {
// 自定义验证逻辑
if (!$this->validateIdCard($value)) {
$fail('身份证号格式不正确');
}
}],
];
}
private function validateIdCard($value): bool
{
// 验证身份证号的逻辑
return preg_match('/^\d{17}[\dXx]$/', $value);
}
}
5. 定时任务
5.1 创建定时任务
<?php
namespace App\Crontab;
use Hyperf\Crontab\Annotation\Crontab;
#[Crontab(
name: 'StatisticsTask',
rule: '0 2 * * *', // 每天凌晨 2 点执行
callback: 'execute',
memo: '统计每日数据'
)]
class StatisticsTask
{
public function execute()
{
echo "执行统计任务\n";
// 统计逻辑
$count = Db::table('orders')
->whereDate('created_at', date('Y-m-d'))
->count();
echo "今日订单数:{$count}\n";
}
}
5.2 Cron 表达式
* * * * *
│ │ │ │ │
│ │ │ │ └─ 星期 (0-7, 0和7都表示周日)
│ │ │ └─── 月份 (1-12)
│ │ └───── 日期 (1-31)
│ └─────── 小时 (0-23)
└───────── 分钟 (0-59)
常用示例:
'0 2 * * *' // 每天凌晨 2 点
'*/5 * * * *' // 每 5 分钟
'0 */2 * * *' // 每 2 小时
'0 0 * * 0' // 每周日凌晨
'0 0 1 * *' // 每月 1 号凌晨
'0 9-18 * * 1-5' // 工作日 9-18 点,每小时
5.3 动态定时任务
<?php
namespace App\Service;
use Hyperf\Crontab\Crontab;
use Hyperf\Crontab\CrontabManager;
use Hyperf\Di\Annotation\Inject;
class CrontabService
{
#[Inject]
private CrontabManager $crontabManager;
public function addTask(string $name, string $rule, callable $callback)
{
$crontab = new Crontab();
$crontab->setName($name);
$crontab->setRule($rule);
$crontab->setCallback($callback);
$crontab->setMemo('动态添加的任务');
$this->crontabManager->register($crontab);
}
public function removeTask(string $name)
{
$this->crontabManager->deregister($name);
}
}
6. 异步队列
6.1 创建任务
<?php
namespace App\Job;
use Hyperf\AsyncQueue\Job;
class EmailJob extends Job
{
public $params;
public function __construct(array $params)
{
$this->params = $params;
}
public function handle()
{
// 发送邮件的逻辑
$to = $this->params['to'];
$subject = $this->params['subject'];
$content = $this->params['content'];
echo "发送邮件到: {$to}\n";
// 实际发送邮件...
}
}
6.2 推送任务
<?php
namespace App\Controller;
use App\Job\EmailJob;
use Hyperf\AsyncQueue\Driver\DriverFactory;
use Hyperf\Di\Annotation\Inject;
class UserController
{
#[Inject]
private DriverFactory $driverFactory;
public function sendEmail()
{
$driver = $this->driverFactory->get('default');
// 推送任务到队列
$driver->push(new EmailJob([
'to' => 'user@example.com',
'subject' => '欢迎注册',
'content' => '感谢您的注册!',
]), 0); // 延迟 0 秒
return '邮件已加入发送队列';
}
public function sendDelayedEmail()
{
$driver = $this->driverFactory->get('default');
// 延迟 60 秒后发送
$driver->push(new EmailJob([
'to' => 'user@example.com',
'subject' => '延迟消息',
'content' => '这是一封延迟发送的邮件',
]), 60);
return '邮件将在 60 秒后发送';
}
}
6.3 启动消费者
php bin/hyperf.php start
消费者会自动处理队列中的任务。
7. 事件系统
7.1 定义事件
<?php
namespace App\Event;
class UserRegistered
{
public $user;
public function __construct($user)
{
$this->user = $user;
}
}
7.2 定义监听器
<?php
namespace App\Listener;
use App\Event\UserRegistered;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use Psr\Container\ContainerInterface;
#[Listener]
class SendWelcomeEmailListener implements ListenerInterface
{
public function __construct(private ContainerInterface $container)
{
}
public function listen(): array
{
return [
UserRegistered::class,
];
}
public function process(object $event): void
{
if ($event instanceof UserRegistered) {
$user = $event->user;
// 发送欢迎邮件
echo "发送欢迎邮件到: {$user->email}\n";
}
}
}
7.3 触发事件
<?php
namespace App\Service;
use App\Event\UserRegistered;
use Psr\EventDispatcher\EventDispatcherInterface;
use Hyperf\Di\Annotation\Inject;
class UserService
{
#[Inject]
private EventDispatcherInterface $eventDispatcher;
public function register(array $data)
{
$user = User::create($data);
// 触发事件
$this->eventDispatcher->dispatch(new UserRegistered($user));
return $user;
}
}
8. 要点
必须掌握
- 数据库 Model 和查询构造器的使用
- 缓存注解的使用
- 日志的使用
- 验证器的使用
- 定时任务的配置
加分项
- 异步队列的使用场景
- 事件系统的应用
- 数据库迁移和 Seeder
高频题
1. Hyperf 的缓存注解有哪几种?
答:主要有三种:
@Cacheable:生成缓存,方法首次调用时将结果缓存@CachePut:更新缓存,每次都执行方法并更新缓存@CacheEvict:删除缓存,可以删除单个或全部缓存
2. 异步队列有什么用?
答:异步队列用于将耗时任务异步执行,避免阻塞主流程。
应用场景:
- 发送邮件、短信
- 数据统计和分析
- 图片处理
- 导出大文件
- 调用第三方 API
3. 定时任务如何配置?
答:使用 @Crontab 注解,配置任务名称、执行规则(Cron 表达式)、回调方法等。Hyperf 会自动调度执行。
下一步:阅读 08-题库.md 巩固知识点