CodeIgniter 4 环境搭建笔记:WampServer + CI4 跑通 Hello World
刚接触 CodeIgniter 4 的朋友,最容易在第一道坎上卡住——不是说 PHP 有多难,而是框架跑起来的姿势跟老版本差太多了。CI3 时代扔到 www 目录就能跑,CI4 却要处理 public 目录、Composer 依赖、intl 扩展、.env 配置……没经验的话,光看报错就能劝退一大半新手。
我这次把从零开始在 Windows 上搭 CI4 的完整过程记录一下,用的是 WampServer 套件,目标是让一个 Hello World 页面稳定跑起来。这篇适合三类人:刚学 PHP 想直接上框架的、从 CI3 迁到 CI4 的老开发者、以及买了 VPS 想本地先练手的同学。内容会涉及 PHP 版本选择、扩展开关、Composer 安装、项目配置和常见 404 排查,全部都是我实际踩过一遍的步骤,跟着做基本不会翻车。
1. 环境准备:WampServer 与 CI4 的前置条件
1.1 WampServer 是什么,为什么要用它
WampServer 是 Windows 平台上一键集成 Apache、MySQL、PHP 的环境包,装上之后三个核心服务全都有了,省去各自安装配置的痛苦。CI4 其实只需要一个合格的 PHP 环境就能跑,理论上用 php 内置开发服务器也能启动,但用 WampServer 有一个明显的好处:它提供了接近生产环境的 Apache 托管方式,后续学路由、伪静态、虚拟主机配置都在同一套环境里完成,不用来回切换工具。
还有个现实原因——很多新手第一次接触的是集成环境,WampServer 的图形界面可以直观看到 PHP 版本切换和扩展开关状态,排查环境问题比纯命令行友好太多。装好之后系统托盘会出现一个半圆图标,左键点击能看到 Apache、MySQL、PHP 的管理菜单。
1.2 PHP 版本与必须开启的扩展
CI4 官方对 PHP 版本有硬性要求:历史版本要求 7.3+,新版本则建议 8.0 以上。我在实际使用中推荐直接用 PHP 8.1 或 8.2,因为框架后续迭代会越来越依赖 PHP 8 的特性,你现在用老版本,过几个月升级框架就会发现环境跟不上。
WampServer 安装完成后默认可能启用某个 PHP 版本,你可以通过左键托盘图标,选择 PHP -> Version 切换版本。切换后最好等 Apache 服务自动重启,或者手动点击 Restart All Services。
除了版本,扩展开关是更隐蔽的问题。CI4 启动时如果缺少 intl 扩展,会直接报错intl extension is not installed,这一步卡住过很多人。intl 是 ICU 国际化库的 PHP 封装,CI4 内部的文本处理、编码转换、URL 解析都会用到它。WampServer 的扩展管理在左键菜单里选 PHP -> PHP Extensions,勾选 intl 即可,也可以在主面板的 php.ini 里搜索extension=intl取消注释并保存。
注意:修改 php.ini 之后必须重启 Apache,否则配置不会生效。另外开启扩展时注意 PHP 版本要对应,WampServer 每个 PHP 版本都有独立的 php.ini 文件。
mbstring 扩展也是推荐开启的,CI4 在处理多字节字符串时依赖它,尤其是中文内容。虽然现在 mbstring 在多数 Linux 发行版里默认带了,但 Windows 下 WampServer 不一定默认开启同一套扩展组合,检查一下最保险。
1.3 安装 WampServer 的细节
安装包从官方站点下载即可,选择 64 位版本,注意安装路径不要带中文和空格,推荐D:\wamp64。安装过程中可能需要安装 Visual C++ 运行库,按提示确认或等它自动安装,这个缺了会导致 Apache 启动不起来。
安装完成后会提示设置默认浏览器和文本编辑器,可以跳过。启动 WampServer,托盘图标从红色变成橙色再变成绿色,才算服务全部正常。绿色图标亮起之前,前端页面是不可用的。
我遇到过一个非常迷惑的情况:托盘图标显示绿色,但浏览器访问 localhost 仍然打不开。后来发现是系统防火墙拦截了 Apache 的网络通信,安装过程中弹窗时选取消,后面上网就授不到端口。解决办法是防火墙设置里放行 Apache 进程,或者重新安装时选择允许访问。
2. 获取 CodeIgniter 4:两种安装方式对比
2.1 方式一:Composer 安装(推荐)
CI4 官方的安装方式首选 Composer,因为后续升级框架补丁、安装第三方库全靠它管理,比手动下载 ZIP 包方便太多。Windows 上安装 Composer 直接下载安装包,一路下一步就行,但安装过程中如果遇到 PHP 路径识别不了,要先确保 WampServer 的 PHP 已启用。
命令行进入你的站点根目录,执行:
composer create-project codeigniter4/appstarter ci4demo命令的含义是:用 CodeIgniter 4 的启动项目模板创建一个叫 ci4demo 的目录,并自动下载框架核心依赖。如果网络环境导致下载缓慢,可以配置一个国内镜像源,命令格式如下,具体地址以你选择的镜像站官方文档为准:
composer config -g repo.packagist composer https://镜像站域名/composer配置完再执行 create-project 就会快很多。
创建完成后,ci4demo 目录结构是官方标准布局,重点记住这几个:
app/:应用代码,控制器、模型、视图全部在这里public/:唯一对外可见的入口目录,Apache 应该指向这里writable/:缓存、日志、会话文件写入位置.env:环境配置文件(安装后需要从 env 复制)vendor/:Composer 依赖目录
很多新手的第一反应是把项目放到 WampServer 的 www 目录下,然后直接访问http://localhost/ci4demo/,结果看到的是目录列表或者 404。原因就是 CI4 的入口不在项目根目录,而在public子目录里。正确访问地址是http://localhost/ci4demo/public/。
2.2 方式二:ZIP 直接下载
如果不想装 Composer,也可以直接从框架源码仓库下载 ZIP 包,解压后同样是 appstarter 结构。这种方式的好处是快,缺点是后续框架升级你得手动替换文件,而且无法使用代码库托管平台自动拉取依赖。
以我个人的经验,除非你只是临时看一下代码结构,否则还是老老实实用 Composer。就算你项目最终不依赖任何第三方库,Composer 管理框架版本这件事本身就值回安装成本。
2.3 项目放在哪个目录、怎么访问
WampServer 默认站点目录是安装目录下的www文件夹。把项目放在D:\wamp64\www\ci4demo后,访问地址就是http://localhost/ci4demo/public/。
如果想省略 public,可以通过 Apache 虚拟主机把站点根目录指向 public 子目录,或者调整 DocumentRoot。但对于刚起步的学习阶段,我建议先带着 public 用,理解入口文件的概念之后再做精简,否则一轮配置下来,你可能分不清问题出在环境还是路由。
3. 配置与起步:第一个 Hello World
3.1 配置 env 变量:开发环境与 baseURL
CI4 安装后根目录有一个env文件,它本质上是环境配置模板。你需要复制一份并重命名为.env,Windows 下直接在资源管理器重命名可能会碰到隐藏扩展名的问题,我习惯用命令行操作:
copy env .env然后编辑.env,至少要改两处。第一处是环境模式,去掉CI_ENVIRONMENT前的分号注释并设置为 development:
CI_ENVIRONMENT = development这样框架会把错误信息完整显示在页面上,方便调试。生产环境遇到同样配置会暴露潜在安全问题,但现在是本地学习,不追求这个。
第二处是app.baseURL,先找到:
app.baseURL = ''改成你的实际访问地址,比如:
app.baseURL = 'http://localhost:8080/'注意要带结尾斜杠。如果你用的是 Apache 方式访问http://localhost/ci4demo/public/,也可以直接写这个完整地址。baseURL 的作用是让框架在生成链接、重定向时知道主路径,配置错会导致 CSS 加载失败、跳转 404 等一系列连锁问题。
提醒:改了 .env 之后如果没生效,检查三点:文件名是否多了
.txt后缀、保存编码是否为 UTF-8 无 BOM、是否忘记重启 Apache。开发模式下环境变量缓存有时会拖后腿,重启一次解决一切问题。
3.2 启动方式:Apache 访问与 php spark serve
CI4 自带一个开发服务器命令,叫php spark serve,默认监听 8080 端口。使用前需要确保命令行能识别php命令,或者直接用 WampServer 的绝对路径。
例如项目目录下执行:
d:\wamp64\bin\php\php8.1.0\php.exe vendor/bin/spark但每次敲全路径很痛苦,建议把 PHP 目录加到系统 PATH 环境变量里。添加之后,直接:
php spark serve浏览器访问http://localhost:8080。
另一个方式就是走 Apache,浏览器直接访问http://localhost/ci4demo/public/。两种方式的区别在于:Apache 更接近真实部署场景,需要理解入口和伪静态规则;spark serve 适合快速调试,改动代码即时生效,不需要频繁重启服务。
我个人的选择是日常开发用 spark serve,因为启动快、日志在终端里很直观;等到需要模拟真实环境或配置域名绑定的时候再切换到 Apache。
3.3 控制器与视图:从 index 到 hello 函数
默认首页显示的内容来自app/Controllers/Home.php,打开看会发现 Home 控制器下有一个 index 方法,内容就是加载一个欢迎视图。
我们先做一个最简单的修改:直接改 Home 的 index 方法,先摸清整个加载链路。
<?php namespace App\Controllers; class Home extends BaseController { public function index() { return "Hello World from CodeIgniter 4!"; } }保存后刷新页面,如果一切正常,你会在浏览器里看到这串字符串。这证明环境没问题,框架能执行控制器方法了。
但这么直接返回字符串不算正规用法,MVC 模式里控制器应该把数据交给视图去渲染。我建议你新建一个专门的控制器来体验完整流程。
创建app/Controllers/Hello.php:
<?php namespace App\Controllers; class Hello extends BaseController { public function index() { return view('hello'); } }同目录下创建视图文件app/Views/hello.php:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>我的第一个 CI4 页面</title> </head> <body> <h1>Hello, CodeIgniter 4!</h1> <p>如果你看到这行字,说明环境和框架都跑通了。</p> </body> </html>访问http://localhost:8080/hello,或者 Apache 方式访问http://localhost/ci4demo/public/hello,就会看到页面了。
3.4 视图里输出变量:体验数据流
光输出静态 HTML 没什么意思,MVC 的核心在于数据从控制器流向视图。修改 Hello 控制器:
<?php namespace App\Controllers; class Hello extends BaseController { public function index() { $data = [ 'title' => '欢迎', 'message' => '这条消息是从控制器传到视图的', ]; return view('hello', $data); } }修改视图文件,用 PHP 短标签输出数据:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title><?= esc($title) ?></title> </head> <body> <h1><?= esc($message) ?></h1> </body> </html>esc()是 CI4 自带的 HTML 转义函数,所有动态数据输出到页面前都应该包一层它,防止 XSS 注入。这算是写 CI4 之后刻进肌肉记忆的习惯。
4. 路由机制:理解 URL 如何找到你的代码
4.1 默认自动路由的工作流程
访问/hello时,CI4 内部把 URL 拆成了几段,默认情况下第一段是控制器名,第二段是方法名,后面的段是参数。这就是控制器、方法、参数的映射关系。
| URL 片段 | 对应内容 |
|---|---|
| /hello | 控制器 Hello |
| /hello/index | 控制器 Hello 的方法 index |
| /hello/show/1 | 控制器 Hello 的方法 show,参数为 1 |
这种自动映射机制在 CI4 中叫做自动路由,约定优于配置,新手阶段非常友好。你不需要写任何路由规则就能访问新控制器。但你迟早会遇到需要自定义路由的场景——比如想让 URL 变成更友好的人话形式,或者在控制器里对参数做校验。
路由定义集中在app/Config/Routes.php文件里。
4.2 自定义路由:让 Hello World 更实用
光靠自动路由不够用,我演示一个加参数的路由写法。希望访问/hello/名字的时候,页面能打出“你好,某某”。
首先在app/Config/Routes.php的默认规则之前加一行:
$routes->get('hello/(:any)', 'Hello::sayHello/$1');然后在 Hello 控制器里添加方法:
<?php namespace App\Controllers; class Hello extends BaseController { public function index() { return view('hello'); } public function sayHello($name = null) { if ($name === null) { return '请提供参数,例如 /hello/小明'; } return "你好,{$name}!"; } }访问http://localhost:8080/hello/小明,可以看到输出。(:any)是 CI4 路由中的占位符,匹配任意非斜杠字符,捕获到的值作为参数传给$1,再拼进方法调用字符串中。
这个方法对于列表页分页、详情页跳转、搜索关键词传递都很实用,算是 CI4 路由的标配用法。
4.3 为什么容易碰到 404
环境正常但页面 404,大概率是下面几种情况:
- 文件没放在
app/Controllers目录 - 命名空间不是
App\Controllers,或者基础命名空间配置被改过 - 类名大小写不对,CI4 的控制器类名要求跟文件名一致,且首字母大写
- 自动路由被关闭,但访问的 URL 又没在 Routes.php 里定义
- 方法名是私有方法或者以
_开头,框架不允许直接通过 URL 访问
排查顺序建议:先看Routes.php有没有意外改动,再检查控制器的命名空间和类名大小写,最后确认文件名。
5. 常见坑与排查速查
实操过程中遇到的报错,很多不是我上面提到的那几类,而是和环境、扩展、路径相关的。我整理了一个速查表,基本上覆盖了新手第一次启动 CI4 时能遇到的 90% 的问题。
| 症状 | 原因 | 解决办法 |
|---|---|---|
| 页面直接显示 PHP 源代码 | Apache 未启用 PHP 模块,或 PHP 处理程序未关联 | 从托盘菜单检查 Apache -> PHP 模块是否加载,重启服务 |
| 报错 intl extension is not installed | PHP 的 intl 扩展未开启 | WampServer 菜单中勾选 PHP 扩展 intl,重启 Apache |
| 首页是目录列表,看不到页面内容 | 访问了项目根目录而非 public 目录 | 改成访问http://localhost/ci4demo/public/ |
| 修改 .env 不生效 | 文件名错误、有 BOM 头、服务未重启 | 用命令行copy env .env重新生成文件,重启 Apache |
| 访问 /hello 出现 404 | 控制器命名空间不对、文件名大小写错、路由冲突 | 检查命名空间是否为App\Controllers,类名首字母大写 |
| spark serve 命令报“不是内部或外部命令” | PHP 未加入系统 PATH | 将 PHP 目录加入环境变量 PATH,或改用完整路径 |
| 样式加载 404 | baseURL 配置错误,导致资源定位失败 | 修正 .env 中的 app.baseURL,确保以斜杠结尾 |
| 页面显示错误但不详细 | CI_ENVIRONMENT 不是 development 或未开启 display_errors | .env 设置CI_ENVIRONMENT = development,重启 |
还有一个容易忽略的细节:Windows 下如果你用记事本编辑.env和 PHP 文件,保存时默认编码可能是 UTF-8 带 BOM,BOM 会让框架在输出 HTML 前输出看不见的字符,导致 API 返回 json 数据时解析失败。我的习惯是编辑器统一设置 UTF-8 无 BOM,或者用专业编辑器打开文件。
另外,CI4 的缓存机制在调试时很反直觉。如果你改了控制器或路由但页面没变化,先确认writable/cache目录中没有旧缓存文件,开发模式下执行一遍php spark clear命令可以清理缓存。
6. 目录结构重点与下一步学习路线
6.1 从 Hello 到实用:熟悉 app 目录
跑通 Hello World 只是第一步,接下来写真实应用,你离不开app目录下的几个核心子目录。我把常用目录的作用列出来:
| 目录 | 作用 |
|---|---|
| app/Config | 全局配置,路由、数据库、缓存、邮箱等都在这里 |
| app/Controllers | 控制器,接收请求、调用业务逻辑 |
| app/Models | 模型,和数据表打交道 |
| app/Views | 视图,前端模板文件 |
| app/Helpers | 自定义辅助函数 |
| app/Filters | 过滤器,用于请求前后拦截处理 |
| app/Database | 数据库迁移和种子数据文件 |
新手最容易犯的错误是把业务逻辑全塞进控制器,视图里又写一堆 SQL。CI4 的模板引擎和数据库查询构造器都做得比较完善,建议从一开始就养成控制器调模型、模型查数据库、控制器传数据给视图的习惯。
6.2 下一步:连接 MySQL 做持久化
既然装的是 WampServer,MySQL 已经在手边了。下一阶段可以从数据模型入手,创建一张数据表,用 CI4 的查询构造器读写数据,再通过表单把数据写进去、在列表页展示出来。这一步能串起 MVC 的完整链路,也算真正入门 PHP 框架开发。
我自己最开始学 CI4 的时候,就是跳过数据库直接学认证和缓存,结果回头补模型层时浪费了不少时间。建议按顺序来:环境 -> 路由 -> 控制器 -> 视图 -> 模型 -> 数据库,每一步都跑通再往下走,稳扎稳打。
最后再分享一个小技巧:如果你用 spark serve 启动开发服务器,可以加--host参数指定监听地址,比如php spark serve --host 192.168.1.100,这样同一局域网里的其他设备也能访问你的项目,方便联调。不过仅限本地局域网调试,别暴露到公网,安全问题不是一句两句能说清楚的。