《PHP实战:Symfony控制层深入详解》要点:
本文介绍了PHP实战:Symfony控制层深入详解,希望对您有用。如果有疑问,可以联系我们。
			           
本文深入分析了Symfony控制层.分享给大家供大家参考,具体如下:PHP学习
Symfony中控制层包含了连接业务逻辑与表现的代码,控制层为不同的使用分成了几个不同的部分.PHP学习
1. 前端控制器是指向应用的唯一入口
2. 动作包含了应用的逻辑,他们检查哀求的完整性并准备好表示层需要的数据
3. 哀求、响应和Session对象提供访问哀求参数、响应参数以及持久的用户数据,这些数据在控制层使用的很普遍
4. 过滤器是每个哀求都要执行的代码的一部分,无论在动作前还是在动作后.可以自创过滤器.PHP学习
前端控制器PHP学习
所有WEB哀求都将被前端控制器捕获,前端控制是给定环境下整个应用的唯一入口点.当前端控制接到一个哀求,他使用路由系统匹配用户输入的URL的动作名和模块名.例如:PHP学习
http://localhost/index.php/mymodule/myActionPHP学习
URL调用了index.php脚本(也就是前端控制器),他被理解为:动作-myAction,模块-mymodulePHP学习
前端控制器的工作细节PHP学习
前端控制器分发哀求,他仅执行那些通用的和共同的代码,包括:PHP学习
1. 定义核心常量
2. 定位symfony库
3. 载入和初始化核心框架类
4. 载入配置信息
5. 解码哀求URL,获取要执行的动作和哀求参数
6. 如果动作不存在则专项404错误
7. 激活过滤器(比如,如果需要身份认证)
8. 执行过滤器,第一次
9. 执行动作,递交视图
10. 执行过滤器,第二次
11. 输出响应.PHP学习
默认前端控制器PHP学习
默认前端控制器叫作index.php,在项目的WEB/目录,他是一个简单的PHP文件,如下:PHP学习
<?php
define('SF_ROOT_DIR',  realpath(dirname(__FILE__).'/..'));
define('SF_APP',     'myapp');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',    false);
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
sfContext::getInstance()->getController()->dispatch();
这个文件在前面已经介绍过了:首先定义几个变量,然后引入应用的配置config.php,最后调用sfController(这是symfony MVC架构中的核心控制器对象)的dispatch()办法.最后一步将被过滤器链捕获.PHP学习
调用另一个前端控制器来更换环境PHP学习
每个环境存在一个前端控制器,环境定义在SF_ENVIRONMENT常量中.PHP学习
创建新环境就和创建新的前端控制器一样简单,比如,你需要一个staging环境以使你的应用上线之前可以被客户测试.要创建staging环境,拷贝web/myapp_dev.php到web/myapp_staging.php,然后修改SF_ENVIRONMENT常量为staging.现在,你可以在所有的配置文件中增加staging段了设置新环境所需要的东西,看下面的示例:PHP学习
## app.yml staging: mail: webmaster: dummy@mysite.com contact: dummy@mysite.com all: mail: webmaster: webmaster@mysite.com contact: contact@mysite.com ##查看结果 http://localhost/myapp_staging.php/mymodule/index
批处理文件PHP学习
在命令行或者计划任务中拜访symfony类和特性的时候需要使用批处理文件.批处理文件的开头与前端控制器的开头一样――除了前端控制器的分发部分不要.PHP学习
<?php
define('SF_ROOT_DIR',  realpath(dirname(__FILE__).'/..'));
define('SF_APP',     'myapp');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',    false);
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
// 添加批处理代码
动作(Actions)PHP学习
动作是应用的心脏,因为他包含了所有应用的逻辑.他们使用模型并定义变量给视图.当在应用中使用一个哀求,URL中定义了一个动作和哀求的参数.PHP学习
动作类PHP学习
动作是moduleNameActions类(继承自sfActions类)中名为executeActionName的办法,以模块组织在一起,模块动作类存储在actions目录的actions.class.php文件中.PHP学习
只有WEB目录下的文件能够被外部拜访,前端控制脚本、图片、样式表和JS文件是公开的,即使PHP中方法不区分大小写,但symfony中区分,所以不要忘了动作方法必须以小写execute开始,紧跟着是首字母大写的动作名.PHP学习
如果动作类变得很大,你应该做一些分解并把代码放在模型层,动作应该尽量的保证短小(几行最好),所有的业务逻辑都应该放在模型层中.PHP学习
可选的动作类语法PHP学习
可以一个动作一个文件,文件的名称为动作名加Action.class.php,类名为动作名加Action,只是记得类继承自sfAction而非sfActions.PHP学习
在动作中获取信息PHP学习
动作类提供了一种拜访控制器相关信息与核心symfony对象的方法,下面演示了如何使用:PHP学习
<?php
define('SF_ROOT_DIR',  realpath(dirname(__FILE__).'/..'));
define('SF_APP',     'myapp');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',    false);
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
class mymoduleActions extends sfActions
{
 public function executeIndex()
 {
  // Retrieving request parameters
  $password  = $this->getRequestParameter('password');
  // Retrieving controller information
  $moduleName = $this->getModuleName();
  $actionName = $this->getActionName();
  // Retrieving framework core objects
  $request   = $this->getRequest();
  $userSession = $this->getUser();
  $response  = $this->getResponse();
  $controller = $this->getController();
  $context   = $this->getContext();
  // Setting action variables to pass information to the template
  $this->setVar('foo', 'bar');
  $this->foo = 'bar';      // Shorter version
 }
}
上下文:PHP学习
在前端控制器中一个sfContext::getInstance()的调用.在动作中,getContext()方法是单例模式(即所有的调用都是第一个实例,这对于存储指向与给定哀求相关的symfony核心对象的索引的情况是非常有用的).PHP学习
sfController:控制器对象 (->getController())
sfRequest:哀求对象 (->getRequest())
sfResponse:响应对象 (->getResponse())
sfUser:用户Session对象 (->getUser())
sfDatabaseConnection:数据库链接 (->getDatabaseConnection())
sfLogger:日志对象 (->getLogger())
sfI18N:国际化对象(->getI18N())
可以在代码的任何位置放置sfContext::getInstance().PHP学习
动作终止PHP学习
当动作执行完成后会出现各种行为,动作办法的返回值决定视图如何被实施.sfView类的常量经常被指定与模板来显示动作的结果.如果一个默认视图被调用,动作应该以下面的代码结束:PHP学习
return sfView::SUCCESS;
Symfony将寻找actionNameSuccess.php的模板,这是默认的行为,所以如果你忽略了return语句,symfony也将查找actionNameSuccess.php模板,空动作也将触发同样的行为,如下:PHP学习
# 将调用indexSuccess.php模板
public function executeIndex()
{
 return sfView::SUCCESS;
}
# 将调用listSuccess.php模板
public function executeList()
{
}
如果要调用错误视图,动作将以下面语句结束:PHP学习
# symfony将查找actionNameError.php模板 return sfView::ERROR;
调用自定义视图PHP学习
# symfony将查找actionNameMyResult.php模板 return 'MyResult';
如果动作不想调用模板(比如批处理和任务计划cron),可以使用下面的语句PHP学习
return sfView::NONE;
上面情况下,视图层将被忽略,HTML代码可以直接在动作中输出,symfony提供了一个特殊的办法renderText()来实现.这种情况比较适用于AJAX交互.PHP学习
public function executeIndex()
{
 echo "<html><body>Hello, World!</body></html>";
 return sfView::NONE;
}
// 等价办法
public function executeIndex()
{
 return $this->renderText("<html><body>Hello, World!</body></html>");
}
有些时候你需要发送空的响应但包含定义的头信息(特别是X-JSON头),定义头通过sfResponse对象,并且放回sfView::HEADER_ONLY常量:PHP学习
public function executeRefresh()
{
 $output = '<"title","My basic letter"],["name","Mr Brown">';
 $this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');
 return sfView::HEADER_ONLY;
}
如果动作必须呈交特定模板,使用setTemplate()办法来忽略return语句:PHP学习
$this->setTemplate('myCustomTemplate');
跳向另一个动作PHP学习
有些情况下,动作以哀求一个新的动作作为结束,例如,一个动作处理表单的POST提交在更新数据库后通常会转向到另一个动作.另一个例子是动作别名:index动作经常是来完成显示,所以实际上是跳向了list动作.PHP学习
有两种方式来实现另一个动作的执行:PHP学习
① 向前(Forwards)方式PHP学习
$this->forward('otherModule','otherAction');
② 重定向(Redirection)方式PHP学习
$this->redirect('otherModule/otherAction');
$this->redirect('http://www.google.cn');
Forward和redirect后面的语句将不会被执行,你可以理解为他们等价于return语句.他们抛出sfStopException异常来停止动作的执行PHP学习
两者的区别:forward是内部的处理,对用户是透明的,即用户不会感觉到动作发生了变化,URL也不会更改.相反,redirection是动作的真正跳转,URL的改变是最直接的反映.PHP学习
如果动作是被POST提交表单调用的,你最好使用redirect.这样,如果用户刷新了结果页面,POST表单不会被重复提交;另外,后退按钮也能很好的返回到表单显示页面而不是一个警告窗口询问用户是否重新提交POST哀求.PHP学习
Forward404()办法是一种常用的特殊forward,他跳到“页面无法找到”动作.PHP学习
经验说明,很多时候一个动作会在验证一些东西后redirect或者forward另一个动作.这就是为什么sfActions类有很多的办法命名为forwardIf(), forwardUnless(), forward404If(), forward404Unless(), redirectIf(), 和 redirectUnless(),这些办法简单地使用一个测试结果参数true(那些xxxIf()办法)或false(那些xxxUnless()办法):PHP学习
public function executeShow()
{
 $article = ArticlePeer::retrieveByPK($this->getRequestParameter('id'));
 $this->forward404If(!$article);
}
public function executeShow()
{
 $article = ArticlePeer::retrieveByPK($this->getRequestParameter('id'));
 $this->forward404Unless($article);
}
这些办法不仅仅是减少你的代码行数,他们还使得你的程序更加易读.PHP学习
当动作调用forward404()或者其他类似方法,symfony抛出管理404响应的sfError404Exception异常,也就是说如果你想显示404信息,你无需拜访控制器,你只是抛出这个异常即可.PHP学习
模块中多个动作重复代码的处理方式PHP学习
preExecute()与postExecute()办法是一个模块中多个动作共同的东西.可以在调用executeAction()之前和之后执行.PHP学习
class mymoduleActions extends sfActions
{
 public function preExecute()
 {
  // 这里的代码在每一个动作调用之前执行
  ...
 }
 public function executeIndex()
 {
  ...
 }
 public function executeList()
 {
  ...
  $this->myCustomMethod(); // 调用自定义的方法
 }
 public function postExecute()
 {
  // 这里的代码会在每个动作结束后执行
  ...
 }
 protected function myCustomMethod()
 {
  // 添加自己的方法,虽然他们没有以execute开头
  // 在这里,最好将方法定义为protected(保护的)或者private(私有的)
  ...
 }
}
访问哀求PHP学习
getRequestParameter(“myparam”)方法常用来获取myparam参数的值,实际上这个方法是一系列哀求调用参数仓库的代理:getRequest()->getParameter(“myparam”).动作类使用sfWebRequest访问哀求对象,通过getRequest()访问他们的方法.PHP学习
sfWebRequest对象的办法PHP学习
| 
       方法名 
       | 
      
       功能 
       | 
      
       输入示例 
       | 
    
| 
       Request Information 
       | 
      
       | 
      
       | 
    
| 
       getMethod() 
       | 
      
       
Request对象
 
       | 
      
       Returns sfRequest::GET or sfRequest::POST constants 
       | 
    
| 
       getMethodName() 
       | 
      
       
Request对象名
 
       | 
      
       'POST' 
       | 
    
| 
       getHttpHeader('Server') 
       | 
      
       
给定HTTP头的值
 
       | 
      
       'Apache/2.0.59 (Unix) DAV/2 PHP/5.1.6' 
       | 
    
| 
       getCookie('foo') 
       | 
      
       
指定名称Cookie的值
 
       | 
      
       'bar' 
       | 
    
| 
       isXmlHttpRequest()* 
       | 
      
       
是否是AJAX哀求?
 
       | 
      
       true 
       | 
    
| 
       isSecure() 
       | 
      
       
是否是SSL哀求
 
       | 
      
       true 
       | 
    
| 
       Request Parameters 
       | 
      
       | 
      
       | 
    
| 
       hasParameter('foo') 
       | 
      
       参数是否在哀求中有 
       | 
      
       true 
       | 
    
| 
       getParameter('foo') 
       | 
      
       指定参数的值 
       | 
      
       'bar' 
       | 
    
| 
       getParameterHolder()->getAll() 
       | 
      
       所有哀求参数的数组 
       | 
      
       | 
    
| 
       URI-Related Information 
       | 
      
       | 
      
       | 
    
| 
       getUri() 
       | 
      
       
完整URI
 
       | 
      
       'http://localhost/myapp_dev.php/mymodule/myaction' 
       | 
    
| 
       getPathInfo() 
       | 
      
       路径信息 
       | 
      
       '/mymodule/myaction' 
       | 
    
| 
       getReferer()** 
       | 
      
       来自那里? 
       | 
      
       'http://localhost/myapp_dev.php/' 
       | 
    
| 
       getHost() 
       | 
      
       主机名 
       | 
      
       'localhost' 
       | 
    
| 
       getScriptName() 
       | 
      
       前端控制器路径与名称 
       | 
      
       'myapp_dev.php' 
       | 
    
| 
       Client Browser Information 
       | 
      
       | 
      
       | 
    
| 
       getLanguages() 
       | 
      
       可接受语言的列表 
       | 
      
       Array( [0] => fr [1] => fr_FR [2] => en_US [3] => en ) 
       | 
    
| 
       getCharsets() 
       | 
      
       可接受字符集的列表 
       | 
      
       Array( [0] => ISO-8859-1 [1] => UTF-8 [2] => * ) 
       | 
    
| 
       getAcceptableContentTypes() 
       | 
      
       可接受内容类型数组 
       | 
      
       | 
    
sfActions类提供了一些代理来快速地访问哀求方法PHP学习
class mymoduleActions extends sfActions
{
 public function executeIndex()
 {
  $hasFoo = $this->getRequest()->hasParameter('foo');
  $hasFoo = $this->hasRequestParameter('foo'); // Shorter version
  $foo  = $this->getRequest()->getParameter('foo');
  $foo  = $this->getRequestParameter('foo'); // Shorter version
 }
}
对于文件上传的哀求,sfWebRequest对象提供了访问和移动这些文件的手段:PHP学习
class mymoduleActions extends sfActions
{
 public function executeUpload()
 {
  if ($this->getRequest()->hasFiles())
  {
   foreach ($this->getRequest()->getFileNames() as $fileName)
   {
    $fileSize = $this->getRequest()->getFileSize($fileName);
    $fileType = $this->getRequest()->getFileType($fileName);
    $fileError = $this->getRequest()->hasFileError($fileName);
    $uploadDir = sfConfig::get('sf_upload_dir');
    $this->getRequest()->moveFile('file', $uploadDir.'/'.$fileName);
   }
  }
 }
}
用户SessionPHP学习
Symfony自动管理用户Session并且能在哀求之间为用户保留持久数据.他使用PHP内置的Session处理机制并提升了此机制,这使得symfony的用户Session更好配置更容易使用.PHP学习
拜访用户SessionPHP学习
当前用户的Session对象在动作中使用getUser()方法拜访,他是sfUser类的一个实例.sfUser类包含了允许存储任何用户属性的参数仓库.用户属性能够存放任何类型的数据(字符串、数组、关联数组等).PHP学习
sfUser对象能够跨哀求地保存用户属性PHP学习
class mymoduleActions extends sfActions
{
 public function executeFirstPage()
 {
  $nickname = $this->getRequestParameter('nickname');
  // Store data in the user session
  $this->getUser()->setAttribute('nickname', $nickname);
 }
 public function executeSecondPage()
 {
  // Retrieve data from the user session with a default value
  $nickname = $this->getUser()->getAttribute('nickname', 'Anonymous Coward');
 }
}
可以把对象存放在用户Session中,但这往往让人气馁,因为Session在哀求之间被序列化了并且存储在文件中,当Session序列化时,存储对象的类必须已经被加载,而这很难被保证.另外,如果你存储了Propel对象,他们可能是“延迟”的对象.PHP学习
与symfony中的getter方法一样,getAttribute()方法接受第二个参数作为默认值(如果属性没有被定义时)使用.判断属性是否被定义使用hasAttribute()方法.属性存储在参数仓库可使用getAttributeHolder()方法拜访,可以使用基本参数仓库方法很简单的清除用户属性:PHP学习
class mymoduleActions extends sfActions
{
 public function executeRemoveNickname()
 {
  $this->getUser()->getAttributeHolder()->remove('nickname');
 }
 public function executeCleanup()
 {
  $this->getUser()->getAttributeHolder()->clear();
 }
}
用户Session属性在模板中默认通过$sf_user变量拜访,他存储了当前的sfUser对象PHP学习
<p>
 Hello, <?php echo $sf_user->getAttribute('nickname') ?>
</p>
如果只想在当前哀求中存储信息,你更应该使用sfRequest类,他也有getAttribute()和setAttribute()方法,只有在哀求之间持久存储信息时才适合sfUser对象.PHP学习
Flash属性PHP学习
Flash属性是一种短命属性,他会在最近的一次哀求后消失,这样可以保持你的Session清洁PHP学习
$this->setFlash('attrib', $value);
在另一个动作中获取Flash属性:PHP学习
$value = $this->getFlash('attrib');
一旦传入了另一个动作,Flash属性就消失了,即使你的Session还不过期.在模板中拜访flash属性使用$sf_flash对象.PHP学习
<?php if ($sf_flash->has('attrib')): ?>
 <?php echo $sf_flash->get('attrib') ?>
<?php endif; ?>
或者PHP学习
<?php echo $sf_flash->get('attrib') ?>
Session管理PHP学习
Symfony的Session处理特性对开发者完全掩盖了客户端与服务端的SessionID存储,当然,如果你非要去改Session管理机制的默认行为也不是不可能,高级用户经常这么干.PHP学习
客户端,Session被Cookies处理(handle).Symfony的Session Cookie叫做symfony,可以在factories.yml中修改.PHP学习
all: storage: class: sfSessionStorage param: session_name: 自定义Cookie名字
Symfony的Session基于PHP的Session设置,也就是说如果希望客户端使用URL参数方式取代Cookies,你必须修改php.ini文件的use_trans_sid参数,不建议这么做.PHP学习
在服务器端,symfony默认使用文件存储用户Session,可以通过修改factories.yml文件承担class参数来使用数据库存储:apps/myapp/config/factories.ymlPHP学习
all: storage: class: sfMySQLSessionStorage param: db_table: SESSION_TABLE_NAME # 存储Session的表 database: DATABASE_CONNECTION # 数据库的名称 Class名称可以是:fMySQLSessionStorage, sfPostgreSQLSessionStorage和sfPDOSessionStorage;后面是首选方式. Session超时的修改和调整:apps/myapp/config/settings.yml default: .settings: timeout: 1800 #Session超时 单位秒
动作的平安PHP学习
动作的执行可以被限定在具有一定权限的用户.Symfony为此提供的工作允许创建平安的应用,用户只有在通过认证之后才能防伪应用的某些特性或部分.设置平安的应用需要两步:定义动作需要的平安和使用具有权限的用户登录.PHP学习
拜访限制PHP学习
在每个动作执行前都会被一个特定的过滤器来检查当前用户是否具有拜访的权限,symfony中权限有两个部分组成:PHP学习
① 平安动作只有被授权用户可以访问
② 凭证允许分组管理权限PHP学习
通过创建或者修改config目录下的security.yml文件即可简单的完成平安访问限制.在文件中可以设置某个动作或者所有动作是否需要授权.PHP学习
Apps/myapp/modules/mymodule/config/security.ymlPHP学习
read: is_secure: off # 所有用户都可以哀求Read动作 update: is_secure: on # update动作只能有认证的用户访问 delete: is_secure: on # 同update credentials: admin # 具有admin凭证 all: is_secure: off # 无需授权
用户访问一个需要授权的动作将依据用户的权限:PHP学习
① 用户已登录并且凭证符合则动作能执行
② 如果用户没有登录则转向默认登录动作
③ 如果用户已登录但凭证不符合则会转向默认的平安动作PHP学习
转向将根据apps/myapp/config/settings.yml文件来决定PHP学习
all: .actions: login_module: default login_action: login secure_module: default secure_action: secure
授权PHP学习
为某用户授权:PHP学习
class myAccountActions extends sfActions
{
 public function executeLogin()
 {
  if ($this->getRequestParameter('login') == 'foobar') //判断根据具体需求而定
  {
   $this->getUser()->setAuthenticated(true);  //设置用户为已认证
  }
 }
 public function executeLogout()
 {
  $this->getUser()->setAuthenticated(false); //设置用户为未认证
 }
}
在动作中处理凭证:PHP学习
class myAccountActions extends sfActions
{
 public function executeDoThingsWithCredentials()
 {
  $user = $this->getUser();
  // 添加凭证
  $user->addCredential('foo');
  $user->addCredentials('foo', 'admin');  //添加多个凭证
  // 判断是否具有凭证
  echo $user->hasCredential('foo');           =>  true
  // 判断是否具有多个凭证
  echo $user->hasCredential(array('foo', 'admin'));    =>  true
  // Check if the user has one of the credentials
  echo $user->hasCredential(array('foo', 'admin'), false); =>  true
  // 删除凭证
  $user->removeCredential('foo');
  echo $user->hasCredential('foo');           =>  false
  // 删除所有凭证 (被用在注销处理过程中)
  $user->clearCredentials();
  echo $user->hasCredential('admin');           =>  false
 }
}
如果用户具有'admin'凭证,他就可以拜访security.yml文件中设定只有admin可以拜访的动作.凭证也经常用来在模板中显示授权信息PHP学习
<ul>
 <li><?php echo link_to('section1', 'content/section1') ?></li>
 <li><?php echo link_to('section2', 'content/section2') ?></li>
 <?php if ($sf_user->hasCredential('section3')): ?>
 <li><?php echo link_to('section3', 'content/section3') ?></li>
 <?php endif; ?>
</ul>
sfGuardPlugin插件扩展了session类,使得登录与注销的处理变得简单.PHP学习
复杂的凭证PHP学习
在security.yml文件中,可以使用AND或者OR来组合各种凭证,这样就可以建立复杂的业务流和用户权限管理系统.例如,CMS系统后台办公自由具有admin凭证用户拜访,文章的编辑必须有editor凭证,发布只能有有publisher凭证的用户,代码如下:PHP学习
editArticle: credentials: [ admin, editor ] # admin 和 editor publishArticle: credentials: [ admin, publisher ] # admin 和 publisher userManagement: credentials: [[ admin, superuser ]] # admin 或者 superuser
每次添加新的[],凭证之间的关系在AND和OR之间切换,这样可以创建及其复杂的凭证组合关系:PHP学习
credentials: [[root, [supplier, [owner, quasiowner]], accounts]]
       # root 或者 (supplier 和 (owner 或者 quasiowner)) 或者 accounts
注:【和】所有凭证都满足,【或】满足其中的一个凭证.PHP学习
验证和错误处理办法PHP学习
验证输入是重复且单调的事情,symfony提供了内置的哀求验证系统,使用动作类的方法.PHP学习
看个例子,当一个用户哀求myAction,symfony首先去查找validateMyAction()方法,如果找到了就执行,根据返回结果来决定如何往下走:如果返回真则executeMyAction()被执行,否则handleErrorMyAction()被执行,并且,如果找不到handleErrorMyAction,symfony则去查找普通handleError方法,如果还不存在则简单返回sfView::ERROR并递交myActionError.php模板,看下图:PHP学习
PHP学习
说明:PHP学习
① validateActionName是验证方法,是ActionName被哀求的第一个查找方法,如果不存在则直接执行动作方法.PHP学习
② handleErrorActionName办法,如果验证失败则查找此办法,如果不存在则Error模板被显示PHP学习
③ executeActionName是动作办法,对于动作他必须存在.PHP学习
看段代码:PHP学习
class mymoduleActions extends sfActions
{
 public function validateMyAction()
 {
  return ($this->getRequestParameter('id') > 0);
 }
 public function handleErrorMyAction()
 {
  $this->message = "Invalid parameters";
  return sfView::SUCCESS;
 }
 public function executeMyAction()
 {
  $this->message = "The parameters are correct";
 }
}
可以在验证方法中加入任何代码,但最终只要返回true或者false即可.因为是sfActions类的方法,所以可以拜访sfRequest和sfUser对象,这样将对于输入与上下文验证非常有利.PHP学习
过滤器PHP学习
安全处理可以被认为是哀求到动作执行之前必须经过的一个过滤器.实际上可以在动作执行前(后)设置任意多个的过滤器.PHP学习
过滤器链PHP学习
Symfony实际上将哀求处理看作是过滤器链.框架收到哀求后第一个过滤器(通常是sfRenderingFilter)被执行,在某些时候他调用下一个过滤器,依次下去.当最后一个过滤器(通常是sfExecutionFilter)执行后,前一个过滤器结束,依次返回去知道rending过滤器.PHP学习
PHP学习
所有的过滤器均继承自sfFilter类并且都包含了execute()办法,此办法之前的代码在动作(action)之前执行,此办法之后的代码在动作之后执行,看一段代码(下一节中要用到,取名myFilter代码):PHP学习
class myFilter extends sfFilter
{
 public function execute ($filterChain)
 {
  // 在动作之前执行的代码
  ...
  // 执行下一个过滤器
  $filterChain->execute();
  // 在动作之后执行的代码
  ...
 }
}
过滤器链在/myapp/config/filters.yml文件中定义:PHP学习
rendering: ~ web_debug: ~ security: ~ # 在这里插入你自己的过滤器 cache: ~ common: ~ flash: ~ execution: ~
这些声明都没有参数(~在symfony中的意思是null,将采用默认的值),他们都继承自symfony核心定义的参数,symfony为每一个过滤器(除了自定义过滤器)定义了类和参数,他们在$sf_symfony_data_dir/config/filter.yml文件.PHP学习
自定义过滤器链的办法:PHP学习
① 设置过滤器的enabled参数为off将禁用过滤器,例如:PHP学习
Web_debug: enabled: off
你还可以通过settings.yml文件达到此目的,修改web_deug、use_security、cache和use_flash的设置即可,应为每一个默认过滤器都有一个condition参数来自上面的配置.PHP学习
② 不要通过删除filters.yml文件中的过滤器来禁用该过滤器,symfony将抛出异常PHP学习
③ 可以自定义过滤器,但无论如何rendering必须是第一个,而execution必须是最后一个PHP学习
④ 为默认过滤器重写默认类和参数(特别是修改security系统和用户的平安验证过滤器)PHP学习
创建自定义过滤器PHP学习
通过创建myFilter的类可以非常简单的常见自定义的过滤器,把类文件放在项目的lib文件夹可以充分利用symfony提供的自动加载特性.PHP学习
由于动作之间可以互相跳转,因此过滤器链会在每一个哀求中循序执行.但更多的时候可能需要是第一次哀求的时候执行自定义的过滤器,这时候使用sfFilter类的isFirstCall()方法.看下面代码:apps/myapp/lib/rememberFilter.class.php(例子)PHP学习
class rememberFilter extends sfFilter
{
 public function execute($filterChain)
 {
  // 通过调用isFirstCall方法保证只执行一次
  if ($this->isFirstCall())
  {
   // 过滤器不直接访问哀求和用户对象,你需要使用context对象获取
   // You will need to use the context object to get them
   $request = $this->getContext()->getRequest();
   $user  = $this->getContext()->getUser();
   if ($request->getCookie('MyWebSite'))
   {
    // 登入
    $user->setAuthenticated(true);
   }
  }
  // 执行下一个过滤器
  $filterChain->execute();
 }
}
有时候需要在一个过滤器执行之后跳往另一个动作而不是下一个过滤器.sfFilter不包含forward方法,但sfController包含,使用下面的语句:PHP学习
return $this->getContext()->getController()->forward('mymodule', 'myAction');
sfFilter类有一个initialize办法,在对象创建的时候执行,可以在自定义的过滤器中覆盖此办法以达到更加灵活地设置参数的目的.PHP学习
过滤器激活及参数PHP学习
过滤器创建后还必须进行激活,在apps/myapp/config/filters.yml文件中:PHP学习
rendering: ~ web_debug: ~ security: ~ remember: # Filters need a unique name class: rememberFilter param: cookie_name: MyWebSite condition: %APP_ENABLE_REMEMBER_ME% cache: ~ common: ~ flash: ~ execution: ~
自定义过滤器中的参数可以在过滤器代码中使用getParameter办法获取:PHP学习
apps/myapp/lib/rememberFilter.class.php
PHP学习
class rememberFilter extends sfFilter
{
 public function execute ($filterChain)
 {
   ...
   if ($request->getCookie($this->getParameter('cookie_name')))
   ...
 }
}
Condition参数被过滤器链测试来决定是否必须被执行.因此自定义过滤器声明能够依赖一个应用配置.要是过滤器执行,记得在应用的app.yml中加入:PHP学习
all: enable_remember_me: on
过滤器示例PHP学习
如果想在项目中包含特定的代码,你可以通过过滤器实现(layout方式需要在每一个应用中都要设置),看下面的代码:PHP学习
class sfGoogleAnalyticsFilter extends sfFilter
{
 public function execute($filterChain)
 {
  // 在动作之前什么也不做
  $filterChain->execute();
  // 使用下面的代码修饰响应
  $googleCode = '
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
 _uacct="UA-'.$this->getParameter('google_id').'";urchinTracker();
</script>';
  $response = $this->getContext()->getResponse();
  $response->setContent(str_ireplace('</body>', $googleCode.'</body>',$response->getContent()));
  }
}
这不是一种好的方式,因为在非HTML响应中不适用,只是一个例子罢了.PHP学习
下个例子是转换http哀求到https哀求PHP学习
class sfSecureFilter extends sfFilter
{
 public function execute($filterChain)
 {
  $context = $this->getContext();
  $request = $context->getRequest();
  if (!$request->isSecure())
  {
   $secure_url = str_replace('http', 'https', $request->getUri());
   return $context->getController()->redirect($secure_url);
   // We don't continue the filter chain
  }
  else
  {
   // The request is already secure, so we can continue
   $filterChain->execute();
  }
 }
}
过滤器广泛地应用于插件,允许全面地扩展应用的特性.PHP学习
模块配置PHP学习
一些模块行为依赖配置,要修改他们必须在模块的config目录下建立module.yml并为每一个环境(或者all)定义设置.PHP学习
看个例子:apps/myapp/modules/mymodule/config/module.ymlPHP学习
all: #对所有环境 enabled: true is_internal: false view_name: sfPHP
Enable参数允许你在模块中禁用所有动作,这样所有动作都将专项到module_disabled_module/module_disabled_action动作(定义在settings.yml)PHP学习
Is_internal参数定义动作只能内部调用,比如发送邮件只能有另一个动作调用而不是外部的直接调用.PHP学习
View_name参数定义了view类,类必须继承自sfView.覆盖他后你将可以使用具有其他模板引擎其他的view系统,比如smarty.PHP学习
希望本文所述对大家基于Symfony框架的PHP程序设计有所赞助.PHP学习
《PHP实战:Symfony控制层深入详解》是否对您有启发,欢迎查看更多与《PHP实战:Symfony控制层深入详解》相关教程,学精学透。维易PHP学院为您提供精彩教程。
转载请注明本页网址:
http://www.vephp.com/jiaocheng/7323.html