第二章:入门
很快你就会发现,真正了解Yii只需要使用它。在这一章中,我们将讲解一个Yii应用,更深刻的了解上一章所介绍的Yii的一些概念。遵循Yii的约定,我们写一个Hello, World程序试用这个框架。
在这一章中,我们将介绍:
-
- Yii框架安装
- 创建一个新的应用
- 创建控制器和视图
- 添加动态内容到视图文件
- Yii请求路由并将页面链接到一起
在使用Yii之前,我们首先需要安装框架,现在让我们开始吧。
安装Yii
在安装Yii之前,你必须配置好你的开发环境,如一台支持PHP5.1.0以上版本的Web服务器。Yii已经在Windows和Linux操作系统上的 Apache Web服务器测试通过。它可能也会运行在其他平台上的支持PHP5的Web服务器,互联网上公布了很多免费资源,你可能会获得一个配置好PHP5的Web 服务器环境。在这里我们会抛开Web服务器和PHP5的安装。
Yii的安装其实非常简单,实际只需要两个步骤:
-
- 从http://www.yiiframework.com/下载Yii框架
- 解压下载文件到Web服务器可访问的目录下。
安装完成后,建议你检查一下当前服务器是否已经满足了Yii的所有要求。幸运的是,这样做很容易,Yii自带了一个简单的检查工具。要调用它,在你的浏览器地址栏中输入:http://yourhostname/path/to/yii/requirements/index.php
在下载Yii时,可能会有多个版本让你选择。编写本书时Yii最稳定的版本是1.1.2,虽然大部份的示例代码都应该可以运行在1.1.x版本上,但可能部份会有些差别。如果你使用的不同这个版本,请使用1.1.2版本完成下面的例子。
下面的图片显示的你在屏幕看到的结果,这就是你服务器的配置:
使用检查工具,确定服务器没有安装和使用扩展或组件,但它只是给出一个建议,以确保可以确定安装。正如你看到的,下在的检查结果,并非都是 Passed(通过)状态,也有部份显示Warning(警告)。当然,你的配置情况可能会略有不同,因此,你的显示结果也会有所不同。其实下面的细节部份没有必要全部能通过。但部份也是必要的,根据 Conclusion(结论)这个段落的内容:
你的服务器配置满足了Yii的最低要求。(Your server configuration satisfies the minimum requirements by Yii.)
安装数据库
在本书中,许多的示例中都将使用到数据库,我们会在用到时给出提示。这了能好更好跟着书中的例子操作,建议你安装一个数据库服务。Yii通过PHP本身可以支持多种数据库,如果你想使用Yii内置的数据库抽象层,这需要框架的支持。从1.1版本开始,支持的数据库有:
-
- MySQL 4.1或更高版本
- PostgresSQL 7.3或更高版本
- SQLite 2 和 3
- Microsoft SQL Server 2000或更高版本
- Oracle
现在我们已经安装了Yii框架,并已经检查了服务器配置符合要求,让我们开始创建一个全新的Yii框架的Web应用程序吧。
创建一个新的应用程序
要创建一个新的应用程序,我们将使用框架附带的一个小工具yiic,这是一个命令行工具,可以使你快速的建立一个全新的Yii应用。你不是必须要用此工具才能创建Yii应用,但使用它将节省你大量的时间,并保证文件及目录的结构。
要使用此工用创建Yii应用,需要打开一个shell窗口,并进入到系统的一个位置来创建应用程序的目录结构。为了这个演示程序,我们将确保如下要求:
-
- Yii的安装位置是你已经知道的
- WebRoot是你的Web服务器配置的根目录
- 从你的命令行,进入到WebRoot目录,并执行以下内容:
% cd Webroot % YiiRoot/framework/yiic webapp demo Create a Web application under '/WebRoot/demo'? [Yes|No] Yes mkdir /WebRoot/demo mkdir /WebRoot/demo/assets mkdir /WebRoot/demo/css generate css/bg.gif generate css/form.css generate css/main.css
你的应用已经成功创建到了/WebRoot/demo下。这个webapp命令的作用是创建一个全新的Yii应用。它只需要指定一个参数,无论是绝对还是相对路径都会创建应用程序。它所生成的目录及文件只是应用程序的一个骨架。
现在,我们进入刚刚创建的demo目录,看看都创建了些什么:
% cd demo % ls –p assets/ images/ index.php themes/ css/ index-test.php protected/
下面是更详细的描述:
demo/ index.php Web应用程序的入口文件 index-test.php Web应用程序的测试入口文件 assets/ 包含发送的资源文件 css/ 包含CSS文件 images/ 包含图片文件 themes/ 包含应用程序主题文件 protected/ 包含所有需要保护的应用程序文件
随着在命令行执行一条简单的命令,我们已建立了Yii框架的目录结构和默认所需的文件。但是,这些文件及目录让你看起来有点害怕。刚开始,我们可以暂时忽视其中的一部分。其实这些文件和目录已经是一个可以工作的Web应用程序了,用yiic命令创建的应用程序是一个简单的应用程序。其中 Contact Us(联系我们)页面是一个典型的表单应用,并且还自动生成了登陆页面和基于Yii框架的授权及身份验证功能。如果你的Web服务器支持GD2图形库的扩展,你也会在联系表单项中看到一个CAPTCHA(验证码)。
只要你的Web服务器正在运行,你可以打开浏览器访问http://localhost/demo/index.php。你将看到Web应用程序的首页并显示Welcome to My Web Application(欢迎来到我的Web应用)和一些帮助信息,下面的图片主是这个示例首页的样子:
你会发现这个程序的顶部有一个导航栏,从左到右分别是:Home(首页),About(关于),Contact(联系),Login(登录)。让我从左到右点击一遍。这个示例中,About(关于)提供的是一个静态页面,Contact(联系)前页已经提到,提供的是一个表单,同时包括一个 CAPTCHA(验证码)输入框。(如果你没有安装GD2图形库扩展,将看不到验证码图片)。
点击Login(登录)链接将转到一个显示登录表单的页面。其实这是一个表单验证代码,通过用户名和密码进行验证。使用demo/demo或 admin/admin的用户名/密码组合进行登录。你也可尝试输入任意组合,将得到一个登录失败的信息。成功登录后,在顶部原来显示Login的链接变成了Logout(username)(其中username可能显示demo或admin,这取决于你用哪个用户名登录)。很神奇吧,你不需要任何编码,就完成了这么多的工作。
Hello, World!
我们将通过自动生成工具,完成一个简单且有意义的工作。让我们在新的应用上建立一个本章开始提到Hello, World!程序上。Hello, World程序在Yii中是一个简单的Web程序,它发送重要信息到我们的浏览器。
在第一章,认识Yii中,我们已经了解到Yii是一个MVC结构的框架。一个典型Yii的Web应用程序是等待用户通过浏览器传入一个请求后,解析该请求的信息,去查找一个对应的控制器,然后调用该控制器内的操作方法。该控制器可以调用一个特定的视图,然后将渲染后的内容返回给用户。在处理数据时,控制器也可以与模型交互来处理创建、读取、更新和删除(CRUD)等操作。在这个简单的Hello, World!示例中,我们只需要一个控制器和视图,我们不处理任何数据,这样将不需要模型。让我们开始创建控制器吧。
创建控制器
和最初开创应用程序一样,这里我们还是调用yiic命令帮助我们创建一个控制器。在这种情况下,我们将使用yiic shell命令来启动一个可以与Yii交互的shell。要启动shell,需进入到应用程序demo目录,如以下命令:
%cd /Webroot/demo
然后接着执行yiic命令:
%YiiRoot/framework/yiic shell(Fen注释:改成%YiiRoot/framework/yiic shell ../index.php) Yii Interactive Tool v1.1 Please type 'help' for help. Type 'exit' to quit. >>
如果你已经进入到了应用程序目录,你也可以调用相对路径protected/yiic命令,而不用使用Yii的安装目录。因此,与上面相同效果的启动shell命令是:
% protected/yiic shell
你当前显示的是与shell交互的提示符。你可以输入help查看shell为你提供的所有命令列表:
>> help At the prompt, you may enter a PHP statement or one of the following commands: - controller - crud - form - help - model - module Type 'help <command-name>' for details about a command.
我们看了有几个可选的命令,有一个controller命令看起来象是我们想要的,可能是用来为应用程序创建一个控制器的命令。我们可以在shell提标符下进一步了解controller命令的更多帮助信息。这些信息包括提供的用法说明,参数描述和一些例子。
>> help controller USAGE controller <controller-ID> [action-ID] ... (Fen注释:yiic命令,controller的规则,第一个参数是类的名称,后面是方法) DESCRIPTION This command generates a controller and views associated with the specified actions. PARAMETERS * controller-ID: required, controller ID, e.g., 'post'. If the controller should be located under a subdirectory, please specify the controller ID as 'path/to/ControllerID', e.g., 'admin/user'. If the controller belongs to a module, please specify the controller ID as 'ModuleID/ControllerID' or 'ModuleID/path/to/Controller' (assuming the controller is under a subdirectory of that module). * action-ID: optional, action ID. You may supply one or several action IDs. A default 'index' action will always be generated. EXAMPLES * Generates the 'post' controller: controller post * Generates the 'post' controller with additional actions 'contact' and 'about': controller post contact about * Generates the 'post' controller which should be located under the 'admin' subdirectory of the base controller path: controller admin/post * Generates the 'post' controller which should belong to the 'admin' module: controller admin/post
在最后两个例子中,使用的命令是一样的,但生成控制器所在的目录不同。Yii是能够检测出admin是一个模块还是一个子目录。
阅读帮助,很明显看出该命令会生成控制器和操作方法及视图文件。由于我们将要做的应用程序主要是显示一条消息,让我们调用controller message 和一个要显示的操作方法:
>> controller message helloWorld generate MessageController.php mkdir /Webroot/demo/protected/views/message generate helloworld.php generate index.php Controller 'message' has been created in the following file: /Webroot/demo/protected/controllers/MessageController.php You may access it in the browser using the following URL: http://hostname/path/to/index.php?r=message >>
它已经给出了创建成功的提示,MessageController默认创建到了 protected/controllers/目录下。
多么简单的一条命令,我们就创建了一个新的控制器,PHP文件名是MessageController.php,并放到了控制器目录 protected/controllers/中。新创建的MessageController类是继承应用程序的基类Controller,它的位置是 protected/components/Controller.php。这类是继承了框架的基础类CController。因此,MessageController继承了CController默认的所有行为。既然我们指了一个ActionID的参数是helloWorld,那么相对的也会在MessageController中也会创建一个actionHelloWorld()操作方法。yiic工具像在控制器中定义的操作方法一样,也承担了定义视图的代码。此视图文件与方法的id的名字一样,叫helloworld.php,此视图文件与控制器关联,默认存放在 protected/views/message/下。下面的代码是MessageController类的内容:
)
<?php class MessageController extends Controller { public function actionHelloWorld() { $this->render('helloWorld'); } public function actionIndex() { $this->render('index'); } }
我们看到,它也增加了一个actionIndex()方法,并简单渲染一个自动创建的视图文件protected/views /message/index.php。正如第一章中描述的那样,如果只指定了controllerID,但没有指定操作,Yii默认会路由到 actionIndex()方法做进一步处理。yiic太聪明了,知道我们需要一个默认的操作方法。
试着浏览 http://localhost/demo/index.php?r=message/helloWorld 地址,你应该看到如下画面:
最后一步
要让应用程序显示Hello, World!,我们需要定制视图文件helloWorld.php。这个很容易就可以做到,编辑protected/views/message/helloWorld.php,修改成如下代码:
<?php $this->breadcrumbs=array( 'Message'=>array('message/index'), 'HelloWorld', );?> <h1>Hello, World!</h1>
保存这段代码,并在再次访问http://yourhostname/demo/index.php?r=message/helloWorld
现在显示问题语的位置改变了,你应该看到如下画面:
我们用很少的代码完成了这个简单的应用,我们仅仅对helloWorld视图文件修改了一行HTML代码。
复习一下路由请求
让我们回顾一下运行这个应用程序Yii框架是如何分析的:
-
- 通过浏览器输入Hello, World地址http://yourhostname/demo/index.php?r=message/helloWorld
- Yii分析这个URL,这条路由表标controllerID是message,它将告诉Yii应该去请求MessageController.php文件,这个文件的位置是protected/controllers/MessageController.php。
- Yii还发现,actionID指定的是helloWorld,因此,会调用MessageController类中的actionHelloWorld()操作方法。
- actionHelloWorld()方法会渲染helloWorld.php视图文件,这个文件的位置是protected/views/message/helloWorld.php。同时,将这个视图内容返回给浏览器。
- 不需要任何配置,这些步骤是连在一起的。按Yii的默认约定,整个应用程序的路由请求是无缝的连在一起。当然,如果有必要改变这个流程,Yii已经给我们提供了这样的接口,但是,如果你使用约定,你将节约配置的时间。
添加动态内容
添加动态内容最简单的方法,就是在视图模板文件中嵌入PHP语句。通过视图文件提供的是HTML结果,任何普通文本不会改变的。然而,任何在标签之间的代码会作被执行。这是一个典型HTML中嵌入PHP代码的方法,你可能很熟悉。
添加日期和时间
为我们的页面添加动态内容,并显示日期和时间。再次打开helloWorld视图文件,并添加以下代码:
<h3><?php echo date("D M j G:i:s T Y"); ?></h3>
保存,并查看以下URL地址:http://yourhostname/demo/index. php?r=message/helloWorld
快看,我们已经为应用程序添加了动态内容,每刷新一次页面,将看到显示内容的变化。
不能否认,这并不能令你兴奋,但它确实表明,怎样将PHP代码嵌入到我们的视图模板中。
一个更好的添加日期和时间的方法
虽然这种直接嵌入PHP代码的做法根本不允许复杂的代码,但Yii强烈建议这些语句不改变数据模型,让他们保持简单明了。这将有助于使我们的业务逻辑与视图分离,这是MVC架构的一部份。
将数据移到控制器
让我们将创建时间的代码放到控制器中,视图只显示这个时间。我们将代码放到控制器的actionHelloWorld()方法中,设置一个变量$theTime保存时间。
-
- 首先,让我们改变控制器的操作方法。当前,我们在MessageController控制中的actionHelloWorld()中编下如下代码:
$this->render('helloWorld');
在render()方法这前,我们添加一段调用时间代码,将时间存入局域变量$theTime。然后我们添加render()方法的第二个参数,将$theTime这个变量传给redner()方法:$theTime=date("D M j G:i:s T Y"); $this->render('helloWorld',array('time'=>$theTime));
调用的render()方法第二个参数的数据是一个array(数组类型),render()方法会提取数组中的值提供给视图脚本,数组中的 key(键值)将是提供给视图脚本的变量名。在这个例子中,数组的key(键值)是time,value(值)是$theTime则提取出的变量名$time是供视图脚本使用的。这是将控制器的数据传递给视图的一种方法。 - 现在让我们在视图中使用这个变量而不使用date(日期函数)。再次打开helloWorld视图,替换之前添加过的时间代码为:
<h3><?php echo $time; ?></h3>
- 保存并查看结果:http://yourhostname/demo/index.php?r=message/helloWorld
- 首先,让我们改变控制器的操作方法。当前,我们在MessageController控制中的actionHelloWorld()中编下如下代码:
下面的图片显示了我们这个应用程序的最终看到的结果,Hello World!(当然你的日期和时间会有所不同)
我们已经讲解了两种在PHP视图模板中生成内容的方法。第一种方法把数据逻辑直接在视图文件中创建。第二种方法把数据逻辑放到控制器中,然后提供给视图一个可用变量。两种方法最终的结果是同样的,时间显示在了HTML页面上。但第二个办法有一个小小的进步,他将业务逻辑的数据与视图分开。MVC架构的目的就是这种分离模式,Yii清晰的目录结构和合理的默认约定使它们连接到了一起。
你有没有注意?
在第一章提到,视图与控制器是非常紧密的兄弟,所以视图文件中的$this指的就是渲染这个视图的控制器。
修改前面的示例,在MessageController中定义一个类的公共属性,而不是局部变量,它是值就是当前的日期和时间。然后在视图中通过$this访问这个类的属性。
在前的的例子中,我们通过给控制器中render()方法传递第二个参数,将时间变量传递给视图。第二个参数提取出的变量,可以在视图中使用。但还有另一种方法,我们鼓励你自己去尝试。
把网页连接在一起
典型的网络应用程序展示给用户的页面不会只有一个。虽然我们的示例很简单,但也不会例外。让我们再增加一个页面,与Hello, World相反的内容,Goodbye, Yii developer!,并在两个页面添加互通的超链接。
通常,每个Yii的Web应用程序,都对应一个单独的视图文件(尽管不一定总是这样)。因此,我们将创建一个新的视图,并使用一个单独的操作方法来显示这个视图。什么时候添加这个页面呢?我们还需要考虑,是否使用一个单独的控制器。由于Hello与Goodbye的页面很相似,所以没有理由将这个应用逻辑放到一个单独的控制器。
连接到新页面
新页面的URL如下所示:http://yourhostname/demo/index.php?r=message/goodbye
-
- 根据Yii的约定,我们不但需要在控制器中定义操作方法,也需要一个视图名称。因此,打MessageController控制器文件,在actionHelloWorld()下面添加actionGoodbye()操作方法。并在操作方法中添加渲染的的视图名称。具体代码如下:
class MessageController extends CController { ... public function actionGoodbye() { $this->render('goodbye'); } ... }
- 下一步,我们要在protected/views/message/目录下创建视图文件,这个视图文件的名字与actionID相同,叫goodbye.php
- 打开这个空的模板文件,添加一行代码:
<h1>Goodbye, Yii developer!</h1>
- 保存并再次查看:http://yourhostname/demo/index.php?r=message/goodbye 应该显示goodbye的信息。
- 现在我们需要添加超链接,把两个页面连接起来,若要从Hello, World!页面添加一个链接到goodbye页面,我们可以在helloWorld视图文件中添加一个标签指向 goodbye,URL结构如:
<a href="/demo/index.php?r=message/goodbye">Goodbye!</a>
- 根据Yii的约定,我们不但需要在控制器中定义操作方法,也需要一个视图名称。因此,打MessageController控制器文件,在actionHelloWorld()下面添加actionGoodbye()操作方法。并在操作方法中添加渲染的的视图名称。具体代码如下:
请大家记住,这只是个推荐的命名约定。其实视图文件名不必与ActionID相同,只需要将文件的名字作为第一个参数传递给render()就可以了。
这当然可以工作,但它仅仅是执行了一个特定URL结构,这个结构可能在某个时候发生变化,如果URL结构变化了,那这些链接将会失效。
记得在第一章中,我们介绍Blog(博客)示例时,使用了一个特别的URL地址,它的格式更加友好,并且对SEO优化也不错,如:http://yourhostname/ControllerID/ActionID一个简单的配置,就可以轻易的将现在的URL结构,改成这种路径格式的。能够改变成这种方法,对应用程序来说非常重要。只要我们避免在应用中对URL使用硬编辑,那么改变成路径格式将非常简单。
使用Yii的CHtml得到一些帮助
这种情况可以使用Yii来处理,Yii提供了许多HTML助手,可在视图模板中使用。这些HTML助手都是以静态类的方式存在的。在当前的情况下,如何为应用程序配置URL结构呢?我们希望能过调用CHtml的link方法,link方法需要一个参数是 controllerID/actionID 成对出现的字符串,另一个超连接显示的名字。由于所有助手都是静态的,所以我们可以直接调用,而不需要创建它的实例。
-
- 使用链接助手,helloWorld视图将会变成:
<h1>Hello, World!</h1> <h3><?php echo $time; ?></h3> <p><?php echo CHtml::link("Goodbye",array('message/goodbye')); ?></p>
- 保存更改,并查看:http://yourhostname/demo/index.php?r=message/helloWorld你应该看到这个超链接,点击它应该转到goodbye页面。link助手的第一个参数是链接的显示文本,第二个参数是一个数组,值就是controllerID/actionID。结果如下图所示:
- 我们可以按照同样的方法为goodbye视图添加链接:
<h1>Goodbye, Yii developer!</h1> <p><?php echo CHtml::link("Hello",array('message/helloWorld')); ?></p>
- 保存视图文件,并访问如下URL地址:http://yourhostname/demo/index.php?r=message/goodbye
你现在应该能从goodbye页面看到回到Hello, World!页面的链接,下面是goodbye页面的截图:
- 使用链接助手,helloWorld视图将会变成:
小结
在这一章中,我们创建了一个非常简单的应用,包括以下几个方面:
-
- 如何安装Yii框架
- 如何使用yiic命令创建一个新的应用
- 如何使用yiic命令创建一个新的控制器
- Yii是如何处理你的请求
- 如何在控制器中创建动态内容,并将内容显示给浏览器
- 如何网站内部的超连接
我们已经知道如何将我们的应用程序页面连接在一起。一种方法是在视图文件中添加HTML的标签以硬编码方法书写URL结构。另一种(首选)是使用Yii的CHtml助手,帮助你建立controllerID/actionID格式的URL地址,这样格式的结构,将始终与应用程序的配置关联,即使整个应用程序的URL地址改变了,我们也不用去修改内部的URL,从而保证了应用程序内部的链接不失效。
通过Hello, World!这个简单的示例,我们了解到了一些Yii的配置理念,通过一些默认推荐约定,这个简单的应用(和整个路由的请求过程)的开发是如此的简单和方便。
通过创建这个简单的应用程序,让我们更好的理解怎样使用Yii框架,它证明了使用Yii建立应用程序是如此的简单,在下一章,我们将为你介绍一个关于项目的任务管理和问题跟踪的应用程序,这个应用将贯穿本书的其余章节。