- FuelPHP 教程
- FuelPHP - 首页
- FuelPHP - 简介
- FuelPHP - 安装
- FuelPHP - 架构概述
- FuelPHP - 简单 Web 应用
- FuelPHP - 配置
- FuelPHP - 控制器
- FuelPHP - 路由
- FuelPHP - 请求 & 响应
- FuelPHP - 视图
- FuelPHP - 展示器
- FuelPHP - 模型 & 数据库
- FuelPHP - 表单编程
- FuelPHP - 验证
- 高级表单编程
- FuelPHP - 文件上传
- FuelPHP - Ajax
- FuelPHP - HMVC 请求
- FuelPHP - 主题
- FuelPHP - 模块
- FuelPHP - 包
- Cookie & Session 管理
- FuelPHP - 事件
- FuelPHP - 邮件管理
- FuelPHP - 性能分析器
- 错误处理 & 调试
- FuelPHP - 单元测试
- 完整的运行示例
- FuelPHP 有用资源
- FuelPHP 快速指南
- FuelPHP - 有用资源
- FuelPHP - 讨论
FuelPHP 快速指南
FuelPHP - 简介
FuelPHP是一个开源的Web应用程序框架。它是用PHP 5.3编写的,并实现了HMVC模式。HMVC是分层模型-视图-控制器框架,它允许子请求控制器,返回部分页面,例如评论、菜单等,而不是像普通MVC那样返回完整的页面。
FuelPHP的创建是为了结合CodeIgniter和Kohana等框架的最佳实践,并加入自身改进和理念。FuelPHP的数据库迁移工具和脚手架功能受到流行的Ruby on Rails框架的启发。
FuelPHP通过一个名为“Oil”的实用程序充分利用了命令行的强大功能。该实用程序旨在帮助加快开发速度,提高效率,进行测试、调试和HTML支持。
FuelPHP纯粹是一种面向对象的方法。其架构基于模块化的思想。应用程序可以分为模块,每个组件都可以扩展或替换,而无需重写一行代码。Fuel支持任何模板解析器,例如Smarty、Twig、PHPTal等,用于解析视图。
FuelPHP社区庞大且活跃,拥有超过300名贡献者。其庞大的社区定期创建和改进包和扩展。FuelPHP框架的主要目标是提供灵活性和兼容性。它快速、易于学习,并且是开发Web应用程序的完整解决方案。
使FuelPHP成为PHP开发人员使用的顶级框架之一的原因是——由于其稳定的API,FuelPHP的新版本与旧版本向后兼容。它非常灵活。
包和模块使以系统化的方式轻松简单地重用现有代码成为可能。FuelPHP通过小型库提供最大性能。其交互式调试允许轻松消除开发中的错误。此外,其简洁稳定的代码使编程更容易。
FuelPHP - 特性
FuelPHP提供了许多特性来创建一个功能齐全的Web应用程序。它提供灵活的组件、简单的配置、易于使用的ORM、基于REST的应用程序开发模式等。以下是一些主要特性:
- 灵活且社区驱动的Web框架
- 易于配置和使用
- FuelPHP极其便携,几乎可以在任何服务器上运行
- 灵活的URI路由系统
- FuelPHP提供RESTful API开发支持
- 轻量级ORM模型
- 输入过滤并防止SQL注入
- 安全的身份验证和授权框架
- 代码可重用且易于维护
- 自动加载类、会话管理和异常处理。
FuelPHP - 优势
FuelPHP是一个优雅的HMVC PHP 5.3框架,提供了一套用于构建Web应用程序的组件,具有以下优势:
模块化结构 - Fuel不会强制你使用模块或HMVC文件结构。如果你想使用,集成过程非常容易。FuelPHP应用程序以模块化结构创建,使开发人员更容易获得明确的好处。
HMVC模式 - 此框架最重要的特性是HMVC(分层模型视图控制器),它使访问或使用更高级别的任何属性、类方法、函数、文件变得容易。
安全的哈希函数 - FuelPHP支持强大的密码工具和密码哈希技术。它使用强大的PHPSecLib处理加密、解密和哈希。
脚手架功能 - 脚手架是一种用于构建数据库操作的元编程方法。Fuel的脚手架非常简单。它允许你通过非常简单的步骤获得基本的CRUD应用程序。
以下流行产品使用FuelPHP框架:
Matic Technology - 全球离岸定制软件开发解决方案提供商。在Matic Technologies,他们根据客户的要求,通过FuelPHP提供所有可能的最佳解决方案。
Kroobe - Kroobe是一家社交网络分类信息公司。Fuel为Kroobe团队提供了极低的开发成本和服务,以实现高效的解决方案。
FuelPHP - 安装
本章解释如何在你的机器上安装FuelPHP框架。FuelPHP的安装非常简单易行。你有两种方法可以创建FuelPHP应用程序:
第一种方法是使用名为Oil的FuelPHP工具进行命令行安装。
第二种方法是基于Composer的安装。FuelPHP使用Composer进行安装和包依赖管理,因此请确保在继续操作之前已在本地安装了composer。
让我们在后续章节中详细逐一介绍每种方法。
系统要求
在进行安装之前,必须满足以下系统要求。
Web服务器(以下任一)
- WAMP(Windows)
- Microsoft IIS(Windows)
- LAMP(Linux)
- MAMP(Macintosh)
- XAMP(多平台)
- Nginx(多平台)
- PHP内置开发Web服务器(多平台)
浏览器支持(以下任一)
- IE(Internet Explorer 8+)
- Firefox
- Google Chrome
- Safari
PHP兼容性 - PHP 5.3或更高版本。为了获得最大的好处,请使用最新版本。
在本教程中,让我们使用PHP的内置开发Web服务器。内置开发Web服务器易于启动,并且足以理解FuelPHP Web应用程序的基础知识,而无需深入了解Web服务器和配置的世界。
命令行安装
FuelPHP的命令行安装非常简单,最多需要五分钟。
安装Oil包
Oil是FuelPHP框架提供的一个特殊包/命令,用于执行FuelPHP应用程序开发中所需的许多任务,包括安装、开发和测试应用程序。
要安装Oil包,请打开shell并运行以下命令:
sudo curl https://get.fuelphp.com/oil | sh
该命令使用curl下载并安装oil包。该命令将显示类似于以下信息的输出,并最终安装oil包。
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 479 100 479 0 0 353 0 0:00:01 0:00:01 --:--:-- 353
创建新项目
要使用Oil创建新项目,请使用以下命令:
oil create <project_name>
让我们使用以下命令创建一个名为“HelloWorld”的新项目。
oil create HelloWorld
现在,你将看到类似于以下的响应,并最终创建一个简单的FuelPHP应用程序框架。
composer create-project fuel/fuel HelloWorld Installing fuel/fuel (1.8.0.1) - Installing fuel/fuel (1.8.0.1) Loading from cache Created project in HelloWorld Loading composer repositories with package information Updating dependencies (including require-dev) - Installing composer/installers (v1.3.0) Loading from cache - Installing fuelphp/upload (2.0.6) Loading from cache - Installing michelf/php-markdown (1.4.0) Loading from cache - Installing psr/log (1.0.2) Loading from cache - Installing monolog/monolog (1.18.2) Loading from cache - Installing phpseclib/phpseclib (2.0.0) Loading from cache - Installing fuel/core (1.8.0.4) Loading from cache - Installing fuel/auth (1.8.0.4) Loading from cache - Installing fuel/email (1.8.0.4) Loading from cache - Installing fuel/oil (1.8.0.4) Loading from cache - Installing fuel/orm (1.8.0.1) Loading from cache - Installing fuel/parser (1.8.0.4) Loading from cache - Installing fuel/docs (1.8.0.4) Loading from cache ……………. ……………. Writing lock file Generating autoload files
Oil版本
要测试Oil是否可用以及检查版本,请使用以下命令:
$ cd HelloWorld $ php oil -v
以上命令产生以下结果:
Fuel: 1.8 running in "development" mode
Oil帮助命令
要获取Oil的基本帮助文档,请使用以下命令:
$ php oil help
以上命令将显示类似于以下结果的帮助文档:
Usage: php oil [cell|console|generate|package|refine|help|server|test] Runtime options: -f, [--force] # Overwrite files that already exist -s, [--skip] # Skip files that already exist -q, [--quiet] # Supress status output -t, [--speak] # Speak errors in a robot voice Description: The 'oil' command can be used in several ways to facilitate quick development, help with testing your application and for running Tasks. Environment: If you want to specify a specific environment oil has to run in, overload the environment variable on the commandline: FUEL_ENV=staging php oil <commands> More information: You can pass the parameter "help" to each of the defined command to get information about that specific command: php oil package help Documentation: http://docs.fuelphp.com/packages/oil/intro.html
目前,你已经了解了如何使用Oil安装Fuel。让我们在下一节中了解基于composer的安装。
基于Composer的安装
以下命令用于使用Composer安装FuelPHP。
$ composer create-project fuel/fuel --prefer-dist.
Git仓库克隆
要安装最新的开发版本作为本地git仓库克隆,请使用以下命令。
$ composer create-project fuel/fuel:dev-1.9/develop --prefer-source.
运行应用程序
移动到项目目录的public文件夹,使用以下命令使用生产服务器运行应用程序。
$ cd path/to/HelloWorld/public $ php -S localhost:8080 index.php
它会产生以下响应。
PHP 5.5.31 Development Server started at Sun May 21 12:26:10 2017 Listening on https://127.0.0.1:8080 Document root is /Users/workspace/php-fuel/HelloWorld/public Press Ctrl-C to quit.
现在,请求URL,https://127.0.0.1:8080,它将产生以下结果。
结果
这是在开发环境中运行FuelPHP应用程序的最简单方法。如果你在生产环境中以这种方式创建应用程序,将会面临安全问题。推荐的方法是设置虚拟主机配置。下一节将针对apache web服务器进行解释。
设置虚拟主机
这是访问FuelPHP应用程序更安全的方法。要设置虚拟主机,你需要将apache虚拟主机文件链接到你的应用程序。对于内网应用程序,将系统主机文件URL重定向到虚拟主机。
虚拟主机文件
打开虚拟主机并添加以下更改。
<VirtualHost *:80> ServerName hello.app DocumentRoot /path/to/public SetEnv FUEL_ENV “development” <Directory /path/to/public> DirectoryIndex index.php AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost>
系统主机文件
现在,使用以下命令向你的机器添加主机条目。
sudo vi /etc/hosts
然后,将以下行添加到文件的末尾。
127.0.0.1 hello.app
为了使所有更改生效,请重新启动你的Apache服务器并请求url,http://hello.app。它将显示FuelPHP主页。
FuelPHP - 架构概述
FuelPHP基于经过实战检验的模型-视图-控制器架构以及HMVC(分层MVC)支持。MVC提供了灵活的分层应用程序开发,而HMVC则更进一步,能够将Web应用程序部件化。
FuelPHP的优势在于它不强制使用特定的应用程序开发方式。它只提供一个简单易用的标准结构。开发人员可以自由使用FuelPHP提供的预定义功能集,或者根据需要修改它。FuelPHP提供的所有功能,包括核心功能,都可以根据应用程序的要求进行更改。
模型
模型是应用程序的业务实体。控制器和视图以模型的形式交换数据。模型使我们的业务数据能够统一表示。它使数据库层能够以标准方式与Web应用程序层交互,并提供选择、保存、编辑和删除数据库实体的选项。
控制器
一个典型的MVC应用程序从控制器开始。一旦用户向FuelPHP Web应用程序发送请求,应用程序就会收集有关该请求的所有信息并将其发送到控制器。控制器执行请求页面的必要业务逻辑,然后调用相关的视图以及以模型形式处理后的数据。
视图
视图是MVC应用程序的表示层。视图决定如何向用户显示模型。它支持从简单数据渲染到高级布局,这使得网站能够在所有页面上规范设计。视图还提供主题支持,这使得能够快速更改应用程序中的设计。
展示器
Presenter是FuelPHP提供的一个特殊功能。它是控制器(Controller)和视图(View)之间的桥梁。控制器可以将一些底层职责,例如从数据库检索模型、为视图生成数据等,委托给Presenter。控制器调用Presenter而不是直接调用视图,而Presenter再调用视图。Presenter实现了业务逻辑和表示层的纯分离。
分层MVC
FuelPHP提供了一个选项,允许一个控制器调用另一个控制器,类似于来自客户端(浏览器)的请求。如果一个控制器调用另一个控制器,被调用的控制器将把响应返回给调用控制器,而不是将其渲染到客户端(浏览器)。这使得Web应用程序可以实现**部件化(widgetization)**。例如,评论区既可以作为一个独立页面显示,也可以作为主页面(博客)的一个子部分显示。
模块 (Module)
FuelPHP 的一个显著特点是,可以将Web应用程序的一部分转换为模块,这些模块可以在不同的应用程序之间共享。例如,为一个应用程序创建的博客模块,只需将模块代码从源应用程序复制到目标应用程序,即可在另一个应用程序中重用。
需要注意的是,创建新模块与开发主应用程序一样简单。其结构与主应用程序类似,唯一的区别在于模块应该编码在一个单独的文件夹中。
包 (Package)
FuelPHP提供了一个选项,可以将代码组织成一个名为“包”的单元。一个包可以包含Web应用程序所需的一个或多个功能。例如,数据库组件(如ORM、电子邮件等)可以组织成一个包,并在需要时使用。
包与模块的不同之处在于,包不包含任何网页或网页片段。包既可以在FuelPHP中使用,也可以在任何其他PHP框架中使用。
工作流程
FuelPHP的工作流程简单易懂。下图描述了该流程。
用户向应用程序发送请求。
控制器接收请求,并通过与模型交互来收集信息,而模型又与数据库交互。
控制器通过向其他控制器发送子请求来收集信息。
控制器将检索到的模型发送给视图,视图生成表示并将其作为响应发送给客户端。
在某些情况下,控制器可能会将控制权传递给Presenter。在这种情况下,Presenter从模型收集信息并将其发送给客户端。在这里,Presenter不执行任何业务逻辑,只从数据库检索模型。
FuelPHP - 简单 Web 应用
本章将介绍如何在FuelPHP框架中创建一个简单的应用程序。正如前面所讨论的,您知道如何在Fuel中创建一个新项目。我们可以以员工详细信息为例。
让我们首先使用以下命令创建一个名为Employee的项目。
oil create employee
执行命令后,将创建一个名为**employee**的项目,其**文件结构**如下:
employee ├── CHANGELOG.md ├── composer.json ├── composer.lock ├── composer.phar ├── CONTRIBUTING.md ├── fuel │ ├── app │ │ ├── bootstrap.php │ │ ├── cache │ │ ├── classes │ │ ├── config │ │ ├── lang │ │ ├── logs │ │ ├── migrations │ │ ├── modules │ │ ├── tasks │ │ ├── tests │ │ ├── themes │ │ ├── tmp │ │ ├── vendor │ │ └── views │ ├── core │ │ ├── base56.php │ │ ├── base.php │ │ ├── bootstrap.php │ │ ├── bootstrap_phpunit.php │ │ ├── classes │ │ ├── composer.json │ │ ├── config │ │ ├── CONTRIBUTING.md │ │ ├── lang │ │ ├── phpunit.xml │ │ ├── tasks │ │ ├── tests │ │ ├── vendor │ │ └── views │ ├── packages │ │ ├── auth │ │ ├── email │ │ ├── oil │ │ ├── orm │ │ └── parser │ └── vendor │ ├── autoload.php │ ├── composer │ ├── fuelphp │ ├── michelf │ ├── monolog │ ├── phpseclib │ └── psr ├── LICENSE.md ├── oil ├── public │ ├── assets │ │ ├── css │ │ ├── fonts │ │ ├── img │ │ └── js │ ├── favicon.ico │ ├── index.php │ └── web.config ├── README.md └── TESTING.md 42 directories, 21 files
应用程序结构
FuelPHP框架提供了一个组织良好的应用程序结构。让我们检查一下应用程序中一些重要的文件和文件夹。
**fuel** - 包含所有PHP文件。
**public** - 包含所有可通过浏览器直接访问的资源,例如JavaScript、CSS、图像等。
**oil** - 用于运行命令行任务的可执行文件,例如生成代码或在应用程序中进行交互式调试。这是可选的。
**fuel/app/** - 包含所有特定于应用程序的PHP文件。它包含模型、视图和控制器。
**fuel/core/** - Fuel框架本身位于此处。
**fuel/packages/** - 包含所有Fuel包。默认情况下,Fuel将包含三个包:oil、auth和orm。除非您需要它们,否则这些包不会被加载。
**fuel/app/config/** - 包含所有与应用程序相关的配置文件。主要的应用程序配置文件config.php位于此处。
**fuel/app/classes/** - 包含所有基于MVC的特定于应用程序的PHP文件。它包含控制器、模型、辅助类、库等。
**fuel/app/classes/controller/** - 控制器放置在此处。
**fuel/app/classes/model/** - 模型放置在此处。
**fuel/app/views/** - 包含视图文件。视图没有特定的命名约定。
添加控制器
如前所述,FuelPHP 基于模型-视图-控制器 (MVC) 开发模式。MVC是一种软件方法,它将应用程序逻辑与表示分离。在MVC模式中,控制器扮演着重要的角色,应用程序中的每个网页都需要由控制器处理。默认情况下,控制器位于**fuel/app/classes/controller/**文件夹中。您可以在此处创建您自己的控制器类。
转到fuel/app/classes/controller/位置并创建employee.php文件。要创建一个新的控制器,只需扩展FuelPHP提供的Controller类,定义如下。
employee.php
<?php class Controller_Employee extends Controller { public function action_home() { // functionality of the home page echo "FuelPHP-Employee application!"; } }
现在,我们创建了一个Employee控制器并添加了一个公共方法action_home,它打印一个简单的文本。
路由
路由将网页URI解析为特定的控制器和操作。FuelPHP应用程序中的每个网页在控制器实际执行之前都应经过路由。默认情况下,每个控制器可以使用以下URI模式解析。
<controller>/<action>
其中:
**controller** 是控制器名称,不包含命名空间,例如employee
**action** 是方法名称,不包含action_关键字,例如home
新创建的控制器可以通过**https://127.0.0.1:8080/employee/home**访问,并将产生以下结果。
结果
FuelPHP - 配置
在本章中,我们将了解如何配置FuelPHP应用程序。默认情况下,配置文件存储在**fuel/app/config**文件夹中。应用程序的主要配置是**fuel/app/config/config.php**。配置使用PHP的关联数组指定。
概述
默认情况下,所有默认配置文件都在**fuel/core/config**文件夹中定义。要覆盖默认配置,请在**fuel/app/config/config.php**文件中添加相应的键并修改其值。我们可以使用“点表示法”来简化多维数组。例如,以下配置具有相同的用途(加载指定的包)。
array("always_load" => array("packages" => array( ... ) ) ); always_load.packages = array( ... );
配置可以按用途分组,并使用不同的文件指定,例如db.php用于数据库配置,package.php用于包管理等。
配置格式类型
FuelPHP非常灵活,并提供不同的格式来指定配置。默认配置格式是使用php数组的PHP。其他选项包括:
**INI** - 许多软件(包括PHP语言本身)都支持的简单的基于文本的配置。
[group] key = value
**YAML** - 易于理解、基于缩进且易于阅读的配置管理。
group: key: value
**JSON** - 易于理解,并且是开发人员最常用的文件格式。
{ "group" : { "key": "value" } }
**Memcached** - 将配置存储在Memcached服务器中。Memcached服务器详细信息可以在主配置文件**fuel/app/config/config.php**中使用**config.memcached**条目指定。
**DB** - 将配置存储在RDBMS系统中。配置表的表结构如下。
CREATE TABLE IF NOT EXISTS `config` ( `identifier` char(100) NOT NULL, `config` longtext NOT NULL, `hash` char(13) NOT NULL, PRIMARY KEY (`identifier`) )
可以使用config.database和config.table_name条目在配置文件中指定数据库和表详细信息。
环境
环境使FuelPHP能够通过加载不同的配置以不同的模式工作。FuelPHP支持以下环境:
**开发 (Development)** - `\Fuel::DEVELOPMENT` 设置开发模式
**生产 (Production)** - `\Fuel::PRODUCTION` 设置生产模式
**测试 (Test)** - `\Fuel::TEST` 设置测试模式
**预发布 (Staging)** - `\Fuel::STAGING` 设置预发布模式
FuelPHP还支持创建新的环境。这将使每个开发人员拥有自己的配置设置,他们可以在编码和测试应用程序时启用它。特定环境的配置可以通过简单地创建一个带有环境名称的文件夹(例如:test)并将配置文件放在新创建的文件夹中来添加,如下所示。
. ├── config.php ├── db.php ├── development │ └── db.php ├── production │ └── db.php ├── routes.php ├── staging │ └── db.php └── test └── db.php 4 directories, 7 files
设置您的环境
有三种方法可以设置您的环境。
**选项1** - 使用Web服务器的环境变量设置环境。在Apache Web服务器的**httpd.conf**文件的虚拟主机部分添加以下代码。它也可以添加到**.htaccess**文件中。
SetEnv FUEL_ENV production
**选项2** - 使用FuelPHP引导文件**fuel/app/bootstrap.php**设置环境
Fuel::$env = (isset($_SERVER['FUEL_ENV']
**选项3** - 使用Oil设置环境
$ env FUEL_ENV = production php oil -v
它会产生以下结果。
Fuel: 1.8 running in "production" mode
FuelPHP - 控制器
**控制器**负责处理进入FuelPHP应用程序的每个请求。根据FuelPHP,控制器位于**fuel/app/classes/controller/**。让我们首先创建一个Employee控制器。
employee.php
<?php class Controller_Employee extends Controller { public function action_home() { echo "FuelPHP-Employee application!"; } public function action_index() { echo "This is the index method of employee controller"; } }
控制器方法
控制器使用其一个**action_**方法来处理Web请求。我们可以根据应用程序的要求创建任意数量的action_方法。默认的action_方法是action_index。可以使用以下任何一个URL调用action_index方法。
https://127.0.0.1:8080/employee/index https://127.0.0.1:8080/employee/
结果
让我们在我们的**employee**应用程序中创建一个新的**action**方法,action_show。
<?php class Controller_Employee extends Controller { public function action_home() { echo "FuelPHP-Employee application!"; } public function action_index() { echo "This is the index method of employee controller"; } public function action_show() { echo "This is the show method of employee controller"; } }
可以使用以下URL调用action_show方法。
https://127.0.0.1:8080/home/show
结果
before() 方法
我们可以在控制器中创建一个方法before。此方法将在每次调用action_方法之前执行。如果该方法不存在,则不会调用此方法。此方法帮助我们编写常见的操作,例如登录检查、默认数据获取等。
让我们创建一个before方法并打印一条简单的文本消息。
public function before() { echo "This message comes from <em>before()</em> method</br>"; }
带有before操作的索引页面
带有before操作的显示页面
after() 方法
after()方法类似于before()方法,但在调用action_方法之后执行。after()方法以response作为输入并返回response对象。
public function after($response) { if ( ! $response instanceof Response) { $response = \Response::forge($response, $this->response_status); } return $response; }
如果输入为NULL或不是response对象,则使用Response的forge方法创建一个新的Response对象并返回它。我们将在后续章节中详细学习Response类。
扩展控制器
我们可以从另一个控制器扩展一个控制器。以下是基本语法。
class Controller_Employee extends Controller_Welcome { // controller methods }
这将有助于共享方法。
生成控制器
Fuel可以选择使用Oil命令生成控制器。以下是语法。
语法
oil g controller <controller-name>
示例
oil g controller sample
执行上述命令后,您将看到以下响应。
结果
Creating view: /path/to/project/fuel/app/views/template.php Creating view: /path/to/project/fuel/app/views/sample/index.php Creating controller: /path/to/project/fuel/app/classes/controller/sample.php
控制器类型
FuelPHP为各种目的提供了不同类型的控制器。它们如下:
- 基础控制器 (Base controller)
- 模板控制器 (Template controller)
- REST控制器 (Rest controller)
- 混合控制器 (Hybrid controller)
基础控制器 (Base Controller)
控制器是FuelPHP中所有不同类型控制器的基控制器。它提供处理Web请求所需的所有基本功能。它支持请求、响应、会话等。除非另有说明,否则我们将在所有示例中使用它。
模板控制器
模板控制器是基控制器的扩展。它具有模板支持,预定义的before()和after()方法。基本上,它可以用于将您的视图包装在具有页眉、页脚、侧边栏等的布局中。要创建模板控制器,我们需要扩展Controller_Template类。默认情况下,扩展Controller_Template类的所有方法都需要使用模板。
其定义如下。
class Controller_Employee extends Controller_Template { public function action_index() { // add methods } }
我们将在视图章节中更详细地讨论模板控制器。
REST控制器
REST控制器是基控制器的扩展。它预先支持REST API编程。这将使您可以轻松构建API。
要创建REST控制器,您需要扩展Controller_Rest类。其定义如下。
class Controller_Employee extends Controller_Rest { public function action_index() { // add methods } }
我们将在Ajax章节中更详细地讨论REST控制器。
混合控制器
混合控制器在一个基控制器中执行REST控制器和模板控制器的功能。
FuelPHP - 路由
路由将请求URI映射到特定控制器的method。在本节中,我们将详细讨论FuelPHP中路由的概念。
配置
路由配置文件位于fuel/app/config/routes.php。默认的routes.php文件定义如下:
<?php return array ( '_root_' => 'welcome/index', // The default route '_404_' => 'welcome/404', // The main 404 route 'hello(/:name)?' => array('welcome/hello', 'name' => 'hello'), );
这里,_root_是预定义的默认路由,当应用程序使用根路径/(例如https://127.0.0.1:8080/)请求时,将匹配它。_root_的值是在匹配时要解析的控制器和操作。welcome/index解析为Controller_Welcome控制器和action_index操作方法。同样,我们还有以下保留路由。
root - 当没有指定URI时的默认路由。
403 - 当发现HttpNoAccessException时抛出。
404 - 当页面未找到时返回。
500 - 当发现HttpServerErrorException时抛出。
简单路由
路由与请求URI进行比较。如果找到匹配项,则请求将路由到URI。简单路由描述如下:
return array ( 'about' => 'site/about', 'login' => 'employee/login', );
这里,about匹配https://127.0.0.1:8080/about并解析控制器Controller_Site和操作方法action_about
login匹配https://127.0.0.1:8080/login并解析控制器Controller_Login和操作方法action_login
高级路由
您可以将任何正则表达式包含到您的路由中。Fuel支持以下高级路由功能:
:any - 匹配从该点开始的任何内容,但不匹配“nothing”
:everything - 与:any类似,但也匹配“nothing”
:segment - 只匹配URI中的一个片段,但该片段可以是任何内容
:num - 匹配任何数字
:alpha - 匹配任何字母字符,包括UTF-8
:alnum - 匹配任何字母数字字符,包括UTF-8
例如,以下路由匹配URI https://127.0.0.1:8080/hello/FuelPHP并解析控制器Controller_Welcome和操作action_hello
'hello(/:name)?' => array('welcome/hello', 'name' => 'hello'),
Controller_Welcome中相应的操作方法如下:
public function action_hello() { $this->name = Request::active()->param('name', 'World'); $message = "Hello, " . $this->name; echo $message; }
这里,我们使用了Request类从URL获取name参数。如果找不到name,则使用World作为默认值。我们将在请求和响应章节学习Request类。
结果
HTTP方法操作
FuelPHP支持匹配HTTP方法前缀操作的路由。以下是基本语法。
class Controller_Employee extends Controller { public function get_index() { // called when the HTTP method is GET. } public function post_index(){ // called when the HTTP method is POST. } }
我们可以在配置文件中根据HTTP动词将您的URL路由到控制器和操作。
return array ( // Routes GET /employee to /employee/all and POST /employee to /employee/create ‘employee’ => array(array('GET', new Route(‘employee/all')), array('POST', new Route(‘employee/create'))), );
FuelPHP - 请求 & 响应
HTTP请求和HTTP响应在任何Web应用程序中都扮演着重要的角色。我们需要获取HTTP请求的完整详细信息才能正确处理它。处理完成后,我们需要通过HTTP响应将处理后的数据发送到客户端。
FuelPHP提供出色的Request和Response类分别读取和写入HTTP请求和HTTP响应。让我们在本节中了解Request和Response类。
请求
在一个典型的Web应用程序中,应用程序需要解析当前请求的详细信息。Request类提供简单的方法来解析应用程序要处理的当前请求。Request还提供了一个选项,可以通过充当http客户端来创建一个新的请求。
创建新的请求使应用程序能够请求应用程序的其他部分或完全不同的应用程序并显示结果。让我们在本节中学习如何解析传入的请求,并在HMVC请求章节中学习如何创建一个新的请求。
解析请求
Request类提供三种方法来获取HTTP请求的详细信息。它们如下:
active - 它是一个静态方法,返回当前活动的HTTP请求。
$currentRequest = Request::active();
param – 它返回指定参数的值。它包含两个参数。第一个参数是参数名称,第二个参数是如果参数在当前HTTP请求中不可用,则返回的值。
$param = Request::active()->param('employee_name', 'none');
params – 与param相同,只是它返回所有参数作为一个数组。
$params = Request::active()->params();
示例
让我们创建一个简单的表单,并使用request类处理表单。
步骤1 - 在employee控制器中创建一个新的操作,action_request。
public function action_request() { }
步骤2 - 调用request方法以获取当前请求的所有参数。
public function action_request() { $params = Request::active()->params(); }
步骤3 - 转储获取的参数数组。
public function action_request() { $params = Request::active()->params(); echo dump($params); }
步骤4 - 更改路由以在路由配置文件fuel/app/config/routes.php中包含参数
'employee/request(/:name)?' => array('employee/request', 'name' => 'name'),
现在,请求新的操作https://127.0.0.1:8080/employee/request/Jon,它将显示以下响应。
响应
Response类提供创建HTTP响应的选项。在大多数情况下,我们不需要直接使用response类。相反,我们使用View(我们将在下一节中学习)来创建HTTP响应。View向开发者隐藏HTTP响应,并使用底层的Response类将响应发送给客户端。在高级情况下,我们直接使用Response类并创建一个完整的HTTP响应。
创建响应
响应由标头和正文组成。主标头是HTTP状态代码。HTTP状态代码是HTTP协议中定义的标准代码,用于描述响应。例如,状态代码200表示请求成功。
Response类提供三个参数来创建HTTP响应:
$body - HTTP响应的正文
$status_code - HTTP响应的状态代码
$headers - 可选标头作为数组
$body = "Hi, FuelPHP"; $headers = array ( 'Content-Type' => 'text/html', ); $response = new Response($body, 200, $headers);
让我们在employee控制器中创建一个新的操作action_response,如下所示。
public function action_response() { $body = "Hi, FuelPHP"; $headers = array ('Content-Type' => 'text/html',); $response = new Response($body, 200, $headers); return $response; }
结果
方法
Response类提供许多方法来操作HTTP响应。它们如下:
forge - 与上面看到的response类构造函数相同。
return Response::forge("Hi, FuelPHP", 404);
redirect - 它提供了一个选项,可以重定向到一个URL,而不是发送响应。它包含以下参数:
a.url - 目标url b. method - 重定向方法。location(默认)和refresh c. redirect_code - HTTP状态代码。默认值为302。
// use a URL Response::redirect('http://some-domain/index', 'refresh'); // or use a relative URI Response::redirect('employee/list');
redirect_back - 与redirect方法类似,只是它重定向到上一页。如果找不到上一页,我们可以指定重定向页面。
// If there is no back page, go to the employee list page Response::redirect_back('/employee/list', 'refresh');
set_status - 它提供了一个选项来设置HTTP状态代码。
$response = new Response(); $response->set_status(404);
set_header - 它提供了一个选项来设置HTTP标头。
$response = new Response(); $response->set_header('Content-Type', 'application/pdf'); // replace previous value using third arguments $response->set_header('Content-Type', 'application/pdf', 'text/plain');
set_headers - 与set_header相同,只是它提供了一个选项,可以使用数组设置多个标头。
$response = new Response(); $response->set_headers (array 'Content-Type' => 'application/pdf', 'Pragma' => 'no-cache', ));
get_header - 它可以获取之前设置的标头详细信息。
$response = new Response(); $response->set_header('Pragma', 'no-cache'); // returns 'no-cache' $header = $response->get_header('Pragma'); // returns array('Pragma' => 'no-cache') $header = $response->get_header();
body - 它提供了一个选项来设置HTTP响应的正文。
$response = new Response(); $response->body('Hi, FuelPHP'); // returns 'Hi, FuelPHP' $body = $response->body();
send_headers - 它将标头发送到请求的客户端。FuelPHP使用此方法将响应发送到客户端。通常,我们不需要使用此方法。
$response->send_headers();
send - 与send_headers相同,只是HTTP响应中的标头可能会受到限制。
// send the headers as well $response->send(true); // only send the body $response->send(false); $response->send();
FuelPHP - 视图
View是MVC应用程序的表示层。它将应用程序逻辑与表示逻辑分开。当控制器需要生成HTML、CSS或任何其他内容时,它会将任务转发给视图引擎。
FuelPHP提供了一个简单灵活的类View,它具有视图引擎的所有必要功能。View类支持渲染视图文件。视图文件是一个HTML页面,其中嵌入了PHP指令。视图文件的变量可以使用View类作为PHP数组来设置,并使用数组的键在视图文件中引用。让我们检查View类的一些重要方法。
forge
用途 - 创建一个新的View对象
参数 - 以下是参数
$file - 视图文件的路径,相对于views文件夹,fuel/app/views
$data - 值的数组
$filter - 设置自动编码,默认为主配置文件中的设置
返回 - 视图的实例
例如:
$view = View::forge ('path/to/view', array( 'title' => "Show employee, 'employees' => $employees, ));
auto_filter
用途 - 设置是否编码数据
参数 - 以下是参数
$filter - true / false
返回 - 当前视图对象
例如:
$view->auto_filter(); $view = $view->auto_filter(false);
set_filename
用途 - 允许设置或更改视图文件。
参数 - 以下是参数 -
$file - 视图文件的路径,相对于views文件夹,fuel/app/views
返回 - 当前View对象
例如:
$view = new View(); $view>set_filename('path/to/view');
set
用途 - 设置一个或多个变量的值
参数 - 以下是参数
$key - 变量名或值的数组
$value - 值 / null
$filter - 编码设置,true / false
返回 - 当前视图对象
例如:
$view = new View(); $view->set(array('name' => 'Jon'));
set_global
set_global类似于set,只是它适用于所有视图,并且所有视图都可以访问这些变量。这是一个静态方法。
View::set_global('name', 'Jon', false);
set_safe
用途 - 设置一个或多个变量的值,并启用安全编码。
参数 - 以下是参数 -
$key - 变量名或值的数组
$value - 值 / null
返回 - 当前视图对象
例如:
$view = new View(); $view->set_safe(array('name' => 'Jon'), null);
get
用途 - 获取一个或多个变量的值
参数 - 以下是参数
$key - 变量名
$default - 如果找不到键,则返回的默认值
返回 - 输入键的值
例如:
$view = new View(); $name = $view>get('name'); // name = 'Jon'
render
用途 - 通过将其与局部和全局变量合并,将视图文件渲染成字符串
参数 - 以下是参数 -
$file − 视图文件名
返回 − 渲染后的视图文件字符串
例如:
$html = View::forge()->render('/path/to/view');
创建视图
为了理解视图,让我们修改控制器 `Controller_Employee` 的操作方法 `action_show`。
employee.php
<?php class Controller_Employee extends Controller { public function action_show() { return View::forge('employee/show'); } }
现在在 `views` 目录(位于 `fuel/app/views`)下创建一个名为 `employee` 的文件夹。然后,在 `employee` 文件夹内创建一个名为 `show.php` 的文件,并添加以下代码。
show.php
<h3> My first view </h3>
现在,请求 URL `https://127.0.0.1:8080/employee/show`,它将产生以下结果。
向视图传递数据
我们可以使用前面讨论过的视图方法向视图传递数据。下面是一个简单的例子。
employee.php
class Controller_Employee extends Controller { public function action_show() { $data = array(); //stores variables going to views $data['name'] = ‘Jon’; $data[‘job’] = ‘Designer’; //assign the view to browser output return View::forge('employee/show', $data); } }
现在,在视图文件中添加更改。
show.php
<html> <body> Hello, <?php echo $name; ?>. Your job is, <?php echo $job; ?>. </body> </html>
请求 URL 后,它将显示姓名和职位,如下所示:
视图过滤器
视图使用输出编码来传递任何你想要的内容。如果你想传递未过滤的数据,可以使用 `set` 方法。
employee.php
class Controller_Employee extends Controller { public function action_show() { $view = \View::forge('employee/show'); $view->set('name', 'Jon', true); $view->set('job', '<em>Designer</em>', false); return $view; } }
请求 URL 后,它将以强调样式显示职位详情,如下所示。
嵌套视图
FuelPHP 支持嵌套视图。在嵌套视图中,一个视图可以包含一个或多个视图。要在一个视图中设置另一个视图,可以使用 `render` 方法,如下所示。
employee.php
class Controller_Employee extends Controller { public function action_nestedview() { //assign variables $data = array(); $data['title'] = 'Home'; $data['name'] = 'Jon'; $data['job'] = 'Designer'; $views = array(); $views['head'] = View::forge('head', $data)->render(); $views['content'] = View::forge('employee/show', $data)->render(); return View::forge('layout', $views, false)->render(); } }
fuel/app/views/layout.php
<html> <head> <?php echo $head; ?> </head> <body> <?php echo $content; ?> </body> </html>
fuel/app/views/head.php
<title> <?php echo $title; ?> </title>
fuel/app/views/employee/show.php
Hello, <?php echo $name; ?>. Your job is, <?php echo $job; ?>.
请求 URL `https://127.0.0.1:8080/employee/nestedview` 并检查源视图后,将得到以下代码。
<html> <head> <title>Home</title> </head> <body> Hello, Jon. Your job is, Designer. </body> </html>
模板控制器
FuelPHP 提供了一个控制器 `Controller_Template`,它具有内置的布局概念。布局概念是使用控制器的 `before()` 和 `after()` 方法完成的。要使用模板控制器,需要使用 `Controller_Template` 而不是 `Controller` 来扩展控制器。使用 `after()`/`before()` 方法时,需要调用 `parent::before` 和 `parent::after`,否则模板会中断。
<?php class Controller_Test extends Controller_Template { public function before() { parent::before(); // do stuff } public function after($response) { $response = parent::after($response); // do stuff return $response; } }
template.php
这是 Fuel 中的默认模板文件。模板文件用于调用 JS、CSS、HTML 和调用视图局部文件。它位于 `fuel/app/views/`。模板用于将你的视图包装在一个带有页眉、页脚、侧边栏等的布局中。我们可以使用操作方法中的 `$template` 变量来更改默认模板,如下所示。
fuel/app/classes/controller/test.php
<?php class Controller_Test extends Controller_Template { public $template = 'template_test'; public function action_index() { $this->template->title = 'Example Page'; $this->template->content = View::forge('test/index'); } }
fuel/app/views/template_test.php
<!DOCTYPE html> <html> <head> <meta charset = "utf-8"> <title><?php echo $title; ?></title> <?php echo Asset::css('bootstrap.css'); ?> </head> <body> <div> <?php echo $content; ?> </div> </body> </html>
fuel/app/views/test/index.php
<h3>My Test page</h3>
现在,请求 URL `https://127.0.0.1:8080/test`,它将产生以下结果。
结果
<!DOCTYPE html> <html> <head> <meta charset = "utf-8"> <title>Example Page</title> <link type = "text/css" rel = "stylesheet" href = "https://127.0.0.1:8080/assets/css/bootstrap.css?1464964766" /> </head> <body> <div> <h3>My Test page</h3> </div> </body> </html>
生成视图页面
你可以使用 Fuel 的 Oil 控制台生成视图页面。以下是基本语法。
oil g controller <controller-name> <page1> <page2> ..
要生成一个带有主页和登录页面的管理员控制器,请使用以下命令。
oil g controller admin home login
结果
Creating view: /path/to/app/fuel/app/views/admin/home.php Creating view: /path/to/app/fuel/app/views/admin/login.php Creating controller: /path/to/app/fuel/app/classes/controller/admin.php
FuelPHP - 展示器
FuelPHP 在控制器之后提供了一个额外的层来生成视图。一旦控制器处理完输入并完成业务逻辑,它就会将控制权发送给 **Presenter**,Presenter负责处理额外的逻辑,例如从数据库获取数据、设置视图数据等,然后调用 View 对象。
我们可以使用 Presenter 类渲染视图,如下所示:
fuel/app/classes/controller/employee.php
public Controller_Employee extends Controller { public function action_welcome() { return Presenter::forge('employee/hello'); } }
Presenter 类的默认位置是 `fuel/app/classes/presenter/`。下面是一个简单的例子。
fuel/app/classes/presenter/employee/hello.php
<?php class Presenter_Employee_Hello extends Presenter { public function view() { $this->name = Request::active()->param('name', 'World'); } }
上述 Presenter 类的视图文件解析为相对于 `views` 文件夹的 `employee/hello.php`,如指定的那样。
fuel/app/views/employee/hello.php
<h3>Hi, <?php echo $name; ?></h3>
最后,更改路由以匹配员工的欢迎操作,如下所示:
fuel/app/config/routes.php
'employee/hello(/:name)?' => array('employee/welcome', 'name' => 'hello'),
现在,请求 URL `https://127.0.0.1:8080/employee/hello/Jon` 将渲染以下结果。
结果
FuelPHP - 模型 & 数据库
模型在 FuelPHP Web 框架中扮演着重要的角色。它代表应用程序的业务实体。它们要么由客户提供,要么从后端数据库获取,根据业务规则进行操作,然后持久化回数据库。让我们在本节学习模型以及它们如何与后端系统交互。
创建模型
在 FuelPHP 中,模型只是一个简单的 PHP 类,它扩展了内置的 Model 类。默认情况下,模型可能以 `Model_` 为前缀,类似于控制器,并且应该放在 `fuel/app/classes/model/` 文件夹中。让我们创建一个基本的员工模型,并在我们继续的过程中对其进行扩展。
fuel/app/classes/model/employee.php
<?php namespace Model; class Model_Employee extends \Model { public static function fetchAll() { // Code to fetch employee from database } }
定义模型后,只需在控制器中包含它,就可以在任何控制器中自由使用它,如下所示:
访问模型
use \Model\Employee; class Controller_Employee extends Controller { public function action_index() { $employees = Employee::fetchAll(); } }
数据库概述
FuelPHP 提供了自己的数据库抽象层来从数据库中获取数据。它提供基本的和高级的基于 ORM 的工具。基本工具包包括基于 DB、DBUtil 和 Query_Builer 的类。高级工具包是 Orm。Orm 工具包派生自基本工具包,并作为单独的包捆绑在一起。
数据库配置
FuelPHP 将数据库设置与主配置文件分开,该文件为 `fuel/app/config/db.php`。它支持每个环境的单独设置。目前,FuelPHP 支持 MySQL、MySQLi 和 PDO 驱动程序。示例设置如下:
<?php return array ( 'development' => array ( 'type' => 'mysqli', 'connection' => array ( 'hostname' => 'localhost', 'port' => '3306', 'database' => 'tutorialspoint_fueldb', 'username' => 'root', 'password' => 'password', 'persistent' => false, 'compress' => false, ), 'identifier' => '`', 'table_prefix' => '', 'charset' => 'utf8', 'enable_cache' => true, 'profiling' => false, 'readonly' => false, ), )
基于 DB 的工具包
DB 类是从应用程序访问数据库的最简单选项。它提供构建数据库查询、针对目标数据库执行查询以及最终获取结果的选项。`DB` 类与以下类交互并提供全面的数据库 API。
Database_Connection − 单例和与数据库交互的主要类
Database_Query − 执行 SQL 查询并获取结果的基本具体类
Database_Query_Builder − 构建 SQL 查询的基本抽象类
Database_Query_Builder_Join − 构建 SQL 连接的类
Database_Query_Builder_Where − 构建 SQL 查询条件的抽象类
Database_Query_Builder_Select − 构建 SQL 选择查询的具体类
Database_Query_Builder_Insert − 构建 SQL 插入查询的抽象类
Database_Query_Builder_Update − 构建 SQL 更新查询的抽象类
Database_Query_Builder_Delete − 构建 SQL 删除查询的抽象类
下图描述了类之间的关系以及类提供的方法。
DB API
让我们在本节学习 DB 类中最重要的方法。
instance
用途 − 创建并返回新的 `Database_Connection` 实例。
参数 −
$db − 配置文件中定义的数据库连接名称,可选。
返回 − 返回 `Database_Connection` 对象
例如:
$db = DB::instance(); $db = DB::instance('test');
query
用途 − 准备提供的 SQL 语句并返回 `Database_Query` 对象,该对象可用于插入、更新、删除或从数据库中获取数据。
参数 −
$query − SQL 语句,可能包含占位符;
$type − SQL 类型,可选 (DB::SELECT, DB::INSERT, DB::UPDATE 和 DB::DELETE)
返回 − 返回 `Database_Query` 对象
例如:
$query = DB::query('SELECT * FROM 'employees'');
last_query
用途 − 获取最后执行的查询
参数 − 无
返回 − 返回最后执行的查询
例如:
$employees = DB::Select('Select * from 'employee''); $sql = DB::last_query();
select
用途 − 生成查询的选择部分
参数 −
$columns − 数据库列名称列表
返回 − 返回 `Database_Query_Builder_Select` 对象
例如:
$query = DB::select(); // Select * $query = DB::select('id', 'name'); // Select id, name
select_array (DB)
它类似于 `select`,只是我们可以将列作为数组发送。
$query = DB::select_array(array('id', 'name')); // Select id, name
insert
用途 − 生成查询的插入部分
参数 −
$table_name − 数据库表名称;
$columns − 表列数组
返回 − 返回 `Database_Query_Builder_Insert` 对象
例如:
$query = DB::insert('employee'); // Insert into employee $query = DB::insert('employee', array('id', 'name')); // Insert into employee (id, name)
update
用途 − 生成查询的更新部分
参数 −
$table_name − 数据库表名称
返回 − 返回 `Database_Query_Builder_Update` 对象
例如:
$query = DB::update('employee'); // update `employee`
delete
用途 − 生成查询的删除部分
参数 −
$table_name − 数据库表名称
返回 − 返回 `Database_Query_Builder_Delete` 对象
例如
$query = DB::delete('employee'); // delete from 'employee'
Query API
Database_Query 提供了一个选项来设置数据库连接、执行查询并将结果作为关联数组或对象获取。让我们看看 `Database_Query` 类提供的方法。
set_connection
用途 − 设置要针对其执行查询的数据库(数据库连接详细信息)
参数 − `$db` - 数据库连接名称
返回 − 返回 `Database_Query` 对象
例如:
$query = DB::query('DELETE * FROM employee', DB::DELETE); $query->set_connection('2nd-db');
param
用途 − 将值设置为在 Query 对象中定义的参数
参数 −
$param − 参数名称;
$value − 参数的值
返回 − 返回 `Database_Query` 对象
例如:
// set some variables $table = 'employee'; $id = 1; $name = 'Jon'; // don't use $query = DB::query('SELECT * FROM '.$table.'. WHERE id = '.$id.' AND name = "'.$name.'"'); // but use $query = DB::query('SELECT * FROM :tablename WHERE id = :id AND name = :name'); $query->param('tablename', 'employee'); $query->param('id', $id); $query->param('name', $name);
类似的方法
parameters 是一个类似的对象,除了它提供一次给多个值的选项。
$query->parameters (array( 'tablename' => $table, 'id' => $id, 'name' => $name });
bind
用途 − 将变量设置为在 Query 对象中定义的参数
参数 −
$param − 参数名称
$var − 要将参数绑定到的变量
返回 − 返回 `Database_Query` 对象
例如:
// bind a query parameter $table = 'employee'; $query = DB::query('DELETE * FROM :tablename', DB::DELETE); $query->bind('tablename', $table); // update the variable $table = 'employee_salary'; // DELETE * FROM `employee_salary`; $sql = $query->compile();
compile
用途 − 将定义的 Query 对象编译成 SQL 查询
参数 −
$db − 连接字符串,可选
返回 −
例如:
// assign a value to a query parameter $table = 'employee'; $query = DB::query('DELETE * FROM :tablename', DB::DELETE); $query->param('tablename', $table); // compile the query, returns: DELETE * FROM employee $sql = $query->compile();
execute
用途 − 执行在 Query 对象中定义的查询并返回结果
参数 −
$db − 数据库连接名称
返回 − 返回结果
例如:
// assign a value to a query parameter $table = 'employee'; $query = DB::query('DELETE * FROM :tablename', DB::DELETE); $query->param('tablename', $table); // execute the query $query->execute();
as_assoc
用途 − 将返回类型设置为关联数组而不是对象
参数 − 无
返回 − 返回当前对象
例如:
$query = DB::query('SELECT * FROM employee', DB::SELECT); $result = $query->as_assoc()->execute(); foreach ($result as $row) { echo $row['id']; }
as_object
用途 − 将返回类型设置为对象而不是关联数组
参数 − 无
返回 − 返回当前对象
例如:
$query = DB::query('SELECT * FROM employee', DB::SELECT); $result = $query->as_object()->execute(); foreach ($result as $row) { echo $row->id; } // have ORM model objects return instead $result = $query->as_object('Model_Employee')->execute();
Query Builder API
基于 Query builder(`Query_Builder`)的类提供动态构建 SQL 查询的选项。它有四个类,每个类用于选择(`Query_Builder_Select`)、插入(`Query_Builder_Insert`)、更新(`Query_Builder_Update`)和删除(`Query_Builder_Delete`)查询。这些类派生自 `Query_Builder_Where` 类(生成条件的选项),而 `Query_Builder_Where` 类本身又派生自 `Query_Builder`,它是所有类的基础。
让我们看看 `Query_Builder` 类提供的方法。
select
用途 − 生成选择查询的列。
参数 −
$columns − 列列表,可选
返回 − 返回当前实例
例如:
$query = DB::select('name') // select `name` $query = DB::select(array('first_name', 'name')) // select `first_name` as `name`
from
用途 − 生成选择查询的表详细信息
参数 −
$tables − 表列表
返回 − 返回当前实例
例如:
$query = DB::select('name')->from('employee') // select `name` from `employee`
where
用途 − 生成选择、插入和更新查询的条件
参数 −
$column − 列名或数组(`$column`, `$alias`);
$op − 逻辑运算符,=,!=,IN,BETWEEN 和 LIKE,可选;
$value − 列值
返回 − 返回当前实例
例如:
$query = DB::select('name')->from('employee') $query = $query->where('name', '=', 'Jon'); // select `name` from `employee` where `name` = `Jon`;
类似的方法
类似的方法有 `where_open()`、`and_where_open()`、`or_where_open()`、`where_close()`、`and_where_close()`、`or_where_close()`。它们类似于 `where()` 方法,只是它们在条件周围添加了额外的关键字和括号。以下是一个示例代码。
$query = DB::select('*')->from('employee'); $query->where('email', 'like', '%@gmail.com'); $query->or_where_open(); $query->where('name', 'Jon'); $query->and_where('surname', 'Peter'); $query->or_where_close(); // SELECT * FROM `employee` WHERE `email` LIKE "%gmail.com" OR (`name` = "Jon" AND `surname` = "Peter")
join
目的 − 生成 select 查询的表连接
参数 −
$table − 表名或数组 ($table, $alias);
$type − 连接类型 (LEFT, RIGHT, INNER 等)
返回 − 返回当前实例
示例
$query = DB::select('name')->from('employee')->join('employee_salary') // select `name` from `employee` JOIN `employee_salary`
on
目的 − 生成 select 查询中连接的条件
参数 −
$c1 − 表名或带有别名的表名数组;
$op − 逻辑运算符;
$c2 − 表名或带有别名的表名数组
返回 − 返回当前实例
例如:
$query = DB::select('name')->from('employee')->join('employee_salary') $query = $query->on('employee.employee_id', '=', 'employee_salary.employee_id') // select `name` from `employee` JOIN `employee_salary` on // `employee.employee_id` = `employee_salary.employee_id`
类似的方法
相关方法为 and_on() 和 or_on()。它们与 on() 类似,只是在连接周围添加了额外的关键字和括号。
group_by
目的 − 生成 group by 查询
参数 − $columns − 用于分组结果的列名
返回 − 返回当前实例
例如:
$query = DB::select('name')->from('employee') $query = $query->group_by('name'); // select `name` from `employee` group by `name`
having
目的 − 生成 SQL 查询的 group by 条件
参数 − $column − 列名或数组 ($column, $alias); $op − 逻辑运算符,=, !=, IN, BETWEEN 和 LIKE,可选; $value − 列值
返回 − 返回当前实例
示例
$query = DB::select('name')->from('employee') $query = $query->group_by('name'); $query = $query->having('name', '!=', 'Jon'); // select `name` from `employee` group by `name` having `name` != `Jon`
类似的方法
类似的方法有 having_open(),and_having_open(),or_having_open(),having_close(),and_having_close(),or_having_close()。它们与 having() 方法类似,只是在条件周围添加了额外的关键字和括号。
reset
目的 − 重置查询
参数 − 无
返回 − 返回当前实例
例如:
$query = DB::select('name')->from('employee') $query->reset() $query = DB::select('name')->from('employee_salary') // select `name` from `employee_salary`
DBUtil 类
DBUtil 类提供了一个管理和执行常规数据库操作的选项。一些重要的方法如下:
- set_connection - 设置默认连接
DBUtil::set_connection('new_database');
- create_database - 创建数据库。
DBUtil::create_database('my_database');
- drop_database - 删除数据库。
DBUtil::drop_database('my_database');
- table_exists - 检查给定的表是否存在。
if(DBUtil::table_exists('my_table')) { // Table exists } else { // Table does NOT exist, create it! }
- drop_table - 删除表。
DBUtil::drop_table('my_table');
- create_table - 创建表。
\DBUtil::create_table ( 'users', array ( 'id' => array('type' => 'int', 'auto_increment' => true), 'name' => array('type' => 'text'), ), );
ORM 工具包
FuelPHP 使用基于流行的活动记录模式的 ORM 概念提供高级数据库层。该工具包包含在应用程序中,但默认情况下未配置。它作为一个包捆绑在一起,包名为 orm。我们可以在主配置文件fuel/app/config/config.php中添加以下配置来加载 orm 工具包。
'always_load' => array ( 'packages' => array ( 'orm', ), ),
创建模型
ORM 提供了基本的模型类 Orm\Model。我们需要用 orm 模型扩展我们的模型才能使用 ORM 功能。以下是一个示例代码。
class Model_Employee extends Orm\Model {}
配置
ORM 提供了一组设置来配置模型以使用 ORM 功能。它们如下:
连接 − 在模型中设置静态_connection属性以指定连接名称。
class Model_Employee extends Orm\Model { protected static $_connection = "production"; }
表名 − 在模型中设置静态_table_name属性以指定后端表的表名。
class Model_Employee extends Orm\Model { protected static $_table_name = 'employee'; }
主键 − 在模型中设置静态_primary_key属性以指定后端表的主键。
class Model_Employee extends Orm\Model { protected static $_primary_key = array('id'); }
列 − 在模型中设置静态 _properties 属性以指定后端表的列。它支持数据类型、标签、验证、表单元素等。
class Model_Employee extends Orm\Model { protected static $_properties = array ( 'id', 'name' => array ( 'data_type' => 'varchar', 'label' => 'Employee Name', 'validation' => array ( 'required', 'min_length' => array(3), 'max_length' > array(80) ), 'form' => array ( 'type' => 'text' ), ), 'age' => array ( 'data_type' => 'int', 'label' => 'Employee Age', 'validation' => array ( 'required', ), 'form' => array ( 'type' => 'text' ), ), ); }
条件 − 设置静态_conditions属性以设置条件和排序选项。
class Model_Employee extends Orm\Model { protected static $_conditions = array ( 'order_by' => array('id' => 'desc'), 'where' => array ( array('is_active', > true), ), ); }
观察者 − Orm 提供基于观察者的事件系统,以便为特定事件添加行为。要添加行为,首先在模型中设置_observers属性。然后,将行为定义为一个类,并将其与事件一起设置在_observers属性中。如果没有指定事件,则该行为将针对所有事件调用。我们也可以指定多个行为。
class Model_Employee { protected static $_observers = array ( 'example', // will call Observer_Example class for all events 'Orm\\Observer_CreatedOn' => array ( 'events' => array('before_insert'), // will only call Orm\Observer_CreatedOn at before_insert event ) ); }
创建
配置好模型后,我们可以直接开始使用这些方法。Orm 提供了一个save方法来将对象保存到数据库中。我们可以使用配置的属性设置数据,如下所示:
// option 1 $new = new Model_Employee(); $new->name = 'Jon'; $new->save(); // option 2, use forge instead of new $new = Model_Employee::forge(); $new->name = 'Jon'; $new->save(); // option 3, use array for properties $props = array('name' => 'Jon'); $new = Model_Employee::forge($props); $new>save();
读取
ORM 提供了一个 find 方法来从数据库中获取数据并绑定到对象中。find 方法的工作方式取决于输入参数。让我们看看不同的选项:
按主键 − 指定主键将根据配置表的匹配主键返回记录。
$employee = Model_Employee::find(1);
第一/最后一条记录 − 指定“first”或“last”将分别获取第一条记录或最后一条记录。我们也可以传递排序选项。
$entry = Model_Employee::find('first'); $entry = Model_Article::find('last', array('order_by' => 'id'));
全部 − 指定“all”将从配置表中获取所有记录。我们也可以指定排序选项和条件。
$entry = Model_Employee::find('all'); $entry = Model_Article::find ('all', array ( 'where' => array ( array ('name', 'Jon'), ), 'order_by' => array ('id' => 'desc'), ));
我们可以将基本数据库工具包的 Query API 与模型一起使用,以实现高级搜索选项,如下所示。
$query = Model_Employee::query()->where('category_id', 1)->order_by('date', 'desc'); $number_of_employees = $query->count(); $latest_employee = $query->max('id'); $young_employee = $query->min('age'); $newest_employee = $query->get_one(); $employees = $query->limit(15)->get();
更新
更新模型与创建模型相同,只是不需要创建新模型,只需使用 find 方法获取要更新的模型,更新属性,然后调用 save 方法,如下所示。
$entry = Model_Employee:find(4); $entry->name = 'Peter'; $entry->save();
删除
ORM 提供了一个 delete 方法来删除模型。只需获取对象并调用 delete 方法即可。
$entry = Model_Employee:find(4); $entry->delete();
工作示例
让我们在本章中创建一个工作示例来理解模型和数据库。
创建数据库
使用以下命令在 MySQL 服务器中创建一个新数据库。
create database tutorialspoint_fueldb
然后,使用以下命令在数据库中创建一个表。
create table employee(id int primary key, name varchar(20), age int not null);
配置数据库
让我们使用数据库配置文件 *fuel/app/config/db.php* 来配置数据库。添加以下更改以连接 MySQL 服务器。
<?php return array ( 'development' => array ( 'type' => 'mysqli', 'connection' => array ( 'hostname' => 'localhost', 'port' => '3306', 'database' => 'tutorialspoint_fueldb', 'username' => 'root', 'password' => 'pass', 'persistent' => false, 'compress' => false, ), 'identifier' => '`', 'table_prefix' => '', 'charset' => 'utf8', 'enable_cache' => true, 'profiling' => false, 'readonly' => false, ), 'production' => array ( 'type' => 'mysqli', 'connection' => array ( 'hostname' => 'localhost', 'port' => '3306', 'database' => 'tutorialspoint_fueldb', 'username' => 'root', 'password' => 'pass', 'persistent' => false, 'compress' => false, ), 'identifier' => '`', 'table_prefix' => '', 'charset' => 'utf8', 'enable_cache' => true, 'profiling' => false, 'readonly' => false, ), );
包含 ORM 包
更新主配置文件fuel/app/config/config.php,通过添加以下配置来包含 ORM 包。
'always_load' => array ( 'packages' => array ( 'orm' ), ),
现在,ORM 已在您的应用程序中启用
创建员工模型
在模型文件夹“fuel/app/classes/model”下创建一个新的模型 Employee。它定义如下。
Employee.php
<?php class Model_Employee extends Orm\Model { protected static $_connection = 'production'; protected static $_table_name = 'employee'; protected static $_primary_key = array('id'); protected static $_properties = array ( 'id', 'name' => array ( 'data_type' => 'varchar', 'label' => 'Employee Name', 'form' => array ( 'type' => 'text' ), ), 'age' => array ( 'data_type' => 'int', 'label' => 'Employee Age', 'form' => array ( 'type' => 'text' ), ), ); }
创建操作
在位于fuel/app/classes/controller/employee.php的 Employee 控制器中创建一个新的操作action_model,如下所示。
class Controller_Employee extends Controller { public function action_model() { // db based sql command to delete all employees $query = db::query('delete from `employee`'); $query->execute('production'); // orm based query to add new employees $model = new model_employee(); $model->name = "john"; $model->age = 25; $model->save(); $model = new model_employee(); $model->name = "peter"; $model->age = 20; $model->save(); // orm based query to fetch all employee data $data = array(); $data['emps'] = model_employee::find('all'); return response::forge(view::forge('employee/model', $data)); } }
创建视图
现在,创建一个位于“fuel/app/views/employee”的视图文件model.php。在文件中添加以下更改。
<ul> <?php foreach($emps as $emp) { ?> <li><?php echo $emp['name']; ?></li> <?php } ?> </ul>
现在,请求 URL,https://127.0.0.1:8080/employee/model,它将产生以下结果。
结果
FuelPHP - 表单编程
FuelPHP 提供了三个类,Form、Fieldset 和Input,来执行表单编程。
Form 类提供了一个创建所有 HTML 表单元素的选项。
Fieldset 类提供了一个通过更高级别的方法创建 html 元素的选项,集成了模型和验证。
Input 类提供了一个解析通过 html 表单以及 http 参数、服务器变量和用户代理提交的数据的选项。
在本章中,让我们学习 FuelPHP 中的表单编程。
表单
如前所述,Form 类提供了创建 html 表单元素的方法,重要的方法如下:
open()
open() 用于创建一个新表单。它提供以下两个参数:
$attributes − 表单标签的属性,可以是数组或只是一个 action URL 字符串。
$hidden − 隐藏字段名称及其值的数组。
echo Form::open('/employee/add'); echo Form::open(array('action' => '/employee/add', 'method' => 'post'));
close()
close() 只需关闭表单。
echo Form::close();
input()
input() 创建 html 输入元素。它有以下三个参数:
$field − 输入元素的名称
$value − 输入元素的值
$attributes − 输入元素的属性数组
echo Form::input('name', 'jon', array('style' => 'border: 20px;'));
label 元素
label 创建 html label 元素。它有以下三个参数:
$label − 要显示的标签
$id − 关联的表单元素 ID
$attributes − label 元素的属性数组
echo Form::label('Employee Name', 'employee_name');
hidden
hidden 与 input 方法类似,只是它将输入元素的类型设置为隐藏。
password
password 与 input 方法类似,只是它将输入元素的类型设置为密码。
radio
radio 与 input 方法类似,只是它将输入元素的类型设置为单选按钮。它有以下四个参数:
$field − 输入元素的名称
$value − 输入元素的值
$checked − 项目是否被选中 (true / false)
$attributes − 输入元素的属性数组
echo Form::label('Male', 'gender'); echo Form::radio('gender', 'Male', true); echo Form::label('Female', 'gender'); echo Form::radio('gender', 'Female');
checkbox
checkbox 与 input 方法类似,只是它将输入元素的类型设置为复选框。它有以下四个参数:
$field − 输入元素的名称
$value − 输入元素的值
$checked − 项目是否被选中 (true / false)
$attributes − 输入元素的属性数组
echo Form::label('Male', 'gender'); echo Form::checkbox('gender', 'Male', true); echo Form::label('Female', 'gender'); echo Form::checkbox('gender', 'Female');
file
file 与 input 方法类似,只是它将输入元素的类型设置为文件。
textarea
textarea 创建 html textarea 元素。它有以下三个参数:
$field − textarea 元素的名称
$value − textarea 元素的值
$attributes − textarea 元素的属性数组
echo Form::textarea ('description', 'original data (value)', array ('rows' => 6, 'cols' => 8));
select
select 创建一个 HTML select 元素。它有以下四个参数:
$field − select 元素的名称
$values − 初始选择值
$options − 选项数组。选项可以使用嵌套数组进行分组
$attributes − 输入元素的属性数组
echo Form::select ( 'country', 'none', array ( 'none' => 'None', 'asia' => array ( 'in' > 'India', 'cn' => 'China' ), 'us' => 'United States' ) );
submit
submit 与 input 方法类似,只是它将输入元素的类型设置为提交。
button
button 创建 html button 元素。它有以下三个参数:
$field − button 元素的名称
$value − button 元素的值
$attributes − button 元素的属性数组
echo Form::button('emp_submit', 'Submit');
reset
reset 与 input 方法类似,只是它将输入元素的类型设置为重置。
fieldset_open
fieldset_open 创建 html fieldset 和 legend 元素。它有以下两个参数:
attributes − fieldset 元素的属性数组
legend − 要创建的图例名称
// returns <fieldset class = "example-class" id = "example-id"> <legend> Custom Legend </legend> echo Form::fieldset_open (array ( 'class' => 'example-class', 'id' => 'exampleid', 'legend' => 'Custom Legend' ));
fieldset_close
fieldset_close 创建 HTML fieldset 关闭标签。
// returns </fieldset> echo Form::fieldset_close();
Input 类
Input 类提供方法来读取所有请求数据以及表单详细信息。一些重要的方法如下:
uri
uri 返回请求的当前 URI
// request: https://127.0.0.1:8080/employee/welcome echo Input::uri(); // return /employee/welcome
method
method 返回请求中使用的 HTTP 方法
echo Input::method() // "POST"
get
get 可用于读取 $_GET 变量。它有以下两个参数:
$index − $_GET 数组的索引
$default − 如果找不到索引,则为默认值。
echo Input::get('age', '20'); // returns $_GET['age']
post
post 可用于读取 $_POST 变量。它有以下两个参数:
$index − $_POST 数组的索引
$default − 如果找不到索引,则为默认值
echo Input::get('age', '20'); // returns $_POST['age']
param
param 可用于从 $_GET、$_POST、$_PUT 或 $_DELETE 变量中获取项目。它有以下两个参数:
$index − 数组的索引
$default − 如果找不到索引,则为默认值
如果没有指定参数,它将返回所有项目。
echo Input::param('age', '20'); // returns $_POST['age']
file
file 可用于读取 $_FILE 变量。它有以下两个参数:
$index − $_POST 数组的索引
$default − 如果找不到索引,则为默认值
echo Input::file();
is_ajax
is_ajax 如果请求是通过 AJAX 发出的,则返回 true。
echo Input::is_ajax() // return false
protocol
protocol 返回请求中使用的 HTTP 协议。
echo Input::protocol() // returns "HTTP"
ip
ip 返回发出请求的 IP 地址。
echo Input::ip() // returns "84.45.34.24" (Public IP Address)
real_ip
real_ip 尝试返回发出请求的真实 IP 地址(如果客户端位于代理后面)。
echo Input::real_ip() // returns "10.76.12.1" (local private IP Address)
server
服务器端 可读取 $_SERVER 变量。它具有以下两个参数:
$index − $_POST 数组的索引
$default − 如果找不到索引,则为默认值。
echo Input::server('HTTP_HOST'); // returns localhost:8080
referrer
referrer 返回 $_SERVER 变量中的 referrer。这是一个获取当前请求的 HTTP referrer 的快捷方法。
user_agent
user_agent 返回 $_SERVER 变量中的 user agent。这是一个获取当前请求的 HTTP user agent 的快捷方法。
query_string
query_string 返回 $_SERVER 变量中的 query string。这是一个获取当前请求的 query string 的快捷方法。
headers
headers 返回特定或所有 HTTP 头信息。它具有以下两个参数:
$index − HTTP 头的名称
$default − 如果找不到索引,则为默认值。
echo Input::headers('Content-Type'); // returns "text/html"
extension
extension 返回当前请求的 URI 扩展名。
// Example URL: https://127.0.0.1/test/ echo Input::extension(); // NULL // Example URL: https://127.0.0.1/test.html echo Input::extension(); // 'html'
工作示例
让我们创建一个简单的表单,使用 Form 和 Input 类来添加新员工。
创建表单
在 employee 控制器中创建一个新的 action,get_add,如下所示。
public function get_add() { return Response::forge(View::forge('employee/add')); }
现在,为该 action 添加视图,fuel/app/views/employee/add.php,如下所示。
<!DOCTYPE html> <html lang = "en"> <head> <title>Employee :: add page</title> <meta charset = "utf-8"> <meta name = "viewport" content = "width = device-width, initial-scale = 1"> <?php echo Asset::css('bootstrap.css'); ?> </head> <body> <div class = "container"> <?php echo Form::open(array('action' => 'employee/add', 'method' => 'post')); ?> <div class = "form-group"> <?php echo Form::label('Employee name:', 'name'); echo Form::input('name', '', array('class' => 'form-control')); ?> </div> <div class = "form-group"> <?php echo Form::label('Employee age:', 'age'); echo Form::input('age', '', array('class' => 'form-control')); ?> </div> <?php echo Form::button('frmbutton', 'Submit', array( 'class' => 'btn btn-default')); ?> <?php echo Form::close(); ?> </div> </body> </html>
这里,我们使用了bootstrap来设计表单。FuelPHP 完全支持 bootstrap 组件。现在,请求页面 https://127.0.0.1:8080/employee/add 将显示以下表单。
处理表单
创建一个新的 action,post_add,用于处理表单并将用户输入的员工数据添加到 employee 控制器中的数据库中,如下所示。
public function post_add() { $name = Input::post('name'); $age = Input::post('age'); $model = new model_employee(); $model->name = $name; $model->age = $age; $model->save(); Response::redirect('employee/list'); }
在这里,一旦用户输入的数据保存到数据库中,我们将被重定向到员工列表页面。接下来,我们将创建员工列表页面。
员工列表
创建一个新的 action,action_list,用于列出数据库中的员工,如下所示。
public function action_list() { $data = array(); $data['emps'] = model_employee::find('all'); return Response::forge(view::forge('employee/list', $data)); }
为上述 action 创建一个新的视图,fuel/app/views/employee/list,如下所示。
<ul> <?php foreach($emps as $emp) { ?> <li><?php echo $emp['name']; ?></li> <?php } ?> </ul>
检查表单
现在,请求 URL,https://127.0.0.1:8080/employee/add,输入一些员工数据(如下面的截图所示)并提交表单。
然后,它将显示数据库中所有员工(包括新添加的员工),如下所示:
FuelPHP - 验证
验证是 Web 应用程序中频繁且最重复的任务之一。用户在表单中输入所需数据并提交。然后,Web 应用程序需要在处理数据之前验证数据。例如,用户输入员工数据,post_action 需要在保存到数据库之前进行验证。FuelPHP 为此目的提供了一个非常简单的类,Validation。
在 FuelPHP 中,验证的概念非常简单,它通过 Validation 类提供各种方法来正确验证表单。以下是验证的工作流程:
步骤 1 − 使用forge方法创建一个新的 Validation 对象。
$val = Validation::forge();
步骤 2 − 使用 add 方法添加需要验证的字段。
$val->add('name', 'Employee name');
步骤 3 − 使用add_rule方法为添加的字段设置验证规则。
$val->add('name', 'Employee name')->add_rule('required'); $val->add('age', 'Employee age')->add_rule('required') ->add_rule('numeric_min', 20) ->add_rule('numeric_max', 30);
步骤 4 − 调用 run 方法来验证数据。
// run validation on just post if ($val->run()) { // success } else { // falier }
步骤 5 − 使用 validated 和 error 分别获取有效和无效的字段。
$vars = $val->validated(); $vars = $val->error();
规则
FuelPHP 包含许多验证规则,并且还提供创建新规则的选项。Validation 类支持的规则如下:
required − 必须输入的值
required_with − 设置另一个字段作为伴随字段。如果设置了该字段,则也需要设置伴随字段。
match_value − 设置要与字段值匹配的值。
match_pattern − 设置要与字段值匹配的正则表达式。
match_field − 设置另一个字段的值作为要与字段值匹配的值。
match_collection − 设置要与字段值匹配的集合。
min_length − 设置字段值的最小长度。
max_length − 设置字段值的最大长度。
exact_length − 设置字段值的精确长度。
valid_date − 将字段值设置为有效的日期。
valid_email − 将字段值设置为有效的电子邮件地址。
valid_emails − 将字段值设置为有效的电子邮件地址,用逗号分隔。
valid_url − 将字段值设置为有效的 URL。
valid_ip − 将字段值设置为有效的 IP 地址。
numeric_min − 设置字段值的最小值。
numeric_max − 设置字段值的最大值。
numeric_between − 设置字段值的最小值和最大值。
valid_string − 与正则表达式类似,但更简单。
$val->add('username', 'User name')->add_rule('valid_string', array('alpha, dots');
这里,alpha 指的是字母字符,点指的是 (.)。有效的字符串仅包含字母字符和 (.) 的字符串。其他选项包括大写字母、小写字母、特殊字符、数字、空格等。
工作示例
我们可以更新添加员工功能以包含验证。只需更新 employee 控制器的post_add方法,如下所示。
public function post_add() { $val = Validation::forge(); $val->add('name', 'Employee name')->add_rule('required'); $val->add('age', 'Employee age')->add_rule('required') ->add_rule('numeric_min', 20) ->add_rule('numeric_max', 30); if ($val->run()) { $name = Input::post('name'); $age = Input::post('age'); $model = new model_employee(); $model->name = $name; $model->age = $age; $model->save(); Response::redirect('employee/list'); } else { Response::redirect('employee/add'); } }
在这里,我们指定了name和 age 为必填字段。age需要在 20 到 30 之间。如果两个规则都有效,则将保存员工数据并重定向到员工列表页面。否则,将拒绝员工数据并重定向到添加员工页面。
FuelPHP - 高级表单编程
FuelPHP 通过 Fieldset 和 Fieldset_Field 类提供高级表单编程。Fieldset提供了一种面向对象的方式来创建表单。它完全支持模型。它还内置支持客户端和服务器端验证。要创建一个完整的表单,创建具有适当表单和验证设置的模型就足够了。让我们在本节中学习关于 Fieldset 类的知识以及如何使用它来创建表单。
Fieldset
Fieldset 是Fieldset_Field对象的集合。Fieldset_Field 定义表单的单个条目,例如 firstname、lastname 等,以及验证。Fieldset 类具有添加/编辑/删除字段的方法。它可以选择识别模型中定义的字段并从给定的模型创建字段。Fieldset在后台使用 Form 和 Validation 类来完成实际工作。让我们看看 Fieldset 类的一些重要方法。
forge
forge 创建一个新的 Fieldset 实例。它具有以下两个参数:
$name − fieldset 的标识符
$config − 配置数组。可能的选项是validation_instance和form_instance。validation_instance可以具有Validation对象,form_instance可以具有 Form 对象。
$employee_form = Fieldset::forge('employee');
instance
instance 通过标识符返回先前创建的 Fieldset 实例。
$employee_form = Fieldset::instance('employee');
get_name
获取 fieldset 实例的标识符。
$employee_form = Fieldset::forge('employee'); $name = $employee_form->get_name();
add
add 创建一个新的 Fieldset_Field 实例并将其添加到当前 fieldset。它包含以下四个参数:
$name − 字段的名称
$label − 字段的标签
$attributes − HTML 标签属性
$rules − 验证规则
$employee_field = $employee_form-> add ( 'employee_lastname', 'Lastname', array ('class' => 'pretty_input') ); // with validation rules $employee_form->add ( 'email', 'E-mail', array('type' => 'email', 'class' => 'pretty_input'), array('required', 'valid_email') );
add_before
add_before 与 add 类似,只是它还有一个额外的参数来指定将在其之前添加新创建字段的字段。
$employee_form->add_before ( 'employee_firstname', 'Firstname', array ('class' => 'pretty_input'), array(), 'employee_lastname' );
delete
delete 从 fieldset 中删除指定的字段。
$employee_form->delete('employee_firstname');
field
field 获取 fieldset 中的所有字段或指定的字段。
$fields = $employee_form->field(); $lastname_field = $employee_form->field('employee_lastname');
build
build 是$this->form()->build()的别名。生成表单的 HTML 标记。
$employee_form->build(Uri::create('employee/add'));
enable
enable 重新启用先前禁用的字段。
$employee_form->enable('employee_firstname');
disable
disable 允许禁用 fieldset 中的字段不被构建。
$employee_form->disable('employee_firstname');
form
form 返回当前 fieldset 的 Form 实例。
$form = employee_form->form();
add_model
add_model 将模型的字段添加到 fieldset。它具有以下三个参数:
$class − 类名
$instance − 类的实例,用于填充字段的值
$method − 类中的方法名称。此方法用于将字段添加到 fieldset。Orm\Model 具有所需的方法。默认方法名称设置为 set_form_fields。
$employee_form = Fieldset::forge('employee'); $employee_form->add_model('Model_Employee');
populate
populate 使用模型实例设置 fieldset 中字段的初始值。
$emp = new Model_Employee(); $emp->name = "Jon"; $employee_form->populate($emp);
repopulate
repopulate 与 populate 相同,只是它重新填充 fieldset 中的字段。
validation
validation 获取当前 fieldset 的验证实例。
$validation = $employee_form->validation();
validated
$this->validation()->validated() 的别名。
input
$this->validation()->input() 的别名。
error
$this->validation()->error() 的别名。
show_errors
$this->validation()->show_errors() 的别名。
工作示例
让我们使用 Fieldset 类创建一个高级表单来在我们的示例员工应用程序中添加新员工。
更新模型
使用必要的验证规则更新员工模型,并添加验证观察者,如下所示。
<?php class Model_Employee extends Orm\Model { protected static $_connection = 'production'; protected static $_table_name = 'employee'; protected static $_primary_key = array('id'); protected static $_properties = array ( 'id', 'name' => array ( 'data_type' => 'varchar', 'label' => 'Employee Name', 'validation' => array ( 'required', 'min_length' => array(3), 'max_length' => array(80) ), 'form' => array ( 'type' => 'text' ), ), 'age' => array ( 'data_type' => 'int', 'label' => 'Employee Age', 'validation' => array ( 'required', ), 'form' => array ('type' => 'text' ), ), ); // Just add the Observer, and define the required event protected static $_observers = array('Orm\\Observer_Validation' => array ( 'events' => array('before_save'))); }
在这里,我们为 name 和 age 字段定义了验证规则,并添加了一个新的观察者,用于在将模型保存到数据库之前执行服务器端验证。相同的验证规则还将在表单中创建必要的输入验证属性。
创建表单
在 employee 控制器中创建一个新的 action,action_advancedform,如下所示。
public function action_advancedform() { // create a new fieldset and add employee model $fieldset = Fieldset::forge('employee')->add_model('Model_Employee'); // get form from fieldset $form = $fieldset->form(); // add submit button to the form $form->add('Submit', '', array('type' => 'submit', 'value' => 'Submit')); // build the form and set the current page as action $formHtml = $fieldset->build(Uri::create('employee/advancedform')); // set form in data $data = array(); $data['form'] = $formHtml; return Response::forge(View::forge('employee/advancedform', $data, false)); }
在这里,我们使用 fieldset 创建了表单,并将表单发送到视图。接下来,为 action 添加视图,fuel/app/views/employee/advancedform.php,如下所示。
<!DOCTYPE html> <html lang = "en"> <head> <title>Employee :: add page</title> <meta charset = "utf-8"> <meta name = "viewport" content = "width = device-width, initial-scale = 1"> <?php echo Asset::css('bootstrap.css'); ?> <style> table { width: 90%; } table tr { width: 90% } table tr td { width: 50% } input[type = text], select { width: 100%; padding: 12px 20px; margin: 8px 0; display: inline-block; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input[type = submit] { width: 100%; background-color: #3c3c3c; color: white; padding: 14px 20px; margin: 8px 0; border: none; border-radius: 4px; cursor: pointer; } div { border-radius: 5px; background-color: #f2f2f2; padding: 20px; } </style> </head> <body> <div class = "container"> <?php if(isset($errors)) { echo $errors; } echo $form; ?> </div> </body> </html>
现在,请求页面https://127.0.0.1:8080/employee/add将显示以下表单。
处理表单
更新 action 方法 action_advancedform 以处理表单并将用户输入的员工数据添加到 employee 控制器中的数据库中,如下所示。
public function action_advancedform() { // create a new fieldset and add employee model $fieldset = Fieldset::forge('employee')->add_model('Model_Employee'); // get form from fieldset $form = $fieldset->form(); // add submit button to the form $form->add('Submit', '', array('type' => 'submit', 'value' => 'Submit')); // build the form and set the current page as action $formHtml = $fieldset->build(Uri::create('employee/advancedform')); if (Input::param() != array()) { try { $article = Model_Employee::forge(); $article->name = Input::param('name'); $article->url = Input::param('age'); $article->save(); Response::redirect('employee/list'); } catch (Orm\ValidationFailed $e) { $view = View::forge('employee/advancedform'); $view->set('form', $formHtml, false); $view->set('errors', $e->getMessage(), false); } } return Response::forge($view); }
在这里,一旦用户输入的数据经过验证并保存到数据库中,我们将被重定向到员工列表页面。否则,我们将再次看到表单。
创建表单
现在,请求 URL,https://127.0.0.1:8080/employee/add,输入一些员工数据并提交表单。如果未提供数据,则表单将提示用户输入数据(如下面的截图所示)。
如果用户绕过客户端验证,则服务器将验证表单并显示错误(如下面的截图所示)。
如果数据通过了客户端和服务器端验证,则员工数据将保存到数据库中,并且页面将重定向到列表页面。
FuelPHP - 文件上传
文件上传是表单编程中最常用的功能之一。FuelPHP 提供了一个特殊的类Upload来处理文件上传。让我们在本节中学习如何使用 Upload 类上传文件。
配置
可以使用单独的配置文件fuel/app/config/upload.php配置 Upload 类。重要的配置项如下:
max_size − 设置要上传文件的最大大小。“0”表示无限制的上传大小
ext_whitelist − 设置允许的文件扩展名
ext_blacklist − 设置不允许的文件扩展名
type_whitelist − 设置允许的文件类型。例如,对于 mime 类型“text/plain”,使用“text”。
type_blacklist − 设置不允许的文件类型
mime_whitelist − 设置允许的 MIME 文件类型。例如,“text/plain”
mime_blacklist − 设置不允许的 MIME 文件类型
prefix − 保存上传文件到服务器时,在文件名之前添加的字符串
suffix − 保存上传文件到服务器时,在文件名之后添加的字符串
extension − 要设置的上传文件的扩展名
create_path − 是否创建文件路径(如果不存在)
overwrite − 保存上传文件时是否覆盖现有文件
auto_rename − 保存上传文件时是否通过添加序列号来重命名文件
randomize − 是否创建一个 32 个字符的随机名称来保存上传文件
上传方法
Upload 类提供处理和保存用户上传文件的选项。每个处理后的文件(保存之前)都将在结果数组中包含以下信息。
field − 表单字段的名称
name − 上传文件的名称
type − 浏览器定义的文件类型
mimetype − Upload 类定义的文件类型
file − 上传文件的临时位置的完整限定名称
filename − 上传文件的名称
extension − 上传文件的扩展名
size − 上传文件的大小(以字节为单位)
errors − 包含错误代码和消息的错误数组
error − 是否设置错误数组以及上传失败的原因(如果上传失败)
文件保存到服务器后,结果数组也将包含以下信息。
saved_to − 上传文件保存的完整限定路径
saved_as − 保存的文件名
errors − 更新后的错误数组
现在,让我们看看 Upload 类的使用方法。
is_valid
如果用户上传了任何有效文件,is_valid 将返回 true。
// do we have any uploaded files to save? if (Upload::is_valid()) { // process }
get_files
get_files 返回所有上传文件作为多维数组。如果指定了表单文件输入的索引/名称,则它只返回与指定文件输入相关的上传文件。
foreach(Upload::get_files() as $file) { // do something with the file info } if ( Upload::get_files(0)) { // do something }
get_errors
如果上传一个或多个文件失败,get_errors 将返回一个错误数组。如果指定了表单文件输入名称的索引/名称,则它只返回与指定文件输入相关的错误。
foreach(Upload::get_errors() as $file) { // do something with the file info } if (Upload::get_errors('myimage')) { // do something }
Process
process 指的是收集有关上传文件信息的实际过程。我们可以使用数组提供新的自定义配置。如果没有指定配置,则它将使用 fuel/app/config/upload.php 中定义的配置。
Upload::process (array( 'auto_rename' => false, 'overwrite' => true ));
save
save 指的是将所有已验证的文件保存到适当位置的实际过程。我们可以指定索引只保存该特定条目。
Upload::save(); Upload::save(0); Upload::save(0, 3);
工作示例
让我们在员工示例中创建一个新的控制器 Controller_Upload 来测试上传功能。
步骤 1 − 创建一个文件,fuel/app/classes/controller/upload.php。创建上传控制器。
<?php class Controller_Upload extends Controller { }
步骤 2 − 创建一个新的 action get_upload。
<?php class Controller_Upload extends Controller { public function get_index() { return \View::forge("upload/index"); } }
步骤 3 − 为创建的 action 创建一个新的视图。
<!DOCTYPE html> <html> <body> <form action = "/upload/index" method = "post" enctype = "multipart/form-data"> Select image to upload: <input type = "file" name = "fileToUpload" id = "fileToUpload"> <input type = "submit" value = "Upload Image" name = "submit"> </form> </body> </html>
步骤 4 − 创建一个新的 action post_action 来处理上传的文件。
<?php class Controller_Upload extends Controller { public function get_index() { return \View::forge("upload/index"); } public function post_index(){ $config = array( 'path' => DOCROOT.'files', 'randomize' => true, 'ext_whitelist' => array('img', 'jpg', 'jpeg', 'gif', 'png'), ); Upload::process($config); // if there are any valid files if (Upload::is_valid()) { Upload::save(); echo "success"; } else { // and process any errors foreach (Upload::get_errors() as $file) { echo var_dump($file); } } } }
最后,通过请求 url https://127.0.0.1:8080/upload/index 来运行应用程序,并尝试上传文件。
结果
FuelPHP - Ajax
AJAX 是 web 编程中的一项现代技术。它提供在网页中异步发送和接收数据的选项,无需刷新页面。本章让我们学习 FuelPHP AJAX 编程。
FuelPHP 框架提供识别请求类型是否为 AJAX 的选项。Input 类为此目的提供了一个方法 is_ajax()。如果进行了 AJAX 请求,Input::is_ajax 方法返回 true,否则返回 false。
此方法用于在服务器端正确处理 AJAX 请求。
if (Input::is_ajax()) { // Ajax request } else { // Normal request }
我们可以使用 json_encode 返回 JSON 响应。我们可以将这两种方法结合起来创建一个简单干净的基于 AJAX 的 web 应用程序。
工作示例
让我们在员工应用程序中添加一个新页面,ajax/index,并尝试异步获取员工信息。
步骤 1 − 在 fuel/app/classes/controller/ajax.php 中创建一个新的控制器 Controller_Ajax。
<?php class Controller_Ajax extends Controller { }
步骤 2 − 创建一个新的 action,action_index,如下所示。
<?php class Controller_Ajax extends Controller { public function action_index() { $emps = model_employee::find('all'); $data = array(); $i = 0; foreach($emps as $emp) { $data[$i] = array(); $data[$i]['name'] = $emp['name']; $data[$i]['age'] = $emp['age']; $i = $i + 1; } if(\Input::is_ajax()) { echo json_encode($data); } else { return \View::forge("ajax/index"); } } }
在这里,如果请求是 AJAX,我们获取学生信息,将其编码为 JSON 并返回。否则,我们只呈现相应的视图。
步骤 3 − 创建相应的视图文件,fuel/app/views/ajax/index.php,如下所示。
<html> <head> <script language = "javascript" src = "/assets/js/jquery-3.2.1.min.js"></script> <style> .table { border-collapse: collapse; } .table th, td { border-bottom: 1px solid #ddd; width: 250px; text-align: left; align: left; } </style> </head> <body> <a id = "loademployee" href = "#">Load employee information</a> </br> </br> <table class = "table"> <tbody id = "employee"> </tbody> </table> <script language = "javascript"> $(document).ready(function() { $("#loademployee").on("click", function(event) { $.ajax ({ url: '/ajax/index', type: 'POST', dataType: 'json', async: true, success: function(data, status) { var e = $('<tr><th>Name</th><th>Age</th></tr>'); $('#employee').html(''); $('#employee').append(e); for(i = 0; i < data.length; i++) { employee = data[i]; var e = $('<tr><td id = "name"></td><td id = "age"></td></tr>'); $('#name', e).html(employee['name']); $('#age', e).html(employee['age']); $('#employee').append(e); } }, error : function(xhr, textStatus, errorThrown) { alert('Ajax request failed.'); } }); }); }); </script> </body> </html>
在这里,我们创建了一个锚点标签 (id: loademployee) 用于使用 AJAX 调用加载员工信息。AJAX 调用是使用 JQuery 完成的。当用户点击时,附加到 loademployee 标签的事件被激活。然后,它将使用 AJAX 调用获取员工信息并动态生成所需的 HTML 代码。
步骤 4 − 运行应用程序。
最后,运行应用程序,https://127.0.0.1:8000/ajax/index 并点击“加载员工信息”锚点标签。
结果
FuelPHP - HMVC 请求
FuelPHP 提供了一个优秀的特性,可以使用 Request 类请求同一个应用程序中的 action。这称为 HMVC 请求。它能够重用控制器逻辑。
创建 HMVC 请求
创建 HMVC 请求就像使用所需的 URL 创建一个请求对象并调用 execute 方法一样简单,如下所示。
$list = Request::forge('employee/list/')->execute(); echo $list; $employee = Request::forge('employee/show/1')->execute(array('id' => '1')); echo $employee;
工作示例
让我们创建一个新的控制器 Controller_HMVC 来测试 HMVC 功能。创建一个文件,fuel/app/classes/controller/hmvc.php 并放置以下代码。
<?php class Controller_HMVC extends Controller { public function action_index() { echo Request::forge('employee/list')->execute(); } }
在这里,我们只是通过 HMVC 请求调用了 employee/list 页面并显示了结果。
结果
FuelPHP - 主题
主题用于为应用程序启用多种外观。它为用户/开发人员提供了更改应用程序外观的选项,而不会影响应用程序的功能。一个应用程序可以有一个或多个主题。每个主题都位于它自己的文件夹中。本章让我们学习如何创建主题。
主题配置
FuelPHP 为主题提供了一个单独的配置文件,fuel/app/config/themes.php。所有与主题相关的设置都在此文件中配置。一些主要的主题设置如下:
active − 活动主题的名称
fallback − 如果找不到活动主题,则为回退主题的名称
paths − 搜索和查找主题的路径数组
assets_folder − 通常情况下,资源需要位于 DOCPATH 中,以便可以通过 web 访问。它指的是 DOCPATH 内主题的资源文件夹。
view_ext − 主题视图文件的扩展名
info_file_name − 包含有关主题的扩展信息的的文件
require_info_file − 是否需要主题信息文件,info_file_name
use_modules − 是否使用当前模块
主题文件的简单配置如下。
<?php return array ( 'active' => 'tpthemes', 'fallback' => 'tpthemes', 'paths' => array ( APPPATH.'themes', ), 'assets_folder' => 'assets', 'view_ext' => '.html', 'require_info_file' => false, 'info_file_name' => 'themeinfo.php', 'use_modules' => false, );
在这里我们设置了:
- 活动和回退主题的名称为 tpthemes
- 主题文件夹的路径为 fuel/app/themes/
- 资源文件夹的路径为 /public/assets/tpthemes/
主题类
完成配置后,我们可以使用 FuelPHP 提供的 Theme 类来执行主题的功能。让我们了解本章中 Theme 类中可用的方法。
instance
instance 方法能够创建一个新的主题。它有两个参数:
$name − 主题的名称(可选)
$config − 主题配置数组(与配置部分中看到的一样)
这两个参数都是可选的。如果没有指定参数,它将尝试从配置文件中获取默认主题。如果指定了主题名称,它将尝试从配置文件中获取其他设置。如果也指定了配置,则它将使用用户指定的设置而不是配置文件中的设置。
$theme = \Theme::instance(); $theme = \Theme::instance('tpthemes'); $theme = \Theme::instance ('mytheme', array ( 'active' => 'mytheme', 'view_ext' => '.php'));
forge
forge 与 instance 类似,只是它只有配置数组。
$theme = \Theme::forge (array( 'active' => 'tpthemes', 'fallback' => 'tpthemes', 'view_ext' => '.php', ));
view
view 方法在后台使用 View::forge()。这两个 API 类似,除了 view 方法在 themes 文件夹 fuel/app/themes/tpthemes/ 中搜索视图文件,而不是 fuel/app/views/ 文件夹。
$theme = \Theme::instance(); $view = $theme->view('template/index'); // *fuel/app/themes/tpthemes/template/index.php
presenter
presenter 方法在后台使用 Presenter::forge()。这两个 API 类似,除了 presenter 方法在 themes 文件夹 fuel/app/themes/tpthemes/ 中搜索视图文件,而不是 fuel/app/views/ 文件夹。
$theme = \Theme::instance(); $presenter = $theme->presenter('template/index');
asset_path
asset_path 方法返回相对于当前选择的主题请求的资源的路径。
$theme = \Theme::instance(); // public/assets/tpthemes/css/style.css $style = \Html::css($theme->asset_path('css/style.css'));
add_path
add_path 方法允许在运行时添加主题路径。
$theme = \Theme::instance(); $theme->add_path(DOCROOT.'newthemes');
add_paths
add_paths 方法允许在运行时添加多个主题路径。
$theme = \Theme::instance(); $theme->add_path(DOCROOT.'newthemes');
active
active 方法允许设置活动主题。
$theme = \Theme::instance(); $active = $theme->active('newtheme');
fallback
fallback 方法允许设置回退主题。
$theme = \Theme::instance(); $fallback = $theme->fallback('custom');
get_template
get_template 方法将返回当前加载的主题模板的 View 实例。
$theme = \Theme::instance(); $theme->get_template()->set('body', 'Theme can change the look and feel of your app');
set_template
set_template 方法允许设置页面的主题模板。
$theme = \Theme::instance(); $theme->set_template('layouts/index')->set('body', 'set theme template');
find
如果找到主题的路径,find 返回 true,否则返回 false。
$theme = \Theme::instance(); $path = $theme->find('newtheme')
all
all 方法返回所有主题路径中所有主题的数组。
$theme = \Theme::instance(); $themes = $theme->all();
get_info
get_info 方法返回主题信息数组中的特定变量。如果没有指定主题,则使用活动主题的信息数组。
$theme = \Theme::instance(); $var = $theme->get_info('color', 'green', 'newtheme');
在这里,该方法获取在“newtheme”中定义的颜色。如果未定义,则将使用“green”作为默认颜色。
set_info
set_info 方法在活动或回退主题中设置变量。
$theme->set_info('color', 'green', 'fallback');
set_partial
set_partial 方法允许为页面模板的命名部分设置视图部分。通常,这是通过 HMVC 调用完成的。
$theme = \Theme::instance(); $theme->set_template('layouts/homepage'); $theme->set_partial('navbar', 'homepage/navbar');
get_partial
get_partial 方法允许获取页面模板命名部分中先前设置的部分的视图实例。
$theme = \Theme::instance(); $theme->set_partial('sidebar', 'partials/menu'); $theme->get_partial('sidebar', 'partials/menu')->set('class', 'menu green');
工作示例
让我们在员工应用程序中添加主题支持。
步骤 1 − 使用以下内容添加新的主题配置文件 fuel/app/config/theme.php。
<?php return array ( 'active' => 'tpthemes', 'fallback' => 'tpthemes', 'paths' => array (APPPATH.'themes', ), 'assets_folder' => 'assets', 'view_ext' => '.html', 'require_info_file' => false, 'info_file_name' => 'themeinfo.php', 'use_modules' => false, );
步骤 2 − 为主题 tpthemes 添加新的资源文件夹 public/assets/tpthemes/css。
cd /go/to/app/root/path mkdir -p public/assets/tpthemes/css
步骤 3 − 下载最新的 bootstrap 并将 bootstrap.min.css 放置在 public/assets/tpthemes/css 下
步骤 4 − 在 fuel/app/themes 文件夹下添加新的文件夹 tpthemes。
cd /go/to/app/root/path mkdir -p fuel/app/themes/tpthemes
步骤 5 − 在 fuel/app/themes/tpthemes/layout/ 下添加新的布局模板 bootstrap.html 并添加以下代码。
<!DOCTYPE html> <html lang = "en"> <head> <title>Theme example</title> <meta charset = "utf-8"> <meta name = "viewport" content = "width = device-width, initial-scale = 1"> <!-- Bootstrap core CSS --> <?php echo \Theme::instance()->asset->css('bootstrap.min.css'); ?> </head> <body> <?php echo $header; ?> <div class = "container"> <div class = "row"> <div class = "col-sm-12"> <?php echo $content; ?> </div> </div> </div> </body> </html>
在这里,我们使用了主题实例和 asset 方法来获取 bootstrap 文件的路径。我们定义了两个变量 header 和 content。header 用于动态设置标题详细信息。content 用于动态设置页面的实际内容。
步骤 6 − 在 fuel/app/themes/tpthemes/partials 下添加新的标题模板 header.php,如下所示。
<div class = "jumbotron text-center"> <h1>Theme support in fuelphp</h1> <p>bootstrap based template</p> </div>
步骤 7 − 在 fuel/app/classes/controller/themesample.php 中创建一个新的控制器 ThemeSample 以及 action action_index,如下所示。
<?php class Controller_ThemeSample extends \Controller { public function before() { $this->theme = \Theme::instance(); $this->theme->set_template('layouts/bootstrap'); $header = $this->theme->view('partials/header'); $this->theme->get_template()->set('header', $header); } public function action_index() { $content = $this->theme ->view('themesample/index') ->set('message', 'This data comes from action page'); $this->theme ->get_template() ->set('content', $content); } public function after($response) { if (empty($response) or ! $response instanceof Response) { $response = \Response::forge(\Theme::instance()->render()); } return parent::after($response); } }
在这里,我们使用了 before 和 after 方法来使用 Theme 类的使用方法初始化主题。使用的一些方法是 instance、get_template、set_template 和 view。
步骤 8 − 最后,为 index action 添加视图 index.php 在 fuel/app/themes/tpthemes/themesample 中,如下所示。
<p>The data comes from *fuel/app/themes/tpthemes/themesample/index.html* file.</p> <p> <?php echo $message; ?> </p>
在这里,我们定义了一个变量 message,需要在控制器中动态设置。
我们创建了一个新的主题 tpthemes 并将其用于 ThemeSample 控制器。现在让我们通过请求 URL https://127.0.0.1:8080/themesample/index 来检查结果。结果如下。
FuelPHP - 模块
模块是编写可复用 web 功能(例如博客、相册、聊天等)的绝佳方式。模块不会干扰 web 应用中的其他代码。它位于自己的文件夹中,并默默地提供其功能。模块只是将控制器、模型和视图分组、配置并放置在特殊文件夹中。通常,模块通常位于应用程序的子目录中,该子目录名为 modules,位于 fuel/app/modules。
模块配置
我们可以在主应用程序配置文件 fuel/app/config/config.php 中定义模块路径,如下所示。
'module_paths' => array ( path/to.’modules'.DS, // path to application modules path/to.’..’.DS.'globalmods'.DS // path to our global modules ),
模块命名空间
在 FuelPHP 中,每个模块都有其自己的 PHP 命名空间。设置单独的命名空间可以解决命名冲突。例如,员工模块可以设置在命名空间 EmployeeModule 下,如下所示。
<?php namespace Employeemodule; class Controller_Employee { //code here }
模块名称必须与其文件夹名称相同。
模块结构
我们可以通过创建在配置中定义的文件夹名称来创建模块。文件夹名称决定模块的名称以及模块中类的命名空间名称。
模块的结构如下:
- classes
- controller
- model
- view
- config
- lang
- tasks
- views
模块可以拥有自己的配置文件。这在路由设置中非常有用,并且不会干扰应用程序的原始配置。另一个重要的概念是,可以通过在 always_load 配置部分加载模块来重用模块类,如下所示。
'always_load => array ( 'modules' => array('employeemodule'), ),
此外,可以立即加载和使用模块,无需进行配置,如下所示。
Module::load('employeemodule'); \Employeemodule\Myclass::mymethod('params');
FuelPHP - 包
包在代码重用方面与模块类似,但在以下方面有所不同:
- 它不会映射到 web URL。
- 无法通过 HMVC 请求访问。
简而言之,包不是直接的 web 功能,例如博客、相册等。相反,它是一个函数库的集合,例如电子邮件处理、文档创建、图表创建、身份验证等,有助于更快地开发 web 应用程序。
创建包
要创建包,首先我们需要按照如下所示的方式安排源代码。
/fuel /packages /package (root directory of package) /bootstrap.php /classes /our.php /classes.php /here.php /config /config.php /and_so_on
包的结构包含两个特定于包的文件:config.php 和 bootstrap.php 文件。配置文件的目的是将包的配置分组到包文件夹本身,而不会干扰主应用程序。bootstrap 文件的目的是设置命名空间,以便自动加载程序正确加载它。
设置命名空间的一些方法如下:
Autoloader::add_namespace('Mypackage', __DIR__.'/classes/'); Autoloader::add_core_namespace('Mypackage'); Autoloader::add_core_namespace('Mypackage', true); Autoloader::add_classes (array( 'Mypackage\\Classname' => __DIR__.'/classes/classname.php', 'Mypackage\\Anotherclass' => __DIR__.'/classes/anotherclass.php', ));
一旦 bootstrap 文件配置正确并将包加载到应用程序中,我们就可以按如下方式使用它:
$instance = new Myclass; $instance = new Mynamespace\Myclass;
安装包
包通常放置在 fuel/packages 目录下。默认情况下,安装了以下包:
auth − 身份验证包
email − 电子邮件包
oil − Fuel 的命令,oil 包
orm − ORM 包
parser − Markdown 解析器包
要安装新包,有以下两种选择:
选项 1 − 手动安装 - 下载并安装
要手动安装包,首先从作者的网站下载包。解压它并将其放在 fuel/packages/ 文件夹下。
选项 2 − 使用 oil 命令的自动方法
FuelPHP 提供了一种自动安装托管在 github 上的包的方法。使用以下命令安装包 mytestpackage。
php oil package install mytestpackage
它使用 git 客户端克隆包源代码并将其移动到 fuel/packages 文件夹。如果 git 客户端不可用,则可以使用 –direct 命令参数直接命令下载并安装包,如下所示。
php oil package install mytestpackage --direct
使用包
一旦将包加载到应用程序中,就可以在应用程序中使用它。将包加载到应用程序中有两种方法。
选项 1 − 通过 Package 类
FuelPHP 提供了一个类 Package 来加载、卸载和检查包的可用性,分别通过 load、unload 和 loaded 方法。load 方法有两个参数。第一个参数 $package 是包的名称,第二个参数 path 是包的路径。如果包安装在 fuel/packages 文件夹中,则第二个参数是可选的。
// load the orm package Package::load('orm'); // load the parser package from a specific directory Package::load('parser', '/path/to/packages/dir/'); // load the non-existent package Package::load('awesome'); // Throws a PackageNotFoundException
选项 2 − 通过配置文件
要永久加载包,只需在主配置文件 fuel/app/config/config.php 中的 always_load 配置项下添加包即可。要加载 email 包,请使用以下语法。
'always_load' => array ( 'packages' => array ( 'email', ), ),
一旦将包加载到应用程序中,我们就可以按如下方式使用它:
$instance = new Myclass; $instance = new Mynamespace\Myclass;
FuelPHP - Cookie 和会话管理
Cookie 提供客户端数据存储,并且仅支持少量数据。通常,每个域为 2KB,这取决于浏览器。Session 提供服务器端数据存储,并且支持大量数据。让我们了解如何在 FuelPHP web 应用程序中创建 Cookie 和会话。
Cookie
FuelPHP 提供了一个 Cookie 类来创建 Cookie 项目。Cookie 类用于创建、分配和删除 Cookie。
配置 Cookie
可以通过位于 fuel/app/config/config.php 的主应用程序配置文件全局配置 Cookie 类。定义如下。
'cookie' => array ( //Number of seconds before the cookie expires 'expiration' => 0, //Restrict the path that the cookie is available to 'path' => '/', //Restrict the domain that the cookie is available to 'domain' => null, // Only transmit cookies over secure connections 'secure' => false, // Only transmit cookies over HTTP, disabling Javascript access 'http_only' => false, ),
方法
Cookie 类提供创建、访问和删除 Cookie 项目的方法。它们如下:
set()
set 方法用于创建 Cookie 变量。它包含以下参数:
$name − $_COOKIE 数组中的键。
$value − Cookie 的值。
$expiration − Cookie 应持续存在的秒数。
$path − 服务器上 Cookie 可用的路径。
$domain − Cookie 可用的域。
$secure − 如果只想通过安全连接传输 Cookie,则设置为 true。
$httponly − 仅允许通过 HTTP 传输 Cookie,禁用 JavaScript 访问。
Cookie::set('theme', 'green');
get()
get 方法用于读取 Cookie 变量。它包含以下参数:
$name − $_COOKIE 数组中的键。
$value − 如果键在 $_COOKIE 数组中不可用,则返回的值。
Cookie::get('theme');
delete()
delete 方法用于删除 Cookie 变量。它包含以下参数:
$name − $_COOKIE 数组中的键。
$value − Cookie 的值。
$domain − Cookie 可用的域。
$secure − 如果只想通过安全连接传输 Cookie,则设置为 true。
$httponly − 仅允许通过 HTTP 传输 Cookie,禁用 JavaScript 访问。
Cookie::delete('theme');
会话
FuelPHP 提供类 Session 来维护应用程序的状态。
配置会话
可以通过特殊的配置文件 fuel/core/config/session.php 配置 Session 类。一些重要的配置项如下:
auto_initialize − 自动初始化会话。
driver − 会话驱动程序的名称。会话是使用驱动程序实现的,可能的选项包括 cookie、db、memcached、redis 和 file。默认驱动程序是 cookie。
match_ip − 检查客户端 IP。
match_ua − 检查客户端用户代理。
expiration_time − 会话超时值(以秒为单位)。
rotation_time − 续期会话的时间。
会话方法
Session 类提供操纵会话数据的方法。它们如下:
instance()
instance 方法返回默认实例或特定实例(由名称标识)。
$session = Session::instance(); // default instance $session = Session::instance('myseesion'); // specific instance
set()
set 方法用于分配会话变量。
Session::set('userid', $userid);
get()
get 方法允许您从会话中检索存储的变量。
$userid = Session::get('userid');
delete()
delete 方法允许您删除存储的会话变量。
Session::delete('userid');
create()
create 方法允许您创建新的会话。如果已经存在会话,则将其销毁并创建一个新的会话。
Session::create();
destroy()
destroy 方法用于销毁现有会话。
Session::destroy();
read()
read 方法允许您读取会话。
Session::read();
write()
write 方法允许您写入会话。
Session::write();
key()
key 方法允许您检索会话键的元素。键的值是唯一的。
$session_id = Session::key('session_id');
FuelPHP - 事件
**事件**是程序识别的动作或事件,程序本身可以处理这些动作或事件。例如,我们可以定义一个名为 my_fuel_event 的动作或事件,然后在调用事件 my_fuel_event 时执行一些工作。FuelPHP 提供类 Event 来处理应用程序中的事件。
系统事件
FuelPHP 定义了一些事件,通过这些事件,我们可以随时执行一些工作,只要应用程序调用或触发定义的事件即可。这有助于更改 FuelPHP 的行为,而无需更改 FuelPHP 的核心代码文件。预定义的事件如下:
app_created − 在 FuelPHP 框架初始化后将触发此事件。
request_created − 创建新的 Request 对象后将触发此事件。
request_started − 请求执行时将触发此事件。
controller_started − 在调用控制器的 before() 方法之前将触发此事件。
controller_finished − 在调用控制器的 after() 方法并收到响应后将触发此事件。
response_created − 创建新的 Response 对象后将触发此事件。
request_finished − 请求执行完成并收到响应时将触发此事件。
shutdown − 处理主要请求并发送输出后将触发此事件。
我们可以在特殊的配置文件 fuel/app/config/events.php 中处理事件,如下所示:
<?php return array ( 'fuelphp' => array ( 'app_created' => function() { // After FuelPHP initialised }, 'request_created' => function() { // After Request forged }, 'request_started' => function() { // Request is requested }, 'controller_started' => function() { // Before controllers before() method called }, 'controller_finished' => function() { // After controllers after() method called }, 'response_created' => function() { // After Response forged }, 'request_finished' => function() { // Request is complete and Response received }, 'shutdown' => function() { // Output has been send out }, ), );
事件方法
Event 类提供注册、注销和触发事件的方法。它们如下:
register()
register 方法允许文件注册一个对象,该对象将在调用 trigger 方法时运行。
$my_event_code = function() { echo 'my event'; } Event::register('my_event', $my_event_code);
unregister()
unregister 方法允许文件注销在调用 trigger 方法时运行的对象。
Event::unregister('my_event', $my_event_code);
trigger()
trigger 方法用于触发或激活通过 register 方法关联的回调函数。
Event::trigger('my_event');
has_events()
has_events 方法允许您检查特定注册事件是否有触发器。
Event::has_events('my_event');
forge()
forge 方法返回一个新的事件对象。
$event = Event::forge();
instance()
instance 方法返回一个新的事件对象单例。
$event = Event::instance('event_instance');
FuelPHP - 邮件管理
电子邮件功能是 Web 框架中最受需求的功能。FuelPHP 提供了一个优雅的电子邮件类,作为软件包捆绑在一起。它用于发送简单的纯文本电子邮件以及带有多个附件的高级富文本电子邮件。它支持以下功能 - 纯文本邮件、HTML 邮件、附件和内联附件。
配置
要在应用程序中启用电子邮件功能,我们只需要按照如下所示在主配置文件 fuel/app/config/config.php 中加载电子邮件软件包。
'always_load' => array ( 'packages' => array ( 'email', ), ),
另一种方法是在控制器本身中加载电子邮件软件包,如下所示。
\Package::load('email');
电子邮件设置可以在主配置文件中完成,一些重要的选项如下:
driver − 电子邮件驱动程序,例如 smtp
is_html − 是否以 HTML 内容发送邮件
priority − 电子邮件的优先级
smtp.host − SMTP 服务器主机
smtp.port − SMTP 服务器端口
smtp.username − SMTP 服务器用户名
smtp.password − SMTP 服务器密码
smtp.timeout − SMTP 超时时间
smtp.starttls − SMTP 服务器是否需要 STARTTLS 命令
电子邮件 API
以下是电子邮件和电子邮件驱动程序类提供的 API。
forge
目的:创建电子邮件驱动程序的实例。它根据收到的配置或输入创建驱动程序。电子邮件驱动程序提供创建和发送邮件的功能。一些可能的电子邮件驱动程序是 smtp、sendmail、mailgun 和 mandrill。
参数 − 无或配置详细信息数组
返回值 − 返回 Email_Driver 对象
例如:
$email = \Email::forge(); $email = \Email::forge (array( 'driver' => 'smtp', ));
body
目的 − 设置消息正文
参数 − $body - 消息正文
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->body('Body message'); //or pass it a View $email->body(\View::forge('my/view', $data);
alt_body
目的 − 设置备用消息正文
参数 − $alt_body - 备用消息正文
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->alt_body('Body message'); //or pass it a View $email->alt_body(\View::forge('my/view', $data);
priority
目的 − 设置邮件的优先级
参数 −
$priority − 优先级的数值。选项为:
a. \Email::P_LOWEST * \Email::P_LOW * \Email::P_NORMAL * \Email::P_HIGH * \Email::P_HIGHEST
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->priority(\Email::P_HIGHEST);
html_body
目的 − 以 HTML 格式设置消息正文
参数 −
$html − HTML 格式的消息正文;
generate_alt − 是否生成替代消息;
auto_attach − 是否嵌入图像
返回 − 返回当前实例
例如:
$email = \Email::forge(); // Do generate the alt body, but don't auto attach images. $email->html_body(\View::forge('welcome/email', $data), true, false);
from
目的 − 设置发件人地址
参数 −
$from − 发件人电子邮件地址;
$name − 发件人姓名
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->from('[email protected]', 'My Name');
subject
目的 − 设置消息的主题
参数 − $subject - 电子邮件主题
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->subject('Suject of the mail message');
to
目的 − 设置收件人电子邮件地址
参数 −
$email − 电子邮件地址或电子邮件地址数组;
$name − 收件人姓名
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->to('[email protected]', 'My Dear Name'); $email->to (array( '[email protected]', '[email protected]' => 'My Dear friend', ));
header
目的 − 为电子邮件消息设置自定义标头
参数 −
$header − 标头类型或标头数组;
$value − 标头的值
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email->header('X-SMTPAP', 'XXXXXXXX'); $email>reply_to (array( 'X-SMTPAP' => 'XXXXXX', 'X-SMTPAP2' > 'XXXXXA', ));
attach
目的 − 将文件附加到电子邮件消息
参数−
$file − 文件路径;
$inline − 是否内联附加文件;
$cid − 内容标识符;
$mime − 附件文件的 MIME 类型;
$name − 附件文件名覆盖
返回 − 返回当前实例
例如:
$email = \Email::forge(); $email>attach(DOCROOT.'attachments/sample_attachment.pdf');
send
目的 − 发送邮件。
参数 −
$validate − 是否验证电子邮件地址
返回值 − true 或 false
例如:
$email = \Email::forge(); try{ $email->send(); } catch(\EmailSendingFailedException $e) { // The driver could not send the mail. } catch(\EmailValidationFailedException $e) { // One or more email addresses failed validation. }
工作电子邮件示例
让我们使用上一章中学习的 API,创建一个简单的代码来发送消息。以下是发送消息的最简单代码。
$email = Email::forge(); $email->from('[email protected]', 'person1'); $email->to('[email protected]', 'person2'); $email->subject('Add something'); $email->body('contents of mail'); $email->send();
FuelPHP - 性能分析器
性能分析器是分析和改进应用程序性能的重要工具之一。FuelPHP 提供了一个优秀的性能分析器来分析应用程序。让我们在本节中了解 FuelPHP 中的性能分析器。
启用性能分析
默认情况下性能分析是禁用的。要启用性能分析,请在主配置文件 fuel/app/config/config.php 中将属性 profiling 设置为 true,如下所示。
'profiling' => true,
现在,应用程序中启用了性能分析。启用性能分析后,所有请求的页面都将在页面的底部显示一个额外的选项卡,其中包含性能分析信息,如下面的屏幕截图所示。
性能分析器信息
性能分析器具有选项卡式界面,它包含以下数据:
控制台 − 提供有关错误、日志条目、内存使用情况或执行时间的详细信息。
加载时间 − 显示请求加载时间。
数据库 − 执行的查询数量和执行时间。
内存 − 请求使用的总内存。
文件 − 显示所有 PHP 文件。
配置 − 请求结束时的配置内容。
会话 − 请求结束时的会话内容。
GET − $_GET 数组的内容。
POST − $_POST 数组的内容。
性能分析器类
性能分析器类用于添加性能分析信息。它实现了一个 PHPQuickProfiler (PQP) 的自定义版本。性能分析器包含一系列 JavaScript 变量,用于控制性能分析器的初始状态。
性能分析器类支持以下方法:
mark()
mark 方法将向性能分析器添加一个速度标记。它显示加载时间。
Profiler::mark('my custom code');
mark_memory()
mark_memory 方法向性能分析器添加内存标记。如果没有指定输入,则记录该时刻的内存使用情况。如果我们指定变量和变量的标签,如下所示,那么它将显示变量的内存使用情况并使用指定的标签进行标记。
mark_memory($this, 'My Employee Controller memory usage');
console()
console 方法只会向性能分析器添加日志条目。
Profiler::console('log entry');
FuelPHP - 错误处理和调试
FuelPHP 为处理错误和调试应用程序提供了出色的支持。让我们在本节中了解错误处理和调试。
错误处理
FuelPHP 错误处理基于异常。FuelPHP 为所有旧的 php 错误提供 PhpErrorException 异常。每当遇到 PHP 代码中的错误时,FuelPHP 都会引发 PhpErrorException。FuelPHP 还简化了为各种 HTTP 状态代码显示自定义错误页面的过程。
文件未找到错误
FuelPHP 提供了一个新的异常类 HttpNotFoundException 来处理未知请求。有时,我们可能会遇到未处理的请求。这时,我们可以直接抛出 HttpNotFoundException。
默认情况下,在路由配置文件 fuel/app/config/routes.php 中使用 400 条目为 HttpNotFoundException 配置了默认页面。每当引发 HttpNotFoundException 时,请求将被重定向到 400 页面。
'_404_' => 'welcome/404', // The main 404 route
内部错误
FuelPHP 提供了一个新的异常类 HttpServerErrorException 来处理所有服务器错误。有时,由于内部错误,我们可能无法处理给定的请求。这时,我们可以直接抛出 HttpServerErrorException。
默认情况下,在路由配置文件 fuel/app/config/routes.php 中使用 500 条目为 HttpServerErrorException 配置了默认页面。每当引发 HttpServerErrorException 时,请求将被重定向到 500 页面。
'_500_' => 'welcome/500', // The main 500 route
此页面将记录错误,在页面上显示格式化的错误,并偶尔向系统管理员发送通知。
访问冲突错误
FuelPHP 提供了一个新的异常类 HttpNoAccessException 来处理访问冲突。有时,由于访问限制,我们可能无法处理请求。这时,我们可以直接抛出 HttpNoAccessException。
默认情况下,在路由配置文件 fuel/app/config/routes.php 中使用 403 条目为 HttpNoAccessException 配置了默认页面。每当引发 HttpNoAccessException 时,请求将被重定向到 403 页面。
'_403_' => 'welcome/403', // The main 403 route
此页面将显示访问冲突信息。
调试
调试是开发应用程序中最常见的活动之一。FuelPHP 提供了一个简单的类 Debug 来处理应用程序的调试活动。让我们在本节中学习 Debug 类及其方法。
Debug 类
Debug 类提供实用程序方法来显示变量、对象、数组等的详细信息。Debug 类提供以下方法:
dump
dump 方法以格式化的结构化方式将多个混合值返回到浏览器。
Debug::dump($var1, $var2);
backtrace()
backtrace 显示有关代码当前执行的详细信息。它显示 PHP 文件信息、当前行及其所有之前的操作。
Debug::backtrace();
classes()
返回所有类的列表。
Debug::classes();
interfaces()
返回所有接口类的列表。
Debug::interfaces();
includes()
返回当前在运行时加载的所有包含文件的列表。
Debug::includes();
functions()
返回所有函数的列表。
Debug::functions();
constants()
返回所有常量的列表。
Debug::constants();
extensions()
返回所有扩展的列表。
Debug::extensions();
headers()
返回所有 HTTP 标头的列表。
Debug::headers();
phpini()
打印从 php.ini 文件读取的配置设置列表。
Debug::phpini();
FuelPHP - 单元测试
单元测试是在开发大型项目中必不可少的流程。单元测试有助于在开发的每个阶段自动测试应用程序的组件。当应用程序的组件不符合项目的业务规范时,它会发出警报。单元测试可以手动完成,但通常是自动化的。
PHPUnit
FuelPHP 框架与 PHPUnit 测试框架集成。要为 FuelPHP 框架编写单元测试,我们需要设置 PHPUnit。如果未安装 PHPUnit,则下载并安装它。我们可以使用以下命令确认 PHPUnit 在我们的系统中是否可用。
phpunit --version
如果 PHPUnit 可用,您将看到类似于以下的结果。
PHPUnit 5.1.3 by Sebastian Bergmann and contributors.
创建单元测试
FuelPHP 提供的编写单元测试的标准位置是 fuel/app/tests。我们可以在单独的文件夹中为控制器、模型、视图和演示者编写单元测试。让我们编写一个单元测试来验证 Model_Employee 对象。
步骤 1 − 在 fuel/app/tests 文件夹下创建一个文件夹 model。
步骤 2 − 在 fuel/app/tests/model/ 文件夹下创建一个文件 employee.php。
步骤 3 − 通过扩展 PHPUnit 提供的 TestCase 类,创建一个新的测试类 Test_Model_Employee。
步骤 4 − 编写一个方法 testInstanceOfEmployee(),使用 PHPUnit 的 TestCase 类提供的 assertInstanceOf() 方法来断言员工对象的创建。
以下是完整的代码:
<?php class Test_Model_Employee extends TestCase { public function testInstanceOfEmployee() { $this->assertInstanceOf(Model_Employee::class, new Model_Employee()); } }
创建测试组
FuelPHP 提供了创建测试用例组的选项。创建组就像添加文档块属性 `@group` 一样简单。让我们将我们的测试用例包含在 MyTest 组中。
<?php /** * @group MyTest */ class Test_Model_Employee extends TestCase { public function testInstanceOfEmployee() { $this->assertInstanceOf(Model_Employee::class, new Model_Employee()); } }
运行测试
要运行目录中的所有测试,请使用以下命令。
$ php oil test
要运行特定组的测试,请使用以下命令。
$ php oil test --group = MyTest
执行命令后,您将收到以下响应。
Tests Running...This may take a few moments. PHPUnit 5.1.3 by Sebastian Bergmann and contributors. 1 / 1 (100%). Time: 123 ms, Memory: 8.00Mb OK (1 test, 1 assertion)
FuelPHP - 完整的运行示例
在本节中,我们将学习如何在 FuelPHP 中创建一个完整的基于 MVC 的 BookStore 应用程序。
步骤 1:创建项目
使用以下命令在 FuelPHP 中创建一个名为“BookStore”的新项目。
oil create bookstore
步骤 2:创建布局
为我们的应用程序创建一个新的布局。在 fuel/app/views/ 目录下创建一个文件 layout.php。代码如下:
fuel/app/views/layout.php
<!DOCTYPE html> <html lang = "en"> <head> <meta charset = "utf-8"> <meta http-equiv = "X-UA-Compatible" content = "IE = edge"> <meta name = "viewport" content = "width = device-width, initial-scale = 1"> <title><?php echo $title; ?></title> <!-- Bootstrap core CSS --> <link href = "/assets/css/bootstrap.min.css" rel = "stylesheet"> <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"> </script> <script src = "/assets/js/bootstrap.min.js"></script> </head> <body> <nav class = "navbar navbar-inverse navbar-fixed-top"> <div class = "container"> <div class = "navbar-header"> <button type = "button" class = "navbar-toggle collapsed" datatoggle = "collapse" data-target = "#navbar" aria-expanded = "false" ariacontrols = "navbar"> <span class= "sr-only">Toggle navigation</span> <span class = "icon-bar"></span> <span class = "icon-bar"></span> <span class = "icon-bar"></span> </button> <a class = "navbar-brand" href = "#">FuelPHP Sample</a> </div> <div id = "navbar" class = "collapse navbar-collapse"> <ul class = "nav navbar-nav"> <li class = "active"><a href = "/book/index">Home</a></li> <li><a href = "/book/add">Add book</a></li> </ul> </div><!--/.nav-collapse --> </div> </nav> <div class = "container"> <div class = "starter-template" style = "padding: 50px 0 0 0;"> <?php echo $content; ?> </div> </div><!-- /.container --> </body> </html>
这里,我们使用 Bootstrap 模板。FuelPHP 对 Bootstrap 模板具有良好的支持。我们创建了两个变量,title 和 content。title 用于指定当前页面的标题,content 用于指定当前页面的详细信息。
步骤 3:创建控制器
创建一个新的控制器 Controller_Book 来显示、添加、编辑和删除书籍。创建一个新文件 fuel/app/classes/controller/book.php 并放置以下代码。
fuel/app/classes/controller/book.php
<?php class Controller_Book extends Controller_Template { public $template = 'layout'; public function action_index() { // Create the view object $view = View::forge('book/index'); // set the template variables $this->template->title = "Book index page"; $this->template->content = $view; } }
这里,我们通过继承模板控制器创建了 book 控制器,并将默认模板设置为 fuel/app/views/layout.php。
步骤 4:创建索引视图
在 fuel/app/views 文件夹下的 views 目录中创建一个文件夹 book。然后,在 book 文件夹内创建一个文件 index.php 并添加以下代码:
fuel/app/views/index.php
<h3>index page</h3>
目前,我们已经创建了一个基本的 book 控制器。
步骤 5:修改默认路由
更新默认路由,将应用程序的主页设置为 book 控制器。打开默认路由配置文件 fuel/app/config/routes.php 并将其更改如下。
fuel/app/config/routes.php
<?php return array ( '_root_' => 'book/index', // The default route '_404_' => 'welcome/404', // The main 404 route 'hello(/:name)?' => array('welcome/hello', 'name' => 'hello'), );
现在,请求 URL https://127.0.0.1:8080/ 将返回 book 控制器的 index 页面,如下所示:
步骤 6:创建数据库
使用以下命令在 MySQL 服务器中创建一个新数据库:
create database tutorialspoint_bookdb
然后,使用以下命令在数据库中创建一个表:
CREATE TABLE book ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(80) NOT NULL, author VARCHAR(80) NOT NULL, price DECIMAL(10, 2) NOT NULL );
使用以下 SQL 语句将一些示例记录插入表中。
INSERT INTO book(title, author, price) VALUES( 'The C Programming Language', 'Dennie Ritchie', 25.00 ),( 'The C++ Programming Language', 'Bjarne Stroustrup', 80.00 ),( 'C Primer Plus (5th Edition)', 'Stephen Prata', 45.00 ),('Modern PHP', 'Josh Lockhart', 10.00),( 'Learning PHP, MySQL & JavaScript, 4th Edition', 'Robin Nixon', 30.00 )
步骤 7:配置数据库
使用位于 fuel/app/config/ 的数据库配置文件 db.php 配置数据库。
fuel/app/config/db.php
<?php return array ( 'development' => array ( 'type' => 'mysqli', 'connection' => array ( 'hostname' => 'localhost', 'port' => '3306', 'database' => 'tutorialspoint_bookdb', 'username' => 'root', 'password' => 'password', 'persistent' => false, 'compress' => false, ), 'identifier' => '`', 'table_prefix' => '', 'charset' => 'utf8', 'enable_cache' => true, 'profiling' => false, 'readonly' => false, ), 'production' => array ( 'type' => 'mysqli', 'connection' => array ( 'hostname' => 'localhost', 'port' => '3306', 'database' => 'tutorialspoint_bookdb', 'username' => 'root', 'password' => 'password', 'persistent' => false, 'compress' => false, ), 'identifier' => '`', 'table_prefix' => '', 'charset' => 'utf8', 'enable_cache' => true, 'profiling' => false, 'readonly' => false, ), );
步骤 8:包含 ORM 包
更新主配置文件以包含 ORM 包。它位于“fuel/app/config/”。
fuel/app/config/config.php
'always_load' => array ( 'packages' => array ( 'orm' ), ),
步骤 9:创建模型
在位于“fuel/app/classes/model”的 book.php 中创建一个 book 模型。其定义如下:
fuel/app/classes/model/book.php
<?php class Model_Book extends Orm\Model { protected static $_connection = 'production'; protected static $_table_name = 'book'; protected static $_primary_key = array('id'); protected static $_properties = array ( 'id', 'title' => array ( 'data_type' => 'varchar', 'label' => 'Book title', 'validation' => array ( 'required', 'min_length' => array(3), 'max_length' => array(80) ), 'form' => array ( 'type' => 'text' ), ), 'author' => array ( 'data_type' => 'varchar', 'label' => 'Book author', 'validation' => array ( 'required', ), 'form' => array ( 'type' => 'text' ), ), 'price' => array ( 'data_type' => 'decimal', 'label' => 'Book price', 'validation' => array ( 'required', ), 'form' => array ( 'type' => 'text' ), ), ); protected static $_observers = array('Orm\\Observer_Validation' => array ( 'events' => array('before_save') )); }
这里,我们将数据库详细信息指定为模型的属性。它也包含验证细节。
步骤 10:显示书籍
更新 book 控制器中的 index 动作以列出数据库中可用的书籍。
fuel/app/classes/controller/book.php
<?php class Controller_Book extends Controller_Template { public $template = 'layout'; public function action_index() { // Create the view object $view = View::forge('book/index'); // fetch the book from database and set it to the view $books = Model_Book::find('all'); $view->set('books', $books); // set the template variables $this->template->title = "Book index page"; $this->template->content = $view; } }
这里,我们使用 **ORM** 从数据库中获取书籍详细信息,然后将书籍详细信息传递给视图。
步骤 11:更新索引视图
更新位于“fuel/app/views/book”的视图文件 index.php。完整的更新代码如下:
fuel/app/views/book/index.php
<table class = "table"> <thead> <tr> <th>#</th> <th>Title</th> <th>Author</th> <th>Price</th> <th></th> </tr> </thead> <tbody> <?php foreach($books as $book) { ?> <tr> <td><?php echo $book['id']; ?></td> <td><?php echo $book['title']; ?></td> <td><?php echo $book['author']; ?></td> <td><?php echo $book['price']; ?></td> <td> <a href = "/book/edit/<?php echo $book['id']; ?>">Edit</a> <a href = "/book/delete/<?php echo $book['id']; ?>">Delete</a> </td> </tr> <?php } ?> </tbody> </table> <ul> </ul>
现在,请求 URL https://127.0.0.1:8080/ 将显示如下页面:
步骤 12:创建添加书籍的动作
创建将新书添加到书店的函数。在 book 控制器中创建一个新的动作 action_add,如下所示:
public function action_add() { // create a new fieldset and add book model $fieldset = Fieldset::forge('book')->add_model('Model_Book'); // get form from fieldset $form = $fieldset->form(); // add submit button to the form $form->add('Submit', '', array('type' => 'submit', 'value' => 'Submit')); // build the form and set the current page as action $formHtml = $fieldset->build(Uri::create('book/add')); $view = View::forge('book/add'); $view->set('form', $formHtml, false); if (Input::param() != array()) { try { $book = Model_Book::forge(); $book->title = Input::param('title'); $book->author = Input::param('author'); $book->price = Input::param('price'); $book->save(); Response::redirect('book'); } catch (Orm\ValidationFailed $e) { $view->set('errors', $e->getMessage(), false); } } $this->template->title = "Book add page"; $this->template->content = $view; }
这里执行以下两个过程:
使用 Fieldset 方法和 Book 模型构建添加书籍的书籍表单。
当用户输入书籍信息并提交表单时,处理书籍表单。可以通过检查 Input::param() 方法是否存在任何提交的数据来找到它。处理表单包括以下步骤:
收集书籍信息。
验证书籍信息。我们已经在保存方法之前设置了要调用的验证。如果验证失败,它将抛出 Orm\ValidationFailed 异常。
将书籍信息存储到数据库中。
成功后将用户重定向到 index 页面。否则,再次显示表单。
我们在同一个动作中同时显示表单和处理表单。当用户第一次调用该动作时,它将显示表单。当用户输入书籍信息并提交数据时,它将处理表单。
步骤 13:为添加书籍动作创建视图
为添加书籍动作创建视图。创建一个新文件 fuel/app/views/book/add.php 并输入以下代码:
<style> #form table { width: 90%; } #form table tr { width: 90% } #form table tr td { width: 50% } #form input[type = text], select { width: 100%; padding: 12px 20px; margin: 8px 0; display: inline-block; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } #form input[type = submit] { width: 100%; background-color: #3c3c3c; color: white; padding: 14px 20px; margin: 8px 0; border: none; border-radius: 4px; cursor: pointer; } #form div { border-radius: 5px; background-color: #f2f2f2; padding: 20px; } </style> <div id = "form"> <h2>Book form</h2> <?php if(isset($errors)) { echo $errors; } echo $form; ?> </div>
这里,我们只是显示在 action 方法中创建的表单。此外,我们还显示错误(如果有)。
步骤 14:检查添加书籍动作
请求 url https://127.0.0.1:8080/book/add 或点击“添加书籍”导航链接,将显示如下表单:
表单
包含数据的表单
输入书籍信息并提交页面后,书籍信息将存储到数据库中,页面将重定向到 index 页面,如下所示。
包含新添加书籍的书籍列表
步骤 15:创建编辑书籍的动作
创建编辑和更新现有书籍信息的函数。在 book 控制器中创建一个新的动作 action_edit,如下所示。
public function action_edit($id = false) { if(!($book = Model_Book::find($id))) { throw new HttpNotFoundException(); } // create a new fieldset and add book model $fieldset = Fieldset::forge('book')->add_model('Model_Book'); $fieldset->populate($book); // get form from fieldset $form = $fieldset->form(); // add submit button to the form $form->add('Submit', '', array('type' => 'submit', 'value' => 'Submit')); // build the form and set the current page as action $formHtml = $fieldset->build(Uri::create('book/edit/' . $id)); $view = View::forge('book/add'); $view->set('form', $formHtml, false); if (Input::param() != array()) { try { $book->title = Input::param('title'); $book->author = Input::param('author'); $book->price = Input::param('price'); $book->save(); Response::redirect('book'); } catch (Orm\ValidationFailed $e) { $view->set('errors', $e->getMessage(), false); } } $this->template->title = "Book edit page"; $this->template->content = $view; }
它与添加动作类似,只是在处理页面之前按 id 搜索请求的书籍。如果在数据库中找到任何书籍信息,它将继续并显示表单中的书籍信息。否则,它将抛出文件未找到异常并退出。
步骤 16:为编辑动作创建视图
为编辑书籍动作创建视图。这里,我们使用与添加动作相同的视图。
步骤 17:检查编辑书籍动作。
点击书籍列表页面中任何书籍的编辑链接,它将显示相应的书籍表单,如下所示:
包含书籍详细信息的表单
步骤 18:创建删除书籍的动作
创建从书店删除书籍的函数。在 book 控制器中创建一个新的动作 action_delete,如下所示:
public function action_delete($id = null) { if ( ! ($book = Model_Book::find($id))) { throw new HttpNotFoundException(); } else { $book->delete(); } Response::redirect('book'); }
这里,我们使用提供的书籍 ID 检查数据库中是否存在书籍。如果找到书籍,则将其删除并重定向到 index 页面。否则,将显示页面未找到信息。
步骤 19:检查删除动作
通过点击书籍列表页面中的删除链接来检查删除动作。它将删除请求的书籍,然后再次重定向到 index 页面。
最后,创建了添加、编辑、删除和列出书籍信息的所有功能。
与其他基于 MVC 的 PHP 框架相比,FuelPHP 简单、灵活、可扩展且易于配置。它提供现代 MVC 框架的所有功能。它可以按原样使用,也可以完全更改以适应我们的需求。最重要的是,它是 Web 开发的绝佳选择。