- Zend 框架教程
- Zend 框架 - 主页
- Zend 框架 - 简介
- Zend 框架 - 安装
- 骨架应用
- Zend 框架 - MVC 架构
- Zend 框架 - 概念
- Zend 框架 - 服务管理器
- Zend 框架 - 事件管理器
- Zend 框架 - 模块系统
- 应用结构
- Zend 框架 - 创建模块
- Zend 框架 - 控制器
- Zend 框架 - 路由
- Zend 框架 - 视图层
- Zend 框架 - 布局
- 模型和数据库
- 不同的数据库
- 表格和验证
- Zend 框架 - 文件上传
- Zend 框架 - Ajax
- Cookie 管理
- 会话管理
- Zend 框架 - 身份验证
- 电子邮件管理
- Zend 框架 - 单元测试
- Zend 框架 - 错误处理
- Zend 框架 - 工作示例
- Zend 框架有用的资源
- Zend 框架 - 快速指南
- Zend 框架 - 有用的资源
- Zend 框架 - 讨论
Zend 框架 - 快速指南
Zend 框架 - 简介
PHP Web 框架是有助于开发 Web 应用程序的类的集合。Zend 是最流行的 PHP 框架之一。它是一个开源 MVC 框架,用于快速开发的现代 Web 应用程序。Zend Framework 有几个松散耦合的组件,因此被称为“组件库”。Zend Framework 提供任何 PHP 堆栈和 Zend 服务器来运行 Zend 框架应用程序。
Zend Studio 是一个 IDE,包含与 Zend Framework 集成的功能。它提供 MVC 视图和代码生成。当前的 Zend 框架 3.0 包含新组件,例如 JSON RPC 服务器、XML 到 JSON 转换器、PSR-7 功能以及与 PHP 7 的兼容性。
Zend Framework 2 是一个开源框架,用于使用 PHP 5.3+ 开发 Web 应用程序和服务。Zend Framework 2 使用 100% 面向对象的代码,并利用 PHP 5.3 的大部分新功能,即命名空间、Lambda 函数和闭包。
Zend Framework 2 从 Zend Framework 1 发展而来,Zend Framework 1 是一个成功的 PHP 框架,下载量超过 1500 万次。Zend Server 有免费社区版本和商业版本。
Zend 框架功能
Zend Framework 的一些显着特征如下 -
- 纯面向对象的Web应用程序框架
- 高级 MVC 实施
- 支持多种数据库,包括PostgreSQL、SQLite等,
- 简单的云API
- 会话管理
- 数据加密
- 灵活的 URI 路由
- Zend 提供 RESTful API 开发支持。
- 代码可重用且更易于维护。
为什么选择 Zend 框架?
Zend Framework 之所以成为 PHP 开发人员使用的首要框架之一,是因为它提供了干净、稳定且具有知识产权的代码。它还使编程变得更容易。它是快速、易学且方便的框架。Zend 支持强大的加密工具和密码散列技术。
Zend 目标
以下是 Zend 框架的目标。
- 灵活性
- 简单而高效
- 兼容性
- 可扩展性- 程序员可以轻松扩展所有框架类。
- 可移植性 - 支持多种环境
Zend 应用程序
以下流行产品都是使用 Zend Framework 开发的。
- 迈克菲公司网站
- IBM公司网站
- Magento - 流行的购物车网站之一。
Zend框架的优点
下面列出了 Zend Framework 的一些优点。
松散耦合- Zend 提供了删除应用程序中不需要的模块或组件的选项。
性能- Zend Framework 针对性能进行了高度优化。Zend Framework 3 比之前的版本快 4 倍。
安全性- 框架支持行业标准加密。
测试- PHPUnit 与 Zend 集成,因此您可以轻松测试框架。
在下一章中,我们将学习如何安装 Zend Framework。
Zend 框架 - 安装
要安装 Zend Framework,我们必须首先安装 Composer 和最新版本的 PHP,如以下步骤所示。
安装 Composer - Zend 使用 Composer 来管理其依赖项,因此请确保您的计算机上安装了 Composer。如果没有安装Composer,则访问Composer官网并安装。
安装最新版本的 PHP - 要获得 Zend Framework 的最大优势,请安装最新版本的 PHP。Zend Framework 3 所需的最低版本是 PHP 5.6 或更高版本。
安装 Zend 框架
Zend Framework 可以通过两种方式安装。它们如下 -
- 手动安装
- 基于 Composer 的安装
让我们详细讨论这两种安装。
手动安装
通过访问以下链接下载最新版本的 Zend Framework – https://framework.zend.com/downloads/archives
将下载的存档文件的内容提取到您想要保留的文件夹中。一旦您的本地计算机上有了可用的 Zend Framework 副本,基于 Zend Framework 的 Web 应用程序就可以访问框架类。尽管有多种方法可以实现此目的,但您的 PHP include_path需要包含发行版中 /library 目录下 Zend Framework 类的路径。此方法仅适用于 Zend Framework 2.4 版及更早版本。
基于 Composer 的安装
要轻松安装 Zend Framework,请使用 Composer 工具。这是安装最新版本 Zend Framework 的首选方法。要安装 Zend Framework 的所有组件,请使用以下 Composer 命令 -
$ composer require zendframework/zendframework
每个 Zend Framework 模块/组件也可以单独安装。例如,要安装Zend Framework 的MVC 组件,请使用以下Composer命令 -
$ composer require zendframework/zend-mvc
Zend 框架 - 骨架应用程序
让我们使用 Zend Framework MVC 层和模块系统创建一个框架应用程序。
使用 Composer 安装
创建新 Zend Framework 项目的最简单方法是使用 Composer。它的定义如下 -
$ cd /path/to/install $ composer create-project -n -sdev zendframework/skeleton-application myapp
您将在屏幕上看到以下结果 -
Installing zendframework/skeleton-application (dev-master 941da45b407e4f09e264f000fb537928badb96ed) - Installing zendframework/skeleton-application (dev-master master) Cloning master Created project in myapp Loading composer repositories with package information Installing dependencies (including require-dev) from lock file - Installing zendframework/zend-component-installer (0.3.0) Loading from cache - Installing zendframework/zend-stdlib (3.0.1) Loading from cache - Installing zendframework/zend-config (2.6.0) Loading from cache - Installing zendframework/zend-loader (2.5.1) Loading from cache - Installing zendframework/zend-eventmanager (3.0.1) Loading from cache - Installing zendframework/zend-view (2.8.0) Loading from cache - Installing container-interop/container-interop (1.1.0) Loading from cache - Installing zendframework/zend-servicemanager (3.1.0) Loading from cache - Installing zendframework/zend-validator (2.8.1) Loading from cache - Installing zendframework/zend-escaper (2.5.1) Loading from cache - Installing zendframework/zend-uri (2.5.2) Loading from cache - Installing zendframework/zend-http (2.5.4) Loading from cache - Installing zendframework/zend-router (3.0.2) Loading from cache - Installing zendframework/zend-modulemanager (2.7.2) Loading from cache - Installing zendframework/zend-mvc (3.0.1) Loading from cache - Installing zendframework/zend-skeleton-installer (0.1.3) Loading from cache - Installing zfcampus/zf-development-mode (3.0.0) Loading from cache zendframework/zend-config suggests installing zendframework/zend-filter (Zend\Filter component) zendframework/zend-config suggests installing zendframework/zend-i18n (Zend\I18n component) zendframework/zend-config suggests installing zendframework/zend-json (Zend\Json to use the Json reader or writer classes) zendframework/zend-view suggests installing zendframework/zend-authentication (Zend\Authentication component) zendframework/zend-view suggests installing zendframework/zend-feed (Zend\Feed component) zendframework/zend-view suggests installing zendframework/zend-filter (Zend\Filter component) zendframework/zend-view suggests installing zendframework/zend-i18n (Zend\I18n component) zendframework/zend-view suggests installing zendframework/zend-json (Zend\Json component) zendframework/zend-view suggests installing zendframework/zend-navigation (Zend\Navigation component) zendframework/zend-view suggests installing zendframework/zend-paginator (Zend\Paginator component) zendframework/zend-view suggests installing zendframework/zend-permissions-acl (Zend\Permissions\Acl component) zendframework/zend-servicemanager suggests installing ocramius/proxy-manager (ProxyManager 1.* to handle lazy initialization of services) zendframework/zend-validator suggests installing zendframework/zend-db (Zend\Db component) zendframework/zend-validator suggests installing zendframework/zend-filter (Zend\Filter component, required by the Digits validator) zendframework/zend-validator suggests installing zendframework/zend-i18n (Zend\I18n component to allow translation of validation error messages as well as to use the various Date validators) zendframework/zend-validator suggests installing zendframework/zend-i18nresources (Translations of validator messages) zendframework/zend-validator suggests installing zendframework/zend-math (Zend\Math component) zendframework/zend-validator suggests installing zendframework/zend-session (Zend\Session component) zendframework/zend-router suggests installing zendframework/zend-i18n (^2.6, if defining translatable HTTP path segments) zendframework/zend-modulemanager suggests installing zendframework/zend-console (Zend\Console component) zendframework/zend-mvc suggests installing zendframework/zend-json ((^2.6.1 || ^3.0) To auto-deserialize JSON body content in AbstractRestfulController extensions, when json_decode is unavailable) zendframework/zend-mvc suggests installing zendframework/zend-mvc-console (zend-mvc-console provides the ability to expose zend-mvc as a console application) zendframework/zend-mvc suggests installing zendframework/zend-mvc-i18n (zendmvc-i18n provides integration with zend-i18n, including a translation bridge and translatable route segments) zendframework/zend-mvc suggests installing zendframework/zend-mvc-pluginfileprg (To provide Post/Redirect/Get functionality around forms that container file uploads) zendframework/zend-mvc suggests installing zendframework/zend-mvc-pluginflashmessenger (To provide flash messaging capabilities between requests) zendframework/zend-mvc suggests installing zendframework/zend-mvc-pluginidentity (To access the authenticated identity (per zend-authentication) in controllers) zendframework/zend-mvc suggests installing zendframework/zend-mvc-plugin-prg (To provide Post/Redirect/Get functionality within controllers) zendframework/zend-mvc suggests installing zendframework/zend-psr7bridge ((^0.2) To consume PSR-7 middleware within the MVC workflow) zendframework/zend-mvc suggests installing zendframework/zend-servicemanager-di (zend-servicemanager-di provides utilities for integrating zend-di and zendservicemanager in your zend-mvc application) Generating autoload files Removing optional packages from composer.json Updating composer.json Removing zendframework/zend-skeleton-installer... - Removing zendframework/zend-skeleton-installer (0.1.3) Removed plugin zendframework/zend-skeleton-installer. Removing from composer.json Complete! > zf-development-mode enable You are now in development mode.
现在应用程序已安装,您可以立即使用PHP 的内置 Web 服务器对其进行测试-
$ cd path/to/install/myapp $ composer serve
然后你会看到以下响应 -
> php -S 0.0.0.0:8080 -t public/ public/index.php
这将在端口 8080 上启动 PHP 内置 CLI 服务器。开发服务器启动后,您可以访问(http://localhost:8080/)站点。内置 CLI 服务器仅用于开发。
单元测试
要运行框架单元测试,请在终端中键入以下命令。
$ composer require --dev zendframework/zend-test
它将产生以下响应 -
Using version ^3.0 for zendframework/zend-test ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing zendframework/zend-dom (2.6.0) Loading from cache - Installing zendframework/zend-console (2.6.0) Loading from cache - Installing sebastian/version (2.0.1) Loading from cache - Installing symfony/yaml (v3.2.1) Downloading: 100% - Installing sebastian/resource-operations (1.0.0) Loading from cache - Installing sebastian/recursion-context (2.0.0) Loading from cache - Installing sebastian/object-enumerator (2.0.0) Loading from cache - Installing sebastian/global-state (1.1.1) Loading from cache - Installing sebastian/exporter (2.0.0) Loading from cache - Installing sebastian/environment (2.0.0) Loading from cache - Installing sebastian/diff (1.4.1) Loading from cache - Installing sebastian/comparator (1.2.2) Loading from cache - Installing phpunit/php-text-template (1.2.1) Loading from cache - Installing doctrine/instantiator (1.0.5) Loading from cache - Installing phpunit/phpunit-mock-objects (3.4.3) Downloading: 100% - Installing phpunit/php-timer (1.0.8) Loading from cache - Installing phpunit/php-file-iterator (1.4.2) Loading from cache - Installing sebastian/code-unit-reverse-lookup (1.0.0) Loading from cache - Installing phpunit/php-token-stream (1.4.9) Loading from cache - Installing phpunit/php-code-coverage (4.0.4) Downloading: 100% - Installing webmozart/assert (1.2.0) Loading from cache - Installing phpdocumentor/reflection-common (1.0) Loading from cache - Installing phpdocumentor/type-resolver (0.2.1) Loading from cache - Installing phpdocumentor/reflection-docblock (3.1.1) Loading from cache - Installing phpspec/prophecy (v1.6.2) Loading from cache - Installing myclabs/deep-copy (1.5.5) Loading from cache - Installing phpunit/phpunit (5.7.4) Downloading: 100% - Installing zendframework/zend-test (3.0.2) Loading from cache zendframework/zend-console suggests installing zendframework/zend-filter (To support DefaultRouteMatcher usage) symfony/yaml suggests installing symfony/console (For validating YAML files using the lint command) sebastian/global-state suggests installing ext-uopz (*) phpunit/phpunit-mock-objects suggests installing ext-soap (*) phpunit/php-code-coverage suggests installing ext-xdebug (>=2.4.0) phpunit/phpunit suggests installing phpunit/php-invoker (~1.1) phpunit/phpunit suggests installing ext-xdebug (*) zendframework/zend-test suggests installing zendframework/zend-mvc-console (^1.1.8, to test MVC <-> console integration) Writing lock file Generating autoload files
现在测试支持已启用,因此您可以使用以下命令运行测试。
$ ./vendor/bin/phpunit
阿帕奇网络服务器
在生产环境中托管基于 Zend Framework 的应用程序非常简单且直接。只需在 Apache 配置文件中创建一个VirtualHost并将DocumentRoot指向Zend Framework 应用程序的Public文件夹即可。
下面给出了示例配置(myapp) -
<VirtualHost *:80> ServerName myapp.localhost DocumentRoot /path/to/install/myapp/public <Directory /path/to/install/myapp/public> DirectoryIndex index.php AllowOverride All Order allow,deny Allow from all <IfModule mod_authz_core.c> Require all granted </IfModule> </Directory> </VirtualHost>
Zend 框架 - MVC 架构
在继续本章之前,让我们先简单了解一下MVC。模型视图控制器是一种将应用程序逻辑与表示分离的软件方法。实际上,它允许网页包含最少的 PHP 脚本,因为演示文稿与其分开。
MVC组件的简短描述如下
模型- 模型代表应用程序数据的结构。通常,模型类包含有助于检索、插入和更新后端数据库(MySQL、PostgreSQL 等)中的业务数据的函数。
视图- 视图是 MVC 应用程序的表示层。它通过控制器获取模型数据并根据需要显示。它与控制器和模型松耦合,因此可以更改它而不影响模型和控制器。
控制器- 控制器是 MVC 架构的主要组件。每个请求首先到达控制器。换句话说,控制器处理所有请求,并充当模型、视图以及处理 HTTP 请求和生成响应所需的任何其他资源之间的中介。
在下一章中,我们将了解 Zend Framework 的不同概念。
Zend 框架 - 概念
Zend Framework 是 60 多个组件的集合。它们彼此之间的联系是松散的。它们既可以用作独立组件,也可以用作作为单个单元工作的一组组件。
Zend Framework 提供了三个最重要的组件,它们是 -
- zend 服务管理器
- zend-eventmanager 和
- zend-模块管理器。
它们为 Zend 组件提供了与其他组件高效集成的能力。
事件管理器- 它提供了创建基于事件的编程的能力。这有助于创建、注入和管理新事件。
服务管理器- 它使您能够轻松地从任何地方使用任何服务(PHP 类)。
模块管理器- 能够将具有类似功能的 PHP 类集合转换为称为模块的单个单元。新创建的模块可以作为一个单元来使用、维护和配置。
我们将在后续章节中详细介绍这些概念。
Zend 框架 - 服务管理器
Zend Framework 包含一个强大的服务定位器模式实现,称为zend-servicemanager。Zend 框架广泛使用服务管理器来实现其所有功能。服务管理器为 Zend Framework 提供了高级抽象。它还与 Zend Framework 的所有其他组件完美集成。
安装服务管理器
可以使用Composer工具安装 Service Manager 组件。
composer require zendframework/zend-servicemanager
例子
首先,所有的服务都需要注册到服务管理器中。一旦服务注册到服务器管理系统中,就可以随时轻松访问。服务管理器提供了很多注册服务的选项。一个简单的例子如下 -
use Zend\ServiceManager\ServiceManager; use Zend\ServiceManager\Factory\InvokableFactory; use stdClass; $serviceManager = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class,], ]);
上面的代码使用Factory选项将stdClass注册到系统中。现在,我们可以随时使用服务管理器的get()方法获取 stdClass 的实例,如下所示。
use Zend\ServiceManager\ServiceManager; $object = $serviceManager->get(stdClass::class);
get() 方法共享检索到的对象,因此多次调用 get() 方法返回的对象是同一个实例。为了每次获得不同的实例,服务管理器提供了另一种方法,即build()方法。
use Zend\ServiceManager\ServiceManager; $a = $serviceManager->build(stdClass::class); $b = $serviceManager->build(stdClass::class);
服务经理注册
服务管理器提供了一组注册组件的方法。一些最重要的方法如下 -
- 工厂方法
- 抽象工厂方法
- 初始化方法
- 委托者工厂方法
我们将在接下来的章节中详细讨论其中的每一个。
工厂方法
工厂基本上是任何可调用的或任何实现FactoryInterface (Zend\ServiceManager\Factory\FactoryInterface) 的类。
FactoryInterface 有一个方法 -
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
FactoryInterface 的参数详细信息如下 -
容器 (ContainerInterface) - 它是 ServiceManager 的基本接口。它提供了获取其他服务的选项。
requestName - 这是服务名称。
options - 它提供了服务所需的附加选项。
让我们创建一个实现 FactoryInterface 的简单类,并看看如何注册该类。
类测试 - 要检索的对象
use stdClass; class Test { public function __construct(stdClass $sc) { // use $sc } }
Test类取决于 stdClass 。
Class TestFactory - 初始化测试对象的类
class TestFactory implements FactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $dep = $container->get(stdClass::class); return new Test($dep); } }
TestFactory 使用容器来检索 stdClass、创建 Test 类的实例并返回它。
Zend框架的注册和使用
现在让我们了解如何注册和使用 Zend Framework。
serviceManager $sc = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class, Test::class => TestFactory::class] ]); $test = $sc->get(Test::class);
服务管理器提供了一个名为InvokableFactory的特殊工厂来检索任何没有依赖关系的类。例如,可以使用 InvokableFactory 配置stdClass ,因为 stdClass 不依赖于任何其他类。
serviceManager $sc = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class] ]); $stdC = $sc->get(stdClass::class);
在不实现FactoryInterface或使用InvokableFactory 的情况下检索对象的另一种方法是使用内联方法,如下所示。
$serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class, Test::class => function(ContainerInterface $container, $requestedName) { $dep = $container->get(stdClass::class); return new Test($dep); }, ], ]);
抽象工厂方法
有时,我们可能需要创建对象,而我们只有在运行时才知道这些对象。这种情况可以使用AbstractFactoryInterface来处理,它派生自 FactoryInterface。
AbstractFactoryInterface 定义了一个方法来检查是否可以在请求的实例上创建对象。如果可以创建对象,它将使用FactoryInterface 的__invoke 方法创建对象并返回它。
AbstractFactoryInterface 的签名如下 -
public function canCreate(ContainerInterface $container, $requestedName)
初始化方法
初始化方法是一个特殊选项,用于为已创建的服务注入额外的依赖项。它实现了InitializerInterface,唯一可用方法的签名如下 -
public function(ContainerInterface $container, $instance) function(ContainerInterface $container, $instance) { if (! $instance instanceof EventManagerAwareInterface) { return; } $instance->setEventManager($container->get(EventManager::class)); }
在上面的示例中,该方法检查实例是否属于 EventManagerAwareInterface 类型。如果它是EventManagerAwareInterface类型,则设置事件管理器对象,否则不设置。由于该方法可能会也可能不会设置依赖关系,因此它不可靠并且会产生许多运行时问题。
委托工厂方法
Zend Framework 通过DelegatorFactoryInterface支持委托者模式。它可以用来装饰服务。
该函数的签名如下 -
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null );
这里,$callback负责装饰服务实例。
懒惰服务
惰性服务是在创建时不会完全初始化的服务之一。它们只是被引用,并且仅在真正需要时才被初始化。最好的例子之一是数据库连接,但可能并非所有地方都需要它。它是一种昂贵的资源,并且创建过程非常耗时。Zend 框架提供了从DelegatorFactoryInterface派生的LazyServiceFactory,它可以借助Delegator概念和第三方代理管理器(称为ocramius 代理管理器)来生成惰性服务。
插件管理器
插件管理器扩展了服务管理器并提供了附加功能,例如实例验证。Zend Framework 广泛使用插件管理器。
例如,所有验证服务都位于ValidationPluginManager下。
配置选项
服务管理器提供了一些选项来扩展服务管理器的功能。它们是共享的、共享的默认值和别名。正如我们之前讨论的,默认情况下,检索到的对象在请求的对象之间共享,我们可以使用build()方法来获取不同的对象。我们还可以使用共享选项来指定要共享的服务。shared_by_default与共享功能相同,只是它适用于所有服务。
$serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class ], 'shared' => [ stdClass::class => false // will not be shared ], 'shared_by_default' => false, // will not be shared and applies to all service ]);
别名选项可用于为注册服务提供替代名称。这既有优点也有缺点。从积极的一面来看,我们可以为服务提供替代的短名称。但与此同时,该名称可能会脱离上下文并引入错误。
aliases' => ['std' => stdClass::class, 'standard' => 'std']
Zend 框架 - 事件管理器
所有现代应用程序都需要可靠且灵活的事件组件。Zend Framework 提供了一个这样的组件:zend-eventmanager。zend-eventmanager 有助于设计高级架构并支持主题/观察者模式和面向方面的编程。
安装事件管理器
可以使用Composer安装事件管理器,如下所示 -
composer require zendframework/zend-eventmanager
事件管理器的概念
事件管理器的核心概念如下 -
事件- 事件是任意命名的操作,例如greet。
Listener - 任何 PHP 回调。它们附加到事件并在事件触发时被调用。监听器的默认签名是 -
function(EventInterface $e)
EventInterface 类- 用于指定事件本身。它具有设置和获取事件信息的方法,如名称 (set/getName)、目标 (get/setTarget) 和参数 (get/setParams)。
EventManager 类- EventManager 的实例跟踪应用程序中所有定义的事件及其相应的侦听器。EventManager 提供了一个方法Attach将侦听器附加到事件,它提供了一个方法trigger来触发任何预定义的事件。一旦调用触发器,EventManager 就会调用附加到它的侦听器。
EventManagerAwareInterface - 对于支持基于事件的编程的类,它需要实现 EventManagerAwareInterface。它提供了两个方法,setEventManager和getEventManager来获取和设置事件管理器。
例子
让我们编写一个简单的 PHP 控制台应用程序来理解事件管理器的概念。请按照下面给出的步骤操作。
创建一个文件夹“eventapp”。
使用 Composer安装zend-eventmanager 。
在“eventapp”文件夹中创建一个 PHP 文件Greeter.php 。
创建类Greeter并实现EventManagerAwareInterface。
require __DIR__ . '/vendor/autoload.php'; class Greeter implements EventManagerAwareInterface { // code }
这里,require用于自动加载所有 Composer 安装的组件。
在类Greeter中编写setEventManager方法,如下所示 -
public function setEventManager(EventManagerInterface $events) { $events->setIdentifiers([ __CLASS__, get_called_class(),]); $this->events = $events; return $this; }
此方法将当前类设置到给定的事件管理器($events 参数)中,然后在局部变量$events中设置事件管理器。
下一步是在Greeter类中编写getEventManager方法,如下所示 -
public function getEventManager() { if (null === $this->events) { $this->setEventManager(new EventManager()); } return $this->events; }
该方法从局部变量获取事件管理器。如果不可用,则创建事件管理器的实例并返回它。
在Greeter类中编写一个方法greet。
public function greet($message) { printf("\"%s\" from class\n", $message); $this->getEventManager()->trigger(__FUNCTION__, $this, $message ]); }
此方法获取事件管理器并触发/触发附加到它的事件。
下一步是创建Greeter类的实例并将侦听器附加到其方法greet。
$greeter = new Greeter(); $greeter->getEventManager()->attach('greet', function($e) { $event_name = $e->getName(); $target_name = get_class($e->getTarget()); $params_json = json_encode($e->getParams()); printf("\"%s\" event of class \"%s\" is called." . " The parameter supplied is %s\n", $event_name, $target_name, $params_json); });
侦听器回调仅打印事件名称、目标和提供的参数。
Greeter.php的完整列表如下 -
<?php require __DIR__ . '/vendor/autoload.php'; use Zend\EventManager\EventManagerInterface; use Zend\EventManager\EventManager; use Zend\EventManager\EventManagerAwareInterface; class Greeter implements EventManagerAwareInterface { protected $events; public function setEventManager(EventManagerInterface $events) { $events->setIdentifiers([__CLASS__, get_called_class(), ]); $this->events = $events; return $this; } public function getEventManager() { if (null === $this->events) { $this->setEventManager(new EventManager()); } return $this->events; } public function greet($message) { printf("\"%s\" from class\n", $message); $this->getEventManager()->trigger(__FUNCTION__, $this, [$message ]); } } $greeter = new Greeter(); $greeter->greet("Hello"); $greeter->getEventManager()->attach('greet', function($e) { $event_name = $e->getName(); $target_name = get_class($e->getTarget()); $params_json = json_encode($e->getParams()); printf("\"%s\" event of class \"%s\" is called." . " The parameter supplied is %s\n", $event_name, $target_name, $params_json); }); $greeter->greet("Hello");
现在,在命令提示符 php Greeter.php中运行应用程序,结果如下 -
"Hello" from class "Hello" from class "greet" event of class "Greeter" is called. The parameter supplied is ["Hello"]
上面的示例应用程序仅解释了事件管理器的基础知识。事件管理器提供了许多更高级的选项,例如侦听器优先级、自定义回调原型/签名、短路等。事件管理器在 Zend MVC 框架中广泛使用。
Zend 框架 - 模块系统
Zend Framework 提供了强大的模块系统。该模块系统由三个组件组成。它们如下 -
模块自动加载器- 模块自动加载器负责从各种来源定位和加载模块。它也可以加载打包为Phar 档案的模块。Module Autoloader 的实现位于 myapp/vendor/zendframework/zend-loader/src/ModuleAutoloader.php。
模块管理器- 一旦模块自动加载器找到模块,模块管理器就会为每个模块触发一系列事件。模块管理器的实现位于 myapp/vendor/zendframework/zendmodulemanager/src/ModuleManager.php。
模块管理器侦听器- 它们可以附加到模块管理器触发的事件。通过附加到模块管理器的事件,它们可以执行从解析和加载模块到为每个模块执行复杂工作的所有操作。
MVC Web模块系统
Zend Framework 中的 MVC Web 应用程序通常被编写为模块。单个网站可以包含一个或多个按功能分组的模块。面向 MVC 的模块的推荐结构如下 -
module_root/ Module.php autoload_classmap.php autoload_function.php autoload_register.php config/ module.config.php public/ images/ css/ js/ src/ <module_namespace>/ <code files> test/ phpunit.xml bootstrap.php <module_namespace>/ <test code files> view/ <dir-named-after-module-namespace>/ <dir-named-after-a-controller>/ <.phtml files>
结构与前一章中讨论的相同,但这里是通用的。autoload_文件可以用作自动加载模块中可用的类的默认机制,而无需使用zend-modulemanager中可用的高级模块管理器。
autoload_classmap.php - 返回类名及其相应文件名的数组。
autoload_function.php - 返回 PHP 回调。这可以利用 autoload_classmap.php 返回的类。
autoload_register.php - 注册由 autoload_function.php 返回的 PHP 回调。
这些自动加载文件不是必需的,但建议使用。在骨架应用程序中,我们没有使用autoload_ files。
模块类
Module 类应命名为Module,模块类的命名空间应为Module name。这将有助于 Zend Framework 轻松解析和加载模块。骨架(myapp)应用程序myapp/module/Application/src/Module.php中的应用程序模块代码如下 -
namespace Application; class Module { const VERSION = '3.0.2dev'; public function getConfig() { return include __DIR__ . '/../config/module.config.php'; } }
Zend Framework 模块管理器将自动调用getConfig()函数并执行必要的步骤。
Zend 框架 - 应用程序结构
在本章中,让我们了解 Zend Framework 应用程序的结构。myapp应用程序的结构如下 -
├── composer.json ├── composer.lock ├── CONDUCT.md ├── config │ ├── application.config.php │ ├── autoload │ │ ├── development.local.php │ │ ├── development.local.php.dist │ │ ├── global.php │ │ ├── local.php.dist │ │ ├── README.md │ │ └── zend-developer-tools.local-development.php │ ├── development.config.php │ ├── development.config.php.dist │ └── modules.config.php ├── CONTRIBUTING.md ├── data │ └── cache │ └── module-classmap-cache.application.module.cache.php ├── docker-compose.yml ├── Dockerfile ├── LICENSE.md ├── module │ └── Application │ ├── config │ ├── src │ ├── test │ └── view ├── phpcs.xml ├── phpunit.xml.dist ├── public │ ├── css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── bootstrap.min.css.map │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ └── style.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── img │ │ ├── favicon.ico │ │ └── zf-logo-mark.svg │ ├── index.php │ ├── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── jquery-3.1.0.min.js │ └── web.config ├── README.md ├── TODO.md ├── Vagrantfile └── vendor ├── autoload.php ├── bin │ ├── phpunit -> ../phpunit/phpunit/phpunit │ ├── templatemap_generator.php -> ../zendframework/zend- view/bin/templatemap_generator.php │ └── zf-development-mode -> ../zfcampus/zf-development-mode/bin/zf- development-mode ├── composer │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ ├── ClassLoader.php │ ├── installed.json │ └── LICENSE ├── container-interop │ └── container-interop ├── doctrine │ └── instantiator ├── myclabs │ └── deep-copy ├── phpdocumentor │ ├── reflection-common │ ├── reflection-docblock │ └── type-resolver ├── phpspec │ └── prophecy ├── phpunit │ ├── php-code-coverage │ ├── php-file-iterator │ ├── php-text-template │ ├── php-timer │ ├── php-token-stream │ ├── phpunit │ └── phpunit-mock-objects ├── sebastian │ ├── code-unit-reverse-lookup │ ├── comparator │ ├── diff │ ├── environment │ ├── exporter │ ├── global-state │ ├── object-enumerator │ ├── recursion-context │ ├── resource-operations │ └── version ├── symfony │ └── yaml ├── webmozart │ └── assert ├── zendframework │ ├── zend-component-installer │ ├── zend-config │ ├── zend-console │ ├── zend-dom │ ├── zend-escaper │ ├── zend-eventmanager │ ├── zend-http │ ├── zend-loader │ ├── zend-modulemanager │ ├── zend-mvc │ ├── zend-router │ ├── zend-servicemanager │ ├── zend-stdlib │ ├── zend-test │ ├── zend-uri │ ├── zend-validator │ └── zend-view └── zfcampus └── zf-development-mode 73 directories, 55 files
Zend Framework 应用程序由不同的文件夹组成。它们如下 -
应用程序- 该目录包含您的应用程序。它将容纳 MVC 系统以及配置、使用的服务和引导文件。
Config - 该目录包含应用程序的配置文件。
数据- 该目录提供了存储易失且可能临时的应用程序数据的位置。
模块- 模块允许开发人员将一组相关控制器分组为逻辑组织的组。
Public - 这是应用程序的文档根目录。它启动 Zend 应用程序。它还包含应用程序的资产,如 JavaScript、CSS、图像等。
Vendor - 该目录包含作曲家依赖项。
应用模块的结构
这是您的应用程序的主目录。Zend Framework 2 引入了强大而灵活的模块系统来有效地组织应用程序。骨架应用程序(myapp)的应用程序模块为整个应用程序提供引导、错误和路由配置。应用程序模块的结构如下所示 -
├── module │ └── Application │ ├── config │ │ └── module.config.php │ ├── src │ │ ├── Controller │ │ │ └── IndexController.php │ │ └── Module.php │ ├── test │ │ └── Controller │ │ └── IndexControllerTest.php │ └── view │ ├── application │ │ └── index │ │ └── index.phtml │ ├── error │ │ ├── 404.phtml │ │ └── index.phtml │ └── layout │ └── layout.phtml
让我们详细介绍每个模块目录 -
应用程序- 这是模块的根目录。文件夹的名称将与模块的名称匹配,并且该名称也用作模块内定义的所有类的 PHP 命名空间。它将容纳 MVC 系统以及配置、使用的服务和引导文件。
配置- 模块的独立配置。
Src - 应用程序的主要业务逻辑。
视图- 包含设计/演示(HTML)文件。例如,index.phtml。
src/Module.php - 它是模块的核心。它充当模块的“前端控制器”。Zend 在处理该模块中的任何 PHP 类之前处理src/Module.php文件。
Application/config/module.config.php - 它是为路由器配置和自动加载文件而实现的。
应用程序/视图/布局- 布局表示多个视图的公共部分。例如,页眉和页脚。默认情况下,布局应存储在views/layouts文件夹中。
所有模块与上述应用模块具有相同或相似的结构。
Zend 框架 - 创建模块
在本章中,我们将学习如何在 Zend Framework 中创建基于 MVC 的模块。让我们创建一个名为Tutorial 的模块来了解模块创建过程。
在 –myapp/module/Tutorial/src/ 目录中创建一个名为Module的新 PHP 类,并实现 ConfigProviderInterface。
将Tutorial设置为Module类的命名空间。
在Module类中编写一个公共函数getConfig ,并返回Tutorial Module的配置文件。
Module类的完整代码如下 -
<?php namespace Tutorial; use Zend\ModuleManager\Feature\ConfigProviderInterface; class Module implements ConfigProviderInterface { public function getConfig() { return include __DIR__ . '/../config/module.config.php'; } }
使用以下代码在autoload部分下的composer.json中配置Tutorial模块。
"autoload": { "psr-4": { "Application\\": "module/Application/src/", "Tutorial\\": "module/Tutorial/src/" } }
使用composer update命令更新应用程序,如下所示。
composer update
Composer命令将对应用程序进行必要的更改,并在命令提示符中显示日志,如下所示 -
Loading composer repositories with package information Updating dependencies (including require-dev) - Removing zendframework/zend-component-installer (0.3.0) - Installing zendframework/zend-component-installer (0.3.1) Downloading: 100% - Removing zendframework/zend-stdlib (3.0.1) - Installing zendframework/zend-stdlib (3.1.0) Loading from cache - Removing zendframework/zend-eventmanager (3.0.1) - Installing zendframework/zend-eventmanager (3.1.0) Downloading: 100% - Removing zendframework/zend-view (2.8.0) - Installing zendframework/zend-view (2.8.1) Loading from cache - Removing zendframework/zend-servicemanager (3.1.0) - Installing zendframework/zend-servicemanager (3.2.0) Downloading: 100% - Removing zendframework/zend-escaper (2.5.1) - Installing zendframework/zend-escaper (2.5.2) Loading from cache - Removing zendframework/zend-http (2.5.4) - Installing zendframework/zend-http (2.5.5) Loading from cache - Removing zendframework/zend-mvc (3.0.1) - Installing zendframework/zend-mvc (3.0.4) Downloading: 100% - Removing phpunit/phpunit (5.7.4) - Installing phpunit/phpunit (5.7.5) Downloading: 100% Writing lock file Generating autoload files
使用以下代码在/config/创建模块配置文件“module.config.php” -
<?php namespace Tutorial; use Zend\ServiceManager\Factory\InvokableFactory; use Zend\Router\Http\Segment; return [ 'controllers' => [ 'factories' => [Controller\TutorialController::class => InvokableFactory::class,], ], 'view_manager' => [ 'template_path_stack' => ['tutorial' => __DIR__ . '/../view',], ], ];
配置文件分为三个部分,如下所示:
控制器配置- 指定模块内可用的控制器。
路由配置- 指定模块中的控制器如何解析为 URL。
视图配置- 指定与视图引擎相关的配置,例如视图的位置等。
在应用程序级配置文件 myapp/config/modules.config.php 中配置教程模块。
return ['Zend\Router', 'Zend\Validator', 'Application', 'Tutorial'];
通过执行应用程序文件夹根目录下的composer服务来运行应用程序。
我们已经成功添加了一个新模块,但我们仍然需要添加控制器、路由和视图才能成功运行教程模块。
Zend 框架 - 控制器
如前所述,控制器在 Zend MVC 框架中发挥着重要作用。应用程序中的所有网页都需要由控制器来处理。
在 Zend MVC 框架中,控制器是实现 Zend/Stdlib/DispatchableInterface 的对象。DispatchableInterface有一个方法:dispatch ,它获取Request对象作为输入,执行一些逻辑并返回Response对象作为输出。
dispatch(Request $request, Response $response = null)
返回“Hello World”的控制器对象的简单示例如下 -
use Zend\Stdlib\DispatchableInterface; use Zend\Stdlib\RequestInterface as Request; use Zend\Stdlib\ResponseInterface as Response; class HelloWorld implements DispatchableInterface { public function dispatch(Request $request, Response $response = null) { $response->setContent("Hello World!"); } }
DispatchableInterface是基本的,它需要很多其他接口来编写高级控制器。其中一些接口如下 -
InjectApplicationEventInterface - 用于注入事件(Zend EventManager)
ServiceLocatorAwareInterface - 用于定位服务(Zend ServiceManager)
EventManagerAwareInterface - 用于管理事件(Zend EventManager)
记住这些事情,Zend Framework 提供了许多实现这些接口的现成控制器。最重要的控制器如下所述。
抽象动作控制器
AbstractActionController (Zend/Mvc/Controller/AbstractActionController) 是 Zend MVC 框架中最常用的控制器。它具有编写典型网页所需的所有功能。它允许路由(路由将请求 url 匹配到控制器及其方法之一)来匹配操作。当匹配时,控制器将调用以该操作命名的方法。
例如,如果匹配了路由test并且路由test返回hello for action,则将调用helloAction方法。
让我们使用AbstractActionController编写TutorialController。
通过扩展AbstractActionController创建一个名为TutorialController的新 PHP 类,并将其放置在module/Tutorial/src/Controller/目录中。
将Tutorial\Controller设置为命名空间。
编写一个indexAction方法。
从indexAction方法返回ViewModel对象。ViewModel对象用于将数据从控制器发送到视图引擎,我们将在后续章节中看到。
完整的代码清单如下 -
?php namespace Tutorial\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; class TutorialController extends AbstractActionController { public function indexAction() { return new ViewModel(); } }
我们已经成功添加了新的TutorialController。
抽象RestfulController
AbstractRestfulController (Zend\Mvc\Controller\AbstractRestfulController) 检查传入请求的HTTP方法,并通过考虑 HTTP 方法来匹配操作(方法)
例如,如果在请求中找到id参数,则使用 GET HTTP 方法的请求要么匹配getList()方法,要么匹配get()方法。
抽象控制台控制器
AbstractConsoleController (Zend\Mvc\Controller\AbstractConsoleController) 与 AbstractActionController 类似,只是它只运行在控制台环境而不是浏览器中。
Zend 框架 - 路由
路由将请求 URI 映射到特定控制器的方法。在本章中,我们将了解如何在 Zend Framework 中实现路由。
一般来说,任何 URI 都由三个部分组成 -
- 主机名段,
- 路径段,以及
- 查询段。
例如,在 URI / URL - http://www.example.com/index?q=data 中, www.example.com是主机名段,index是路径段,q=data是查询段。通常,路由根据一组约束检查页面段。如果任何约束匹配,则它返回一组值。主要价值之一是控制器。
在某种情况下,路由还会检查主机段、查询段、请求 HTTP 方法、请求 HTTP 标头等。
路由和路由堆栈
Route是路由中的主要对象。Zend Framework 有一个用于路由对象的特殊接口RouteInterface。所有路由对象都需要实现RouteInterface。RouteInterface 的完整列表如下 -
namespace Zend\Mvc\Router; use Zend\Stdlib\RequestInterface as Request; interface RouteInterface { public static function factory(array $options = []); public function match(Request $request); public function assemble(array $params = [], array $options = []); }
主要方法是match。此匹配方法根据其中定义的约束检查给定的请求。如果找到任何匹配项,则返回RouteMatch对象。此 RouteMatch 对象提供匹配请求的详细信息作为参数。可以使用getParams方法从RouteObject中提取这些参数。
RouteObject 的完整列表如下 -
namespace Zend\Mvc\Router; class RouteMatch { public function __construct(array $params); public function setMatchedRouteName($name); public function getMatchedRouteName(); public function setParam($name, $value); public function getParams(); public function getParam($name, $default = null); }
一般来说,一个典型的MVC应用程序有很多路线。每条路由都将按照 LIFO 顺序进行处理,并且将匹配并返回一条路由。如果没有匹配/返回路由,则应用程序将返回“找不到页面”错误。Zend Framework 提供了一个处理路由的接口RouteStackInterface。此 RouteStackInterface 可以选择添加/删除路由。
RouteStackInterface 的完整列表如下 -
namespace Zend\Mvc\Router; interface RouteStackInterface extends RouteInterface { public function addRoute($name, $route, $priority = null); public function addRoutes(array $routes); public function removeRoute($name); public function setRoutes(array $routes); }
Zend 框架提供了RouteStack接口的两种实现,如下所示:
- 简单路由栈
- 树路由栈
路线类型
Zend框架在“Zend\Mvc\Router\Http”命名空间下为所有情况提供了大量现成的路由对象。针对给定情况选择和使用正确的路由对象就足够了。
可用路线如下 -
主机名- 用于匹配 URI 的主机部分。
Literal - 用于匹配精确的 URI。
Method - 用于匹配传入请求的 HTTP 方法。
部分- 用于使用自定义逻辑匹配 URI 路径段的部分。
Regex - 用于通过 Regex 模式匹配 URI 路径段。
Schema - 用于匹配 URI Schema,例如 http、https 等。
Segment - 用于通过将 URI 路径拆分为多个段来匹配 URI 路径。
我们来看看最常用的字面Route和分段Route怎么写。路由通常在每个模块的配置文件 - module.config.php中指定。
文字路线
通常,按 LIFO 顺序查询路由。Literal 路由用于精确匹配 URI 路径。
它的定义如下 -
$route = Literal::factory(array( 'route' => '/path', 'defaults' => array('controller' => 'Application\Controller\IndexController', 'action' => 'index',), ));
上面的路由匹配请求 url 中的/path并返回index作为操作和IndexController作为控制器。
分段路线
当您的 url 应该包含可变参数时,就会使用分段路由。
其描述如下 -
$route = Segment::factory(array( 'route' => '/:controller[/:action]', 'constraints' => array( 'controller' => '[a-zA-Z][a-zA-Z0-9_-]+', 'action' => '[a-zA-Z][a-zA-Z0-9_-]+', ), 'defaults' => array( 'controller' => 'Application\Controller\IndexController', 'action' => 'index',), ));
这里,段由冒号表示,后跟字母数字字符。如果您保留一个段是可选的,那么它将用括号括起来。每个段可能有与其相关的约束。每个约束都是一个正则表达式。
在教程模块中配置路由
让我们在教程模块中添加一条分段路线。更新教程模块配置文件 – module.config.php位于myapp/module/Tutorial/config。
<?php namespace Tutorial; use Zend\ServiceManager\Factory\InvokableFactory; use Zend\Router\Http\Segment; return [ 'controllers' => [ 'factories' => [ Controller\TutorialController::class => InvokableFactory::class, ], ], 'router' => [ 'routes' => [ 'tutorial' => [ 'type' => Segment::class, 'options' => [ 'route' => '/tutorial[/:action[/:id]]', 'constraints' => [ 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ], 'defaults' => [ 'controller' => Controller\TutorialController::class, 'action' => 'index', ], ], ], ], ], 'view_manager' => [ 'template_path_stack' => ['tutorial' => __DIR__ . '/../view',], ], ];
我们已成功添加教程模块的路由。我们在完成教程模块方面仅落后一步。我们需要为我们的模块添加视图,我们将在后续章节中学习。
Zend 框架 - 视图层
视图层是 MVC 应用程序的表示层。它将应用程序逻辑与表示逻辑分开。在典型的 PHP Web 应用程序中,所有业务逻辑和设计都是混合在一起的。混合可以在小项目中实现更快的开发。但是,在涉及大量高级架构的大型项目中,它会惨遭失败。要更改 Web 应用程序的设计,开发人员还需要处理业务逻辑。这可能是灾难性的,会导致业务逻辑的破坏。
Zend Framework 提供了一个经过深思熟虑、干净、灵活且可扩展的视图层。View 层可作为单独的模块Zend/View并与Zend/Mvc模块完美集成。Zend View Layer 被分成多个组件,彼此之间可以很好地交互。
其各个组成部分如下 -
变量容器- 保存视图层的数据。
查看模型- 保存变量容器和设计模板。
渲染器