重要声明:Zend Framework 2 已过时
在开始之前,必须强调:Zend Framework 2 是一个非常古老的版本,于 2025 年发布,官方已于 2025 年停止支持。

这意味着:
- 没有官方支持:您无法从 Zend 获得帮助。
- 存在严重安全漏洞:旧版本可能包含未修复的安全问题,绝对不应该用于任何生产环境。
- 与现代 PHP 不兼容:它使用的是 PHP 5.3+ 的语法和特性,与现代 PHP 7/8/8.x 的最佳实践和语法相去甚远。
- 社区已死:相关的博客、文章和讨论都已过时,很难找到有效的解决方案。
学习 ZF2 的目的:
- 维护一个非常古老的项目。
- 出于历史学习目的,了解 PHP 框架的演变史。
对于任何新项目,您应该学习 Zend Framework 3 或更新的 Laminas Project (ZF3 之后,社区接管并更名为 Laminas)。
Zend Framework 2 核心概念入门
ZF2 的核心思想是 "微内核" 和 "高度模块化",这与现在流行的 "全栈框架" (如 Laravel, Symfony) 有很大不同。

核心概念
- MVC (Model-View-Controller):这是 ZF2 的基础架构。
- Model (模型):处理数据和业务逻辑,通常与数据库交互。
- View (视图):负责数据展示,通常是 HTML 模板。
- Controller (控制器):接收用户请求,调用 Model 处理数据,然后选择一个 View 进行渲染。
- 模块化:ZF2 应用程序被组织成多个独立的模块,每个模块都可以有自己的 MVC 结构、配置、资源等,这使得代码复用和大型团队协作变得容易。
- 服务管理器:这是 ZF2 的 心脏,它是一个依赖注入容器,当你需要某个对象(例如数据库连接、邮件服务)时,你不需要自己
new它,而是向服务管理器请求,它会帮你创建、配置并管理这些对象的生命周期。 - 事件管理器:ZF2 是一个事件驱动的框架,应用程序的许多生命周期(如路由、分发、渲染)都可以通过监听和响应事件来扩展,你可以在渲染页面前修改数据。
- 路由与分派:URL 请求首先被 路由 匹配,确定哪个控制器和哪个动作(方法)来处理。分派 器会调用该控制器的方法。
环境准备
- PHP:ZF2 需要 PHP 5.3.23 或更高版本,推荐使用 PHP 5.6 以获得更好的兼容性。
- 安装 PHP 并确保
php命令可用。 - 安装必要的扩展:
php-cli,php-mbstring,php-xml,php-zip等。
- 安装 PHP 并确保
- Web 服务器:Apache 或 Nginx。
- 确保服务器配置了
mod_rewrite(Apache) 或类似功能 (Nginx)。 - 将网站根目录指向
public文件夹。
- 确保服务器配置了
- Composer:PHP 的依赖管理工具。
- 从 getcomposer.org 下载并安装 Composer。
第一步:创建项目
ZF2 项目通常使用 Composer 的 zendframework/skeleton-application 来创建。
# 1. 创建项目目录 mkdir my-zf2-app cd my-zf2-app # 2. 使用 Composer 创建骨架应用 # 这会下载最基本的项目结构 composer create-project zendframework/skeleton-application . --stability="dev"
创建完成后,你会看到一个类似下面的目录结构:
my-zf2-app/
├── composer.json # 项目依赖和脚本配置
├── composer.lock # 锁定具体版本
├── config/ # 全局配置目录
│ ├── application.config.php # 应用程序的主配置文件
│ └── module.config.php # 模块配置
├── module/ # 模块目录
│ └── Application/ # 默认的 Application 模块
│ ├── config/
│ ├── src/
│ │ ├── Controller/
│ │ ├── Model/
│ │ └── Module.php # 模块的入口文件
│ ├── view/
│ │ └── application/
│ └── ...
├── public/ # Web 服务器访问的根目录
│ ├── .htaccess # Apache 重写规则
│ ├── index.php # 应用程序的入口文件
│ └── ... (如 robots.txt)
├── vendor/ # Composer 下载的依赖库
└── ... (其他文件)
第二步:Hello, World!
让我们修改默认的首页来显示 "Hello, ZF2!"。
-
找到控制器: 打开
module/Application/src/Application/Controller/IndexController.php。
(图片来源网络,侵删) -
修改控制器方法: 找到
indexAction方法,并修改它。// module/Application/src/Application/Controller/IndexController.php namespace Application\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; class IndexController extends AbstractActionController { public function indexAction() { // 创建一个 ViewModel 并传递一个变量 $view = new ViewModel(); $view->setVariable('message', 'Hello, ZF2!'); return $view; } } -
修改视图: 打开
module/Application/view/application/index/index.phtml。<!-- module/Application/view/application/index/index.phtml --> <?php // $this 是一个 ViewModel 实例,我们可以通过它获取变量 $message = $this->message; ?> <h1><?php echo $this->escapeHtml($message); ?></h1> <p>Welcome to Zend Framework 2!</p>
-
运行项目:
- 如果你使用 PHP 内置服务器,在项目根目录下运行:
php -S localhost:8080 -t public/
- 然后在浏览器中访问
http://localhost:8080,你应该能看到 "Hello, ZF2!"。
- 如果你使用 PHP 内置服务器,在项目根目录下运行:
第三步:创建一个自定义模块
这是 ZF2 的核心,我们来创建一个名为 "Blog" 的模块来展示文章列表。
-
创建模块目录结构: 在
module目录下创建Blog目录,并创建以下子目录和文件:module/ └── Blog/ ├── config/ │ └── module.config.php # 模块的配置 ├── src/ │ └── Blog/ │ ├── Controller/ │ │ └── IndexController.php # 控制器 │ ├── Module.php # 模块入口 │ └── ... ├── view/ │ └── blog/ │ └── index/ │ └── index.phtml # 视图 └── composer.json # (可选,但推荐) -
创建
Module.php: 这是模块的入口,告诉 ZF2 这个模块的存在。// module/Blog/src/Blog/Module.php namespace Blog; class Module { public function getAutoloaderConfig() { return array( 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), ), ); } public function getConfig() { return include __DIR__ . '/config/module.config.php'; } } -
创建模块配置
module.config.php: 这个文件定义了路由、控制器映射、视图管理器等。// module/Blog/config/module.config.php return array( 'router' => array( 'routes' => array( 'blog' => array( 'type' => 'segment', 'options' => array( 'route' => '/blog[/:action][/:id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Blog\Controller\Index', 'action' => 'index', ), ), ), ), ), 'controllers' => array( 'invokables' => array(
