在 ServBay 中创建并运行 Webman 项目
什么是 Webman?
Webman 是一个基于 Workerman 的高性能 PHP 异步 Web 框架,专为构建高并发、高性能的 Web 应用而设计。与传统的同步阻塞框架不同,Webman 采用事件驱动和异步非阻塞 I/O 模型,使其在处理大量并发请求时表现出色。Webman 提供了简洁易用的 API 和灵活的扩展机制,非常适合用于构建实时应用、API 服务、微服务等。
Webman 的主要特性和优势
- 高性能: 基于 Workerman,利用事件驱动和异步非阻塞 I/O,能够处理海量并发连接,吞吐量远超传统同步框架。
- 易于使用: 提供简洁直观的 API 和丰富的功能,开发者可以快速上手并构建应用。
- 多协议支持: 内置支持 HTTP、WebSocket 等多种常用应用层协议,方便构建不同类型的服务。
- 灵活扩展: 支持通过 Composer 包、插件和中间件机制轻松扩展框架功能。
- 低资源占用: 相较于传统 Web 服务器 + PHP-FPM 的模式,Webman 作为常驻内存应用,资源开销更低。
- 强大的社区支持: 拥有活跃的开发者社区和丰富的文档资源。
Webman 能够帮助开发者快速构建高性能、高可用的 Web 应用和 API 服务,特别适用于需要处理高并发、低延迟的场景。
使用 ServBay 创建并运行一个简单的 Webman 项目
本指南将详细介绍如何在 ServBay 本地开发环境中使用 Webman 创建并运行一个简单的 Web 项目。我们将演示如何安装 Webman、编写基本的路由和控制器代码,以及如何集成 ServBay 提供的数据库(MySQL, PostgreSQL)和缓存服务(Redis, Memcached)。
TIP
ServBay 建议开发者将所有本地网站项目存放在/Applications/ServBay/www
目录下,这样便于 ServBay 进行统一管理,例如配置本地网站(原称为“主机”)。
前提条件
在开始之前,请确保您已完成以下准备:
- 安装 ServBay: 您已经在 macOS 上成功安装了 ServBay。ServBay 提供了一站式的本地开发环境,包含了 PHP、Composer、MySQL、PostgreSQL、Redis、Memcached 等本教程所需的全部软件包。
- 启用所需软件包: 通过 ServBay 控制面板,确保以下软件包已安装并正在运行:
- 您选择的 PHP 版本 (建议使用较新版本,如 PHP 8.x)
- Composer (ServBay 已内置)
- MySQL
- PostgreSQL
- Redis
- Memcached
- 确保您所选的 PHP 版本已启用
memcached
,redis
,pdo_mysql
,pdo_pgsql
等必要的 PHP 扩展。ServBay 通常默认启用这些常用扩展,您可以在 ServBay 的 PHP 配置界面中检查。
- 终端访问: 熟悉使用 macOS 的终端应用程序。
安装 Webman
确认 Composer 可用
ServBay 出厂时已经自带 Composer,并且已配置为可在终端中直接使用。您可以在终端中运行以下命令确认:
bashcomposer --version
1如果正确显示 Composer 版本信息,则表示 Composer 已准备就绪。
进入 ServBay 网站目录
打开终端,进入 ServBay 建议的网站根目录:
bashcd /Applications/ServBay/www
1使用 Composer 创建 Webman 项目
使用 Composer 的
create-project
命令来安装 Webman 框架到指定目录。我们将项目命名为servbay-webman-app
:bashcomposer create-project workerman/webman servbay-webman-app
1Composer 将从 Packagist 下载 Webman 及其核心依赖到
servbay-webman-app
目录中。进入项目目录
安装完成后,进入新创建的项目目录:
bashcd servbay-webman-app
1安装必要的组件
为了演示数据库和缓存功能,我们需要安装一些额外的 Composer 包。Webman 通常使用
illuminate/database
(来自 Laravel 的数据库组件)、illuminate/redis
等。-W
参数(--with-dependencies
)用于在安装时解决依赖冲突,确保兼容性。bashcomposer require -W illuminate/database illuminate/redis illuminate/pagination illuminate/events symfony/var-dumper
1这个命令会安装数据库 ORM、Redis 客户端、分页组件、事件调度器以及用于调试的 VarDumper。
创建数据库和表
为了使示例代码能够正常工作,我们需要在 ServBay 的 MySQL 和 PostgreSQL 数据库中创建相应的数据库和 users
表。ServBay 默认的数据库 root
用户密码是 password
。
您可以使用 ServBay 提供的数据库管理工具(如 phpMyAdmin 或 pgAdmin,通过 ServBay 控制面板访问)或命令行来执行以下 SQL 语句。
创建数据库
webman_app
- MySQL:sql
CREATE DATABASE IF NOT EXISTS webman_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
1 - PostgreSQL:sql
CREATE DATABASE webman_app;
1
- MySQL:
在
webman_app
数据库中创建users
表- MySQL:sql
USE webman_app; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
1
2
3
4
5
6
7 - PostgreSQL:sql
\c webman_app; -- 连接到新创建的数据库 CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
1
2
3
4
5
6
7
- MySQL:
编写 Web 项目代码
接下来,我们将添加代码来定义路由、创建控制器,并实现与数据库和缓存的交互逻辑。
配置路由
编辑项目根目录下的
config/route.php
文件,添加以下代码来定义示例所需的路由:php<?php use Webman\Route; use app\controller\IndexController; use app\controller\CacheController; use app\controller\DatabaseController; // 定义根路径路由,映射到 IndexController 的 index 方法 Route::any('/', [IndexController::class, 'index']); // 定义缓存相关路由 Route::any('/memcached', [CacheController::class, 'memcached']); Route::any('/redis', [CacheController::class, 'redis']); // 定义数据库相关路由 Route::any('/mysql-add', [DatabaseController::class, 'mysqlAdd']); Route::any('/mysql', [DatabaseController::class, 'mysqlGet']); Route::any('/pgsql-add', [DatabaseController::class, 'pgsqlAdd']); Route::any('/pgsql', [DatabaseController::class, 'pgsqlGet']); // 可以在这里添加更多路由...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21创建控制器文件
在
app/controller
目录下创建IndexController.php
、CacheController.php
和DatabaseController.php
文件,并分别添加以下代码。app/controller/IndexController.php
: 用于处理根路径请求。php<?php namespace app\controller; use support\Request; use support\Response; // 引入 Response 类 class IndexController { /** * 处理根路径请求的示例方法 * @param Request $request 当前请求对象 * @return Response 返回一个 Response 对象 */ public function index(Request $request): Response // 明确返回类型 { // 返回一个简单的文本响应 return response('Hello ServBay & Webman!'); // 更新欢迎信息 } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20app/controller/CacheController.php
: 用于演示 Memcached 和 Redis 的使用。php<?php namespace app\controller; use support\Request; use support\Response; use Memcached; // 引入 Memcached 类 use support\Redis; // 引入 Webman 提供的 Redis Facade class CacheController { /** * 演示 Memcached 的使用 * @param Request $request * @return Response */ public function memcached(Request $request): Response { // 连接 Memcached 服务器,ServBay 默认运行在 127.0.0.1:11211 $memcached = new Memcached(); $memcached->addServer('127.0.0.1', 11211); // 设置缓存项,有效期 60 秒 $success = $memcached->set('servbay_key', 'Hello Memcached from ServBay!', 60); // 更新 key 和 value if (!$success) { return response('Failed to set Memcached key', 500); } // 获取缓存项 $value = $memcached->get('servbay_key'); // 更新 key // 返回获取到的值 return response($value ?: 'Memcached key not found or expired'); // 增加找不到时的提示 } /** * 演示 Redis 的使用 * @param Request $request * @return Response */ public function redis(Request $request): Response { // 使用 Webman 的 Redis Facade 设置缓存项 Redis::set('servbay_redis_key', 'Hello Redis from ServBay!'); // 更新 key 和 value // 使用 Webman 的 Redis Facade 获取缓存项 $value = Redis::get('servbay_redis_key'); // 更新 key // 返回获取到的值 return response($value ?: 'Redis key not found'); // 增加找不到时的提示 } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52app/controller/DatabaseController.php
: 用于演示 MySQL 和 PostgreSQL 的数据库操作。php<?php namespace app\controller; use support\Request; use support\Response; use support\Db; // 引入 Webman 提供的 Db Facade class DatabaseController { /** * 向 MySQL 数据库添加用户 * @param Request $request * @return Response */ public function mysqlAdd(Request $request): Response { try { // 使用 Db Facade 连接 'mysql' 数据库并插入数据 Db::connection('mysql')->table('users')->insert([ 'name' => 'ServBay Webman MySQL User', // 更新示例数据 'email' => '[email protected]', // 更新示例邮箱 'created_at' => date('Y-m-d H:i:s') // 增加 created_at ]); return response('User added to MySQL'); // 更新响应信息 } catch (\Exception $e) { return response('Error adding user to MySQL: ' . $e->getMessage(), 500); // 增加错误处理 } } /** * 从 MySQL 数据库获取用户列表 * @param Request $request * @return Response */ public function mysqlGet(Request $request): Response { try { // 使用 Db Facade 连接 'mysql' 数据库并获取所有用户 $users = Db::connection('mysql')->table('users')->get(); // 返回 JSON 格式的用户列表 return response(json_encode($users), 200, ['Content-Type' => 'application/json']); // 明确 Content-Type } catch (\Exception $e) { return response('Error getting users from MySQL: ' . $e->getMessage(), 500); // 增加错误处理 } } /** * 向 PostgreSQL 数据库添加用户 * @param Request $request * @return Response */ public function pgsqlAdd(Request $request): Response { try { // 使用 Db Facade 连接 'pgsql' 数据库并插入数据 Db::connection('pgsql')->table('users')->insert([ 'name' => 'ServBay Webman PgSQL User', // 更新示例数据 'email' => '[email protected]', // 更新示例邮箱 'created_at' => date('Y-m-d H:i:s') // 增加 created_at ]); return response('User added to PostgreSQL'); // 更新响应信息 } catch (\Exception $e) { return response('Error adding user to PostgreSQL: ' . $e->getMessage(), 500); // 增加错误处理 } } /** * 从 PostgreSQL 数据库获取用户列表 * @param Request $request * @return Response */ public function pgsqlGet(Request $request): Response { try { // 使用 Db Facade 连接 'pgsql' 数据库并获取所有用户 $users = Db::connection('pgsql')->table('users')->get(); // 返回 JSON 格式的用户列表 return response(json_encode($users), 200, ['Content-Type' => 'application/json']); // 明确 Content-Type } catch (\Exception $e) { return response('Error getting users from PostgreSQL: ' . $e->getMessage(), 500); // 增加错误处理 } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
配置数据库连接
编辑项目根目录下的
config/database.php
文件,配置 MySQL 和 PostgreSQL 的连接信息。ServBay 默认的数据库主机是127.0.0.1
,端口分别是3306
(MySQL) 和5432
(PostgreSQL),root
用户密码是password
。php<?php /** * 数据库配置 */ return [ // 默认使用的数据库连接 'default' => 'mysql', // 数据库连接配置列表 'connections' => [ 'mysql' => [ 'driver' => 'mysql', // ServBay 默认的 MySQL 主机和端口 'host' => '127.0.0.1', 'port' => 3306, // 之前创建的数据库名 'database' => 'webman_app', // ServBay 默认的 MySQL 用户名 'username' => 'root', // ServBay 默认的 MySQL 密码 'password' => 'password', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ], 'pgsql' => [ 'driver' => 'pgsql', // ServBay 默认的 PostgreSQL 主机和端口 'host' => '127.0.0.1', 'port' => 5432, // 之前创建的数据库名 'database' => 'webman_app', // ServBay 默认的 PostgreSQL 用户名 'username' => 'root', // ServBay 默认的 PostgreSQL 密码 'password' => 'password', 'charset' => 'utf8', 'prefix' => '', 'schema' => 'public', 'sslmode' => 'prefer', // 或者 require, verify-ca, verify-full ], // 可以在这里添加更多数据库连接... ], ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46重要提示: 在生产环境中,请务必修改默认的数据库密码,并避免在代码中硬编码敏感信息。
运行 Webman 项目
Webman 项目通常通过其自带的 start.php
脚本启动 Workerman 进程。这与传统的通过 Nginx/Apache + PHP-FPM 运行的方式不同,Webman 是一个常驻内存的异步应用。
在项目根目录 (/Applications/ServBay/www/servbay-webman-app
) 下运行以下命令启动 Webman 项目:
php start.php start
执行此命令后,您会看到 Webman 启动的信息,默认情况下,它会在 127.0.0.1:8787
监听 HTTP 请求。
- 注意: 这里的
php
命令使用的是 ServBay 环境中的 PHP 可执行文件。ServBay 会自动配置您的终端环境,让您可以直接使用 ServBay 安装的 PHP 版本。 - 如果您希望让 Webman 在后台运行,可以使用
-d
参数:php start.php start -d
。 - 要停止 Webman 服务,运行命令:
php start.php stop
。 - 要重启 Webman 服务,运行命令:
php start.php restart
。 - 要平滑重启(不中断当前请求),运行命令:
php start.php reload
。
测试项目
Webman 启动成功并监听 127.0.0.1:8787
后,您可以在浏览器中访问以下 URL 来测试各个功能:
http://localhost:8787/
:您会看到页面输出Hello ServBay & Webman!
。http://localhost:8787/memcached
:您会看到页面输出Hello Memcached from ServBay!
。这表示您已成功通过 Webman 连接并使用了 ServBay 的 Memcached 服务。http://localhost:8787/redis
:您会看到页面输出Hello Redis from ServBay!
。这表示您已成功通过 Webman 连接并使用了 ServBay 的 Redis 服务。http://localhost:8787/mysql-add
:您会看到页面输出User added to MySQL
。这会在之前创建的 MySQL 数据库的users
表中插入一条记录。http://localhost:8787/mysql
:您会看到一个 JSON 格式的输出,其中包含 MySQL 数据库users
表中的用户列表。http://localhost:8787/pgsql-add
:您会看到页面输出User added to PostgreSQL
。这会在之前创建的 PostgreSQL 数据库的users
表中插入一条记录。http://localhost:8787/pgsql
:您会看到一个 JSON 格式的输出,其中包含 PostgreSQL 数据库users
表中的用户列表。
如果您在访问这些 URL 时遇到问题,请检查 Webman 终端输出是否有错误信息,并确认 ServBay 中的 MySQL, PostgreSQL, Redis, Memcached 软件包是否正在运行,以及 PHP 扩展是否已启用。
常见问题 (FAQ)
- Q:
php start.php start
命令无法找到?- A: 确保您已经在终端中
cd
进入了servbay-webman-app
项目目录。同时,确认 ServBay 安装的 PHP 已被正确添加到您的系统 PATH 中(ServBay 通常会自动处理)。
- A: 确保您已经在终端中
- Q: 访问
localhost:8787
提示连接失败?- A: 检查终端中运行
php start.php start
的输出,看是否有错误。确保端口8787
没有被其他程序占用。如果被占用,可以在 Webman 的配置文件中修改监听端口(例如修改config/server.php
)。
- A: 检查终端中运行
- Q: 数据库连接失败?
- A: 确认 ServBay 中的 MySQL 和 PostgreSQL 软件包正在运行。检查
config/database.php
中的连接信息(主机、端口、数据库名、用户名、密码)是否与 ServBay 的配置一致(默认用户root
,密码password
)。确认您已经创建了webman_app
数据库和users
表。
- A: 确认 ServBay 中的 MySQL 和 PostgreSQL 软件包正在运行。检查
- Q: Memcached 或 Redis 连接失败?
- A: 确认 ServBay 中的 Memcached 和 Redis 软件包正在运行。检查
app/controller/CacheController.php
中的连接地址和端口是否正确(默认127.0.0.1:11211
和127.0.0.1:6379
)。确认您所使用的 PHP 版本已启用memcached
和redis
扩展。
- A: 确认 ServBay 中的 Memcached 和 Redis 软件包正在运行。检查
总结
通过以上步骤,您已经成功地在 ServBay 本地开发环境中创建、配置并运行了一个基础的 Webman 项目。您学会了如何利用 ServBay 提供的一站式服务,快速搭建 Webman 的开发环境,并集成了数据库和缓存功能。Webman 的高性能特性结合 ServBay 的便捷性,为您的异步 PHP 应用开发提供了强大的支持。希望本指南能帮助您更好地利用 ServBay 和 Webman 构建出色的 Web 应用。