官方文档
* https://hyperf.wiki/2.0/#/README

初步搭建
1. 安装项目

composer create-project hyperf/hyperf-skeleton

2. 项目根目录配置为当前目录的安装目录根目录,即不存在public目录

3. 配置Nginx反向代理

# 至少需要一个 Hyperf 节点,多个配置多行
upstream hyperf {
# Hyperf HTTP Server 的 IP 及 端口
server 127.0.0.1:9501;
server 127.0.0.1:9502;
} server {
# 监听端口
listen 80;
# 绑定的域名,填写您的域名
server_name proxy.hyperf.io; location / {
# 将客户端的 Host 和 IP 信息一并转发到对应节点
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 转发Cookie,设置 SameSite
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; # 执行代理访问真实服务器
proxy_pass http://hyperf;
}
}

4. 宝塔Nginx配置为(同LNMP的Nginx配置)

upstream hyperf {
# Hyperf HTTP Server 的 IP 及 端口
server 127.0.0.1:9501;
server 127.0.0.1:9502;
} server
{
listen 80;
server_name hyperf.com.net;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/hyperf-skeleton; #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END #ERROR-PAGE-START 错误页配置,可以注释、删除或修改
#error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END #PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-74.conf;
#PHP-INFO-END location / {
# 将客户端的 Host 和 IP 信息一并转发到对应节点
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 转发Cookie,设置 SameSite
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; # 执行代理访问真实服务器
proxy_pass http://hyperf;
} #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/hyperf.kefu.com.net.conf;
#REWRITE-END #禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
} #一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
} location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log off;
access_log /dev/null;
} location ~ .*\.(js|css)?$
{
expires 12h;
error_log off;
access_log /dev/null;
}
access_log /www/wwwlogs/hyperf.kefu.com.net.log;
error_log /www/wwwlogs/hyperf.kefu.com.net.error.log;
}

5.启动http服务命令

php bin/hyperf.php start

或者重写启动文件watch。执行命令为:php watch

#!/usr/bin/env php
<?php /**
* Hyperf Watch Hot Reload Scripts
* From: https://github.com/ha-ni-cc/hyperf-watch
* Author: hanicc@qq.com
* Usage:
* Open the terminal console in the project root directory and enter:php watch
* 在项目根目录下打开终端控制台,输入:php watch
* If you want to clean the /runtime/container cache, enter: php watch -c
* 如果你想要清除/runtime/container缓存,则输入:php watch -c
*/ # PHP Bin File PHP程序所在路径(默认自动获取)
const PHP_BIN_FILE = 'which php';
# Watch Dir 监听目录(默认监听脚本所在的根目录)
const WATCH_DIR = __DIR__ . '/';
# Watch Ext 监听扩展名(多个可用英文逗号隔开)
const WATCH_EXT = 'php,env';
# Exclude Dir 排除目录(不监听的目录,数组形式)
const EXCLUDE_DIR = ['vendor', 'runtime', 'public'];
# Entry Point File 入口文件
const ENTRY_POINT_FILE = __DIR__ . '/bin/hyperf.php';
# Start Command 启动命令
const START_COMMAND = [ENTRY_POINT_FILE, 'start'];
# PID File Path PID文件路径
const PID_FILE_PATH = __DIR__ . '/runtime/hyperf.pid';
# Scan Interval 扫描间隔(毫秒,默认2000)
const SCAN_INTERVAL = 2000; if (!function_exists('exec')) {
echo '[x] 请在php.ini配置中取消禁用exec方法' . PHP_EOL;
exit(1);
} define('PHP', PHP_BIN_FILE == 'which php' ? exec('which php') : PHP_BIN_FILE); if (!file_exists(PHP) || !is_executable(PHP)) {
echo '[x] PHP bin (" ' . PHP . ' ") 路径没有找到或无法执行,请确认路径正确?' . PHP_EOL;
exit(1);
} if (!file_exists(ENTRY_POINT_FILE)) {
echo '[x] 入口文件 ("' . ENTRY_POINT_FILE . '") 没有找到,请确认文件存在?' . PHP_EOL;
exit(1);
} # 加载env
$content = @file_get_contents('.env');
$values = array_filter(preg_split("/(\r\n|\n|\r)/", $content));
foreach ($values as $val) {
if (substr($val, 0, 1) === '#') {
continue;
}
list($name, $value) = explode('=', $val);
$_ENV[$name] = $value;
} use Swoole\Process;
use Swoole\Timer;
use Swoole\Event; swoole_async_set(['enable_coroutine' => false, 'log_level' => SWOOLE_LOG_INFO]);
$hashes = [];
$serve = null;
echo " Start @ " . date('Y-m-d H:i:s') . PHP_EOL;
start();
state();
Timer::tick(SCAN_INTERVAL, 'watch'); function killOldProcess()
{
// pid存在则关闭存在的进程
if (file_exists(PID_FILE_PATH) && $pid = @file_get_contents(PID_FILE_PATH)) {
if (!@posix_kill($pid)) forceKill();
} else forceKill();
} function forceKill($match = '')
{
if (!$match) {
$match = @$_ENV['APP_NAME'] . '.Master';
}
// 适配MacOS
if (PHP_OS == 'Darwin') $match = ENTRY_POINT_FILE;
$command = "ps -ef | grep '$match' | grep -v grep | awk '{print $2}' | xargs kill -9 2>&1";
// 找不到pid,强杀进程
exec($command);
} function start()
{
// 杀旧进程
killOldProcess();
global $serve;
$serve = new Process('serve', true);
$serve->start();
if (false === $serve->pid) {
echo swoole_strerror(swoole_errno()) . PHP_EOL;
exit(1);
}
addEvent($serve);
} function addEvent($serve)
{
Event::add($serve->pipe, function () use (&$serve) {
$message = @$serve->read();
if (!empty($message)) {
echo $message;
}
});
} function watch()
{
global $hashes;
foreach ($hashes as $pathName => $currentHash) {
if (!file_exists($pathName)) {
unset($hashes[$pathName]);
continue;
}
$newHash = fileHash($pathName);
if ($newHash != $currentHash) {
change();
state();
break;
}
}
} function state()
{
global $hashes;
$files = phpFiles(WATCH_DIR);
$hashes = array_combine($files, array_map('fileHash', $files));
$count = count($hashes);
echo " Watching $count files..." . PHP_EOL;
} function change()
{
global $serve;
echo " Restart @ " . date('Y-m-d H:i:s') . PHP_EOL;
Process::kill($serve->pid);
start();
} function serve(Process $serve)
{
$opt = getopt('c');
# if (isset($opt['c'])) echo exec(PHP . ' ' . ENTRY_POINT_FILE . ' di:init-proxy') . '..' . PHP_EOL;
if (isset($opt['c'])) delDir('./runtime/container');
$serve->exec(PHP, START_COMMAND);
} function fileHash(string $pathname): string
{
$contents = @file_get_contents($pathname);
if (false === $contents) {
return 'deleted';
}
return md5($contents);
} function phpFiles(string $dirname): array
{
$directory = new RecursiveDirectoryIterator($dirname);
$filter = new Filter($directory);
$iterator = new RecursiveIteratorIterator($filter);
return array_map(function ($fileInfo) {
return $fileInfo->getPathname();
}, iterator_to_array($iterator));
} function delDir($path)
{
if (is_dir($path)) {
//扫描一个目录内的所有目录和文件并返回数组
$dirs = scandir($path);
foreach ($dirs as $dir) {
//排除目录中的当前目录(.)和上一级目录(..)
if ($dir != '.' && $dir != '..') {
//如果是目录则递归子目录,继续操作
$sonDir = $path . '/' . $dir;
if (is_dir($sonDir)) {
//递归删除
delDir($sonDir);
//目录内的子目录和文件删除后删除空目录
@rmdir($sonDir);
} else {
//如果是文件直接删除
@unlink($sonDir);
}
}
}
@rmdir($path);
}
} class Filter extends RecursiveFilterIterator
{
public function accept()
{
if ($this->current()->isDir()) {
if (preg_match('/^\./', $this->current()->getFilename())) {
return false;
}
return !in_array($this->current()->getFilename(), EXCLUDE_DIR);
}
$list = array_map(function (string $item): string {
return "\.$item";
}, explode(',', WATCH_EXT));
$list = implode('|', $list);
return preg_match("/($list)$/", $this->current()->getFilename());
}
}

6. 启动报错

ERROR Swoole short name have to disable before start server, please set swoole.use_shortname = off into your php.ini. 

php.ini文件最后一行新增 swoole.use_shortname = off 即可

7. 访问当前配置域名返回

hyperf-搭建初始化的更多相关文章

  1. Activiti工作流搭建---初始化数据库

    Activiti介绍 Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩展的可执 ...

  2. vue3.0+vite+ts项目搭建--初始化项目(一)

    vite 初始化项目 使用npm npm init vite@latest 使用yarn yarn create vite 使用pnpm pnpx create-vite 根据提示输入项目名称,选择v ...

  3. 图解Hyperf框架:Hyperf 的初始化

  4. vue二、脚手架搭建

    1:安装nodeJs(下载一路回车) https://nodejs.org/zh-cn/ 2:检验nodeJs是否安装成功 (注意nodeJs是否添加到window路径中) 进入cmd -> n ...

  5. finger-guessing game:1场景搭建

    场景搭建 //初始化legend组件 init(50, "div_caiquan", 800, 400, main); //定义游戏层 //游戏背景层,结果显示层,点击层 var ...

  6. TypeScript完全解读(26课时)_1.TypeScript完全解读-开发环境搭建

    1.TypeScript完全解读-开发环境搭建 初始化项目 手动创建文件夹 D:\MyDemos\tsDemo\client-demo 用VSCode打开 npm init:初始化项目 然后我们的项目 ...

  7. 使用VuePress搭建个人博客

    使用VuePress搭建个人博客 VuePress 是一个基于 Vue 的静态网站生成器.其中主要用到:Vue,VueRouter,Webpack. 类似的工具:hexo 基于 Markdown 语法 ...

  8. rollup 开发环境搭建

    rollup 开发环境搭建 初始化项目使用lerna管理项目 使用npm init 初始化项目 npm init -y 安装lerna并初始化项目 npm install lerna --save-d ...

  9. 【迁移】—Entity Framework实例详解 转

    一.Entity Framework 迁移命令(get-help EntityFramework) Enable-Migrations 启用迁移 Add-Migration 为挂起的Model变化添加 ...

  10. Node.js高级编程读书笔记 - 4 构建Web应用程序

    Outline 5 构建Web应用程序 5.1 构建和使用HTTP中间件 5.2 用Express.js创建Web应用程序 5.3 使用Socket.IO创建通用的实时Web应用程序 5 构建Web应 ...

随机推荐

  1. Vue 状态管理之vuex && {mapState,mapGetters}

    1 # 一.理解vuex 2 1.概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读写),也是一种组件间通信的方式,且适用于任意组件间 ...

  2. linux常见命令(七)

    df/du/ln/lsblk/mount磁盘和目录的容量df 列出文件系统整体的磁盘使用量查看磁盘占用量并用易读的格式显示出来df -hdu 列出目录的磁盘占用量查看当前目录下每个目录/文件的占用量, ...

  3. Linux 的常用基本命令

    一.Linux 的常用基本命令..................................................................................... ...

  4. Git 02 安装

    参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 这里以安装 ...

  5. 2022-08-15 - 初识MySQL

    MySQL数据库 数据库 数据库,又称为Database,简称DB.数据库就是一个文件集合. 顾名思义:是一个存储数据的仓库,实际上就是一堆文件,这些文件中存储了具有特定格式的数据,可以很方便的对里面 ...

  6. LOJ6077「2017 山东一轮集训 Day7」逆序对 (生成函数+多项式exp?朴素DP!)

    题面 给定 n , k n,k n,k ,求长度为 n n n 逆序对个数为 k k k 的排列个数,对 1 e 9 + 7 \rm1e9+7 1e9+7 取模. 1 ≤ n , k ≤ 100   ...

  7. PHP为任意页面设访问密码

    使用方法 把下面的代码存为php文件,下面的整段代码是验证过程,然后在你入口页进行调用例如命名为MkEncrypt.php,那么在入口页进行       require_once('MkEncrypt ...

  8. 1.2_Selenium的三生三世

  9. python筛选excel内容并生成exe文件

    最近疫情原因,班级每天都要筛选未打卡人员,每次都手动操作太麻烦了.遂写下如下的程序,并且生成了exe可执行文件. 1. 主程序 import openpyxl import pyperclip # 1 ...

  10. DataRow修改某一Cell的值

    发现ItemArray并不能改变DataRow的值,之前用ItemArray来复制整行数据的操作. 实际上可以直接用DataRow[]就可以直接改变对应Cell的值.