应用Yii和PHP5进行web的敏捷开发翻译_第1页
应用Yii和PHP5进行web的敏捷开发翻译_第2页
应用Yii和PHP5进行web的敏捷开发翻译_第3页
应用Yii和PHP5进行web的敏捷开发翻译_第4页
应用Yii和PHP5进行web的敏捷开发翻译_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.z应用Yii和PHP5进展web的敏捷开发第十二章:迭代9:添加管理模块到目前为止,我们已经给TrackStar应用程序增加了很多功能。如果你还记得在第8章,我们介绍了使用基于用户角色的层次构造来限制用户*些功能。这有助于限制对一些单一工程的管理职能的。例如:在一个特定的工程中,你可能不希望让所有的成员都有删除权限。我们为用户分配到一个工程内的特殊角色来实现基于角色的控制,然后控制这些角色是否有该功能的权限。然而,我们尚未解决的是整个应用程序的管理需求。例如TrackStarWeb应用程序经常需要的有一个非常特殊的用户拥有所有的管理权限。其中一个例子就是让系统的每一个用户拥有CURD操作,而不仅仅是工程。我们应用程序的系统管理员应该有以下权限:能够登录,删除或者修改用户、工程、问题,管理所有的评论,等等。同时,我们经常建立适用于整个应用程序的额外功能,如能给所有用户发布站点系统信息,管理电子运动,翻开/关闭*些应用功能,管理角色的层次,改变站点主题,等等。因为管理员的权限与用户的权限有极大的不同,把这些功能和应用程序别离是一个好想法。我们将通过Yii模块建立所有的管理功能来完成这个别离。12.1迭代方案在这个迭代中,我们将集中完成以下开发任务:•创造一个新的模块来存放管理功能•为系统管理员建立系统播送功能,用户可以在工程列表页面查看•为应用模块添加一个新课题•创立一个新表保持系统消息数据•为系统信息生成所有的CURD操作•只允许管理用户使用新模块中的功能•在工程列表页面显示新系统信息12.2模块模块类似于一个大型应用程序中的小型应用程序。它有与应用程序类似的构造,包含模型、视图、控制器及其他支持组件。然而,模块不能作为独立的应用程序,它们必须嵌入*一个应用程序。Modules在帮助你的应用程序模块化架构方面很有用。大型的应用程序经常可以分成几个离散的应用程序,这些离散的应用程序也可以用模块来构建。站点功能,如添加一个用户论坛,用户博客或站点管理员功能都是一些例子,说明从主站点功能别离出来的功能,可以让它们单独开发,并且容易在未来的方案中重用。我们将在应用程序中不同的位置建立存放管理功能的模块。12.3创立一个模块使用我们的老朋友,Gii代码生成工具创立一个新模块是很容易的。伴随着我们的URL的改变,要通过://localhost/trackstar/gii来该工具。翻开后,在左边的菜单中选择ModuleGenerator选项。你将看到下面的画面:我们需要给模块取一个唯一的名字。由于我们正在创立一个管理模块,我们可以命名为admin。在ModuleID内输入admin,点击Preview按钮。如以下列图所示,它会向你展示它将会生成的所有文件,让你在创立之前预览这些文件:然后点击Generate按钮来生成这些文件。由于web效劳器进程它自动创立文件夹和文件的要求,所以要确保你的/protected文件夹是可写入的。下面的截图显示一个成功的模块生成:让我们更进一步的看看这个自动生成的模板。Yii中模块是以一个文件夹组织的,文件夹的名字就是该模块的名字。默认情况下,居所有的模块保存在/protected/modules目录下。每个模块文件夹的构造都与主应用程序非常相似。这个指令为我们所做的是创立admin模块建立脚手架文件夹构造。因为这是我们的第一个模块,顶层的文件夹/protected/modules被创立了,然后将admin文件夹放在里面。下面为我们展示了模块命令行为我们建立的所有文件夹和文件:一个模块必须拥有一个模块继承自CWebModule或其子类。该模块类的名字由模块ID(在这里指admin)和字符串Module联合生成。模块ID的第一个字母大写。所以,在我们的例子中,我们的admin模块类文件被命名AdminModule.php。模块类主要作为存储模块代码共享信息的中转站。例如,我们可以用CWebModule的params属性来存储模块性能的具体参数,并利用其ponents属性在模块级分享应用程序的组件。这个模块类在模块中的作用类似于应用程序类对整个应用程序的作用。所以CWebModule是对模块的就像CWebApplication是对应用程序的。12.4使用一个模块正如成功建立的信息说明,在我们使用新模块之前,我们需要在主应用程序中设置modules属性,才可以使用它。在添加gii模块应用程序之前,允许我们使用gii代码生成工具。我们对主要配置文件protected/config/main.php进展改变。以下代码显示了所需的改变:PHP代码:'modules'=>array('gii'=>array('class'=>'system.gii.GiiModule','password'=>'iamadmin',),'admin',),保存这个改变后,我们的新admin模块就可以使用了。我们可以先通过://localhost/trackstar/admin/default/inde*来看一下。该请求显示的模块的页类似于我们的主应用程序页,除了我们需要在路由中添加moduleID。所以我们的路径形式如下:moduleID/controllerID/actionID。我们URL请求/admin/default/inde*应该解释为admin模块的default控制器的inde*方法。当我们这个页面,我们看到类似下面的画面:12.5主题化一个模块我们立刻发现这一视图〔View〕似乎没有应用任何布局〔Layout〕。有人可能会想,控制器渲染视图时用的是renderPartial(),而不是render()。然而,在检查我们的默认的admin的controller文件,/protected/modules/admin/controllers/DefaultController.php时,我们可以看到,事实上它使用的是render()方法。因此,我们需要使用一个layout文件(如果有的话)。问题是在模块中几乎一切都是独立的,包括layout文件的默认路径。模块布局的默认路径是/protected/modules/[moduleID]/views/layouts,在我们的例子中moduleID应该是admin。我们可以看到,在这个文件夹中没有文件,所以没有应用默认布局。在这里多讲一点。在上一次迭代中,我们实现了一个名为new的新主题。我们也可以通过这个主题管理我们所有的模块view文件,包括layoutview文件。如果我们这样做,我们需要增加一些主题文件夹构造以适应我们的新模块。文件夹的构造与预期的一样。大致上为:/themes/[themeName]/views/[moduleID]/layouts/为布局文件,/themes/[themeName]/views/[moduleID]/[controllerID]/为对应controller的视图文件。为了说得更清楚,我们模拟一次admin模块调用view的过程的Yii决策流程。下面就是admin模块的DefaultController.php文件中$this->render('inde*')的渲染过程:当render()被调用,与renderPartial()不同,它会尝试用一个layout文件来修饰指定的视图文件inde*.php。我们的应用程序现在被配置使用名为new的主题,所以要在这个主题文件夹中找到layout文件。我们的新模块的DefaultController类继承自我们的应用程序组件controller.php,所以使用了column1作为指定的$layout的属性值。这个属性没有被重写,所以这也是DefaultController的Layout值。最后,当这些都在admin模块中完成后,Yii首先寻找以下layout文件:/themes/new/views/admin/layouts/column1.php。注意到在这个文件夹构造包含了moduleID。这个文件不存在,所以在模块的着默认位置查找。如前所述,每一个模块都有特定的默认布局文件夹。因此,在这种情况下,它将试图找到下面的layout文件:/protected/modules/admin/views/layouts/column1.php.这个文件也不存在,因此它将不会使用layout。现在只是在没有布局时尝试简单的渲染指定试图文件inde*.php。但是,我们已经为应用程序定义了特定的主题new,所以它将首先寻找以下的视图文件:/themes/new/views/admin/default/inde*.php。这个文件也不存在,则它将再次查找在这个模块(AdminModule)的控制器(DefaultController.php)的默认位置,即:/protected/modules/admin/views/default/inde*.php。这就解释了为什么网页://localhost/trackstar/admin/default/inde*被渲染了却没有任何布局。现在,为了使事情变得完全别离和简单,让我们管理一下在我们的模块的默认位置的视图文件,而不是在主题new内。让我们为admin模块应用我们为原始应用程序设计的主题,就是在使用新主题前的样子。这样的话,我们的admin模块的页面就会和正常应用程序页面有所不同,这将有助于提醒我们,我们是在特殊的admin事务,但我们不需要花任何时间想出一个新设计。12.6应用一个主题首先,让我们为模块设定一个默认的layout值。我们在模块类的int()方法设置我们的的模块级配置,模块类位于/protected/modules/AdminModule.php。翻开这个文件,并且添加下面的代码:PHP代码:classAdminModulee*tendsCWebModule{publicfunctioninit(){//当模块创立时,调用这个方法//你可以在这里用代码来自定义模块或应用程序//导入模块级模型和组件$this->setImport(array('admin.models.*','admin.ponents.*',));$this->layout='main';}...这样一来,如果我们在更细化的水平没有特别指定布局文件,像在一个控制器类中,模块的所有视图将会调用位于/protected/modules/admin/views/layouts/下的main.php布局文件来修饰。现在,我们自然需要创立这个文件。从主应用程序复制两个布局文件:/protected/views/layouts/main.php和/protected/views/layouts/column1.php,并把他们两个放在/protected/modules/admin/views/layouts/文件夹。复制完之后,我们需要对它们做一些修改。首先修改column1.php文件。在beginContent()中去除对/layouts/main的引用,修改后代码如下:PHP代码:<?php$this->beginContent();?><divclass="container"><divid="content"><?phpecho$content;?></div><!--content--></div><?php$this->endContent();?>在未指明导入文件时调用beginContent(),将会使用模块的默认的布局文件,而我们刚刚将其指定到新复制的main.php文件。现在让我们对main.php布局文件做一些修改。我们打算给应用程序头部添加AdminConsole文本,来强调我们是应用程序的一局部。我们也将修改我们的菜单项,添加一个到管理主页的,以及一个回到主站点的。我们可以消除这个菜单的About和Content,因为我们并不需要在管理局部重复这些选项。修改后代码如下:PHP代码:...<divclass="container"id="page"><divid="header"><divid="logo"><?phpechoCHtml::encode(Yii::app()->name)."AdminConsole";?></div></div><!--header--><divid="mainmenu"><?php$this->widget('zii.widgets.CMenu',array('items'=>array(array('label'=>'BackToMainSite','url'=>array('/project')),array('label'=>'Admin','url'=>array('/admin/default/inde*')),array('label'=>'Login','url'=>array('/site/login'),'visible'=>Yii::app()->user->isGuest),array('label'=>'Logout('.Yii::app()->user->name.')','url'=>array('/site/logout'),'visible'=>!Yii::app()->user->isGuest)),));?></div><!--mainmenu-->...文件其余局部不变。现在如果我们admin模块页面,我们看到类似下面的画面:如果我们点击BackToMainSite的,我们被带回到最新主题主应用程序。12.7限制admin模块的一个你可能已经注意到的问题是:任何用户,包括游客都可以我们的新的admin模块。但实际上我们建立admin模块只想将该功能提供给拥有管理员权限的用户。所以我们要解决这个问题。幸运的是,我们已经在第8章就在应用程序中实现了RBAC模型。我们现在要做的是将其扩大,包括一个新的管理员角色和该角色的管理权限。如果你回忆一下在第八章中,我们使用了一个Yii脚本命令来实现RBAC的构造。我们需要增加命令。所以,翻开包含脚本命令的文件,/protected/mands/shell/Rbacmand.php和添加以下内容:PHP代码://给管理员创立一个常规的任务级权限$this->_authManager->createTask("adminManagement","accesstotheapplicationadministrationfunctionality");//创立站点管理员的角色,并添加适当的权限$role=$this->_authManager->createRole("admin");$role->addChild("owner";$role->addChild("reader");$role->addChild("member");$role->addChild("adminManagement");//确保我们系统内有一个管理员(使它是用户的id号为1)$this->_authManager->assign("admin",1);当着修改完成后,我们必须重新运行我们的命令来更新数据库。这样做之后,翻开yiicshell,执行rbac的命令:%cdWebroot/trackstar%protected/yiicshell>>rbac当我们对RBAC模型修改完后,我们可以添加一个检查AdminModule:beforeControllerAction()方法,这样admin模块中没有什么事物会被执行,除非用户是admin角色:PHP代码:publicfunctionbeforeControllerAction($controller,$action){if(parent::beforeControllerAction($controller,$action)){//在模块控制器执行actions之前,调用这个方法//你可以在这里自定义代码if(!Yii::app()->authManager->checkAccess("admin",Yii::app()->user->id)){thrownewCE*ception(403,Yii::t('yii','Youarenotauthorizedtoperformthisaction.'));}else{returntrue;}}elsereturnfalse;}当这些都完成后,如果在admin模块中,一个没有被分配到admin角色的用户试图网页,他们将会遇到授权错误页面。例如,如果你在没有登录的情况下,试图管理页面,你会遇到以下结果:这同样适用于任何未被指派admin角色的用户。现在,我们可以在主应用程序菜单添加admin局部的。这样,拥有管路员权限的用户不需要记住的是繁琐的URL就可以进入到管理控制台。作为一个提示,我们的主应用程序菜单位于应用主题的默认布局文件中,/themes/new/views/layouts/main.php。翻开这个文件,并且作如下修改:PHP代码:<divid="mainmenu"><?php$this->widget('zii.widgets.CMenu',array('items'=>array(array('label'=>'Projects','url'=>array('/project')),array('label'=>'About','url'=>array('/site/page','view'=>'about')),array('label'=>'Contact','url'=>array('/site/contact')),array('label'=>'Admin','url'=>array('/admin/default/inde*'),'visible'=>Yii::app()->authManager->checkAccess("admin",Yii::app()->user->id)),array('label'=>'Login','url'=>array('/site/login'),'visible'=>Yii::app()->user->isGuest),array('label'=>'Logout('.Yii::app()->user->name.')','url'=>array('/site/logout'),'visible'=>!Yii::app()->user->isGuest)),));?></div><!--mainmenu-->现在,使用有admin权限的用户登录应用程序,我们将会看到在顶部的导航中有一个新的,它将带我们到站点新添加的admin局部。12.8添加系统级的信息由于一个模块可以被认为是一个小型应用程序,因此,向模块添加功能和向主程序添加功能具有一样的步骤。让我们只为管理员添加一些新功能;这个功能可以使他们第一次登录应用程序时向用户显示的系统级信息。12.9创立数据库表和创立新功能一样,我们需要一个地方来放置我们的数据。我们需要创立一个新的表来存储我们系统级的信息。对于我们而言,我们可以简单一点。下面是我们数据表表的定义:SQL代码:CREATETABLE`tbl_sys_message`(`id`INTEGERNOTNULLPRIMARYKEYAUTO_INCREMENT,`message`TE*TNOTNULL,`create_time`DATETIME,`create_user_id`INTEGER,`update_time`DATETIME,`update_user_id`INTEGER)在主要的trackstar_dev和我们的trackstar_test数据库中都创立这个新表。12.10创立模型和CRUD脚手架当表建立好以后,下一步就是使用Gii代码生成器来建立模型类了。我们将首先使用ModelGenerator来创立模型类,然后用CrudGenerator创立脚手架来与该模型快速互动。接下来,引导Gii工具表单来创立一个新的模型。这一次,我们是在模块内容中做的,我们需要明确指定模型的路径。用下面的图中所描述的值填写表单〔当然,你的CodeTemplate路径值应该是具体到您的本地设置〕:现在,我们可以用一样的方式创立的CRUD脚手架。同样的,以前我们所做的与我们现在正在做的之间的唯一的区别在于模型类的位置是在admin模块中。从Gii工具选择CrudGenerator选项后,按照如以下列图填写ModelClass和ControllerID:这里要注意一点,我们的模型类是在admin模块之中的,我们的控制类以及所有其他与这个代码生成有关的文件也应被放置在管理模块中。通过点击Preview按钮后点击Generate按钮完成文件创立。以下列图是所有被创立的文件列表:12.11将添加到我们的新功能让我们在主admin局部导航内添加一个新的菜单项到我们新建的消息功能。翻开含有我们的主菜单导航的文件,/protected/modules/admin/views/layouts/main.php,并将在menu不见添加以下数组项:array('label'=>'SystemMessages,'url'=>array('/admin/sysMessage/inde*')),由于为新的系统消息功能自动创立controller和view文件使用了2列布局文件,我们可以做以下两件事之一:我们可以改变controller文件让它使用我们现有的单个列布局文件,或者我们可以新增2列的布局文件到我们的admin模块。后面的会很容易做到,也会更好看,因为所有的view文件都被设计成拥有一个自菜单项,里面存放了所有crud功能的连接,而该菜单项被放在右边的一列中。下面是我们所要做的步骤:1.从主应用程序中复制2列布局到admin模块:即复制/protectediews/layouts/column2.php和/protected/modules/admin./views/layouts/column2.php。2.删除新复制的column2.php文件中的第一行上的beginContent()方法的输入内容/layouts/main。3.修改SysMessage()模型类,使之继承自TrackstarActiveRecord(如果你还记得,这将添加代码自动更新create_time/user和update_time/user属性)。更新SysMessageController控制器类使用新的位于模块文件内的column2.php布局文件,而不是主应用程序的。自动生成的代码中$layout='application.views.layouts.column2',但我们需要的修改$layout='column2'。4.由于我们继承自TrackstarActiveRecord,我们可以删除在自动生成系统消息创立的窗体中不必要的字段和模型的类,同时移除与之工程的模型类中的rules。在SysMessage::rules()方法中移除一下内容:array('create_user,update_user,'numerical,'integerOnly'=>true)还有array('create_time,update_time,'safe')。最后一步不是必需的,但它的好处是只验证这些用户可以输入字段规则的习惯。最后一个需要修改的是,我们应该是更新我们简单的规则,来实现只有admin角色中的用户可以这个方法的需求。这也是为什么我们在AdminModule::beforeControllerAction()方法中使用RBAC模型的原因。我们实际上可以将accessRules完全删除。但是,我们要通过更新它以实现要求,所以你在下面可以看到,如何使用规则的方法。使用以下的代码替换SysMessageController::accessRules()方法:PHP代码:publicfunctionaccessRules(){returnarray(array('allow',//只允许用户有“admin〞的角色才可以进入行动'actions'=>array('inde*','view','create','update','admin','delete'),'roles'=>array('admin'),),array('deny',//否认所有用户'users'=>array('*'),),);}好了,都改完以后,如果使用localhost/trackstar/admin/sysMessage/create新消息输入表单,我们将看到类似以下列图的界在表单中填写HellowUsers!Thisisyouradminspeaking…后点击Submit按钮。应用程序将重定向到类似下面的新建消息的清单页面:12.12向全体用户显示消息现在我们已经将消息存入在我们的系统,我们将展示给在应用程序的主页的用户。12.13在应用程序级导入新模型类为了在应用程序中随时我们新创立的模型,我们应当将其配置为应用程序的一局部。修改protected/config/main.php文件内容如下:PHP代码://半自动生成模型和组件类'import'=>array('application.models.*','application.ponents.*','application.modules.admin.models.*',),12.14选择最近更新的消息我们将限制只显示一条消息,并且会根据表中的update_time来选择。我们希望把它添加到主工程列表页面,所以我们需要修改ProjectController::actionInde*()方法。通过添加以下代码来改变该方法:PHP代码:publicfunctionactionInde*()

{

$dataProvider=newCActiveDataProvider('Project');Yii::app()->clientScript->registerLinkTag('alternate','application/rss+*ml',$this->createUrl('ment/feed'));//基于update_time获得系统最新显示的消息

$sysMessage=SysMessage::model()->find(array(

'order'=>'t.update_timeDESC',));if($sysMessage!=null)

$message=$sysMessage->message;else

$message=null;$this->render('inde*',array(

'dataProvider'=>$dataProvider,'sysMessage'=>$message,));

}现在,我们需要改变我们的视图文件来显示新内容。只需要在views/project/inde*.php的<h1>Projects</h1>上添加以下代码:PHP代码:<?phpif($sysMessage!=null):?>

<divclass="sys-message">

<?phpecho$sysMessage;?>

</div>

<?phpendif;?>现在我们只要我们的工程列表页面〔即我们的应用程序主页〕,就会看到如以下列图所显示的内容:12.15添加少许的设计调整好了,这完成了我们想要做的,但是对用户来说,这条消息并不是最完美的,我们可以在我们的css主文件中〔/themes/new/css/main.css〕添加一点片段来做一点修改:CSS代码:div.sys-messa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论