2012-02-16 92 views
4

我想在我的應用程序中使用Zend_acl。我遵循了「Zend Framework in Action」一書。 我加入這個助手:如何調試「最大執行時間」致命錯誤?

<?php 
/** 
* Zend Framework 
* 
* LICENSE "removed for clarity" 
* 

/** Zend_Controller_Action_Helper_Abstract */ 
require_once 'Zend/Controller/Action/Helper/Abstract.php'; 



class Bravo_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract 
{ 

    protected $_action; 

    protected $_auth; 

    protected $_acl; 

    protected $_controllerName; 

    public function __construct(Zend_View_Interface $view = null, array $options = array()) 
    { 
     $this->_auth = Zend_Auth::getInstance(); 
     $this->_acl = $options['acl']; 
     //var_dump($this->_acl);die(); 
    } 

    public function init() 
    { 
     $this->_action = $this->getActionController(); 

     // add resource for this controller 
     $controller = $this->_action->getRequest()->getControllerName(); 
     if(!$this->_acl->has($controller)) { 
      $this->_acl->add(new Zend_Acl_Resource($controller)); 
     } 

    } 

    public function preDispatch() 
    { 
     $role = 'guest'; 
     if ($this->_auth->hasIdentity()) { 
      $user = $this->_auth->getIdentity(); 
      if(is_object($user)) { 
       $role = $this->_auth->getIdentity()->getUral()->getUralAccessNbr(); 
      } 
     } 

     $request = $this->_action->getRequest(); 
     $controller = $request->getControllerName(); 
     $action = $request->getActionName(); 
     $module = $request->getModuleName(); 
     $this->_controllerName = $controller; 

     $resource = $controller; 
     $privilege = $action; 

     if (!$this->_acl->has($resource)) { 
      $resource = null; 
     } 

     //** EDIT: During my test, the user isn't allowed. I'm now suspecting the 4 requests setting to be wrong. 
     if (!$this->_acl->isAllowed($role, $resource, $privilege)) { 
      $request->setModuleName('default'); 
      $request->setControllerName('login'); 
      $request->setActionName('login'); 
      $request->setDispatched(false);    
     } 

    } 


    public function allow($roles = null, $actions = null) 
    { 
     $resource = $this->_controllerName; 
     $this->_acl->allow($roles, $resource, $actions); 
     return $this; 
    } 

    public function deny($roles = null, $actions = null) 
    { 
     $resource = $this->_controllerName; 
     $this->_acl->deny($roles, $resource, $actions); 
     return $this; 
    } 

} 

和引導:

<?php 

class Agenda_Bootstrap extends Zend_Application_Module_Bootstrap 
{ 

    protected function _initAcl() 
    { 

     // acl action helper 
     $acl = new Bravo_Acl_Acl(); 
     $aclHelper = new Bravo_Controller_Action_Helper_Acl(null, array('acl' => $acl)); 
     Zend_Controller_Action_HelperBroker::addHelper($aclHelper); 
    } 
} 

助手是不是在控制器中使用。我想我的應用程序,看看是否所有是正確的,我得到這個錯誤:

Fatal error: Maximum execution time of 30 seconds exceeded in /usr/share/php/ZendFramework-1.11.11/Zend/Filter/PregReplace.php on line 171

有了這個調用堆棧:

Call Stack 
# Time Memory Function            Location 
1 0.0001 314556 {main}()            ../index.php:0 
2 0.3275 2039356 Zend_Application->run()        ../index.php:29 
3 0.3275 2039356 Zend_Application_Bootstrap_Bootstrap->run()    ../Application.php:366 
4 0.3276 2039412 Zend_Controller_Front->dispatch()      ../Bootstrap.php:97 
5 31.7462 4813252 Zend_Controller_Dispatcher_Standard->dispatch()  ../Front.php:954 
6 31.7470 4813944 Zend_Controller_Action->__construct()      ../Standard.php:268 
7 31.7470 4814144 Zend_Controller_Action_HelperBroker->__construct()  ../Action.php:132 
8 31.7472 4814924 Zend_Controller_Action_Helper_ViewRenderer->init()  ../HelperBroker.php:253 
9 31.7472 4814924 Zend_Controller_Action_Helper_ViewRenderer->initView()  ../ViewRenderer.php:516 
10 31.7473 4815260 Zend_Controller_Action_Helper_ViewRenderer->_getBasePath() ../ViewRenderer.php:469 
11 31.7478 4815628 Zend_Filter_Inflector->filter()      ../ViewRenderer.php:393 
12 31.7489 4816768 Zend_Filter_Word_CamelCaseToSeparator->filter()  ../Inflector.php:473 
13 31.7489 4816768 Zend_Filter_PregReplace->filter()    ../CamelCaseToSeparator.php:46 

我試圖增加max_execution_time,但它始終是相同的:第一4堆仍然不變,第五反映max_execution_time(30秒=> 31.7462,40秒=> 42.6546等等)

所以我懷疑Zend_Controller_Front->dispatch()是我的問題的根源,但爲什麼它始終以最大時間?我有點困惑。有人對我應該挖掘的地方有一些想法嗎?

編輯:我進一步在我的調試。當用戶不被允許時,我現在懷疑我的幫助器中的4個請求設置是錯誤的。我也編輯了幫手代碼並添加了評論。

編輯2:帕特里克,你是如此的正確!我重新檢查過,並且陷入了一個無限循環:沒有登錄頁面登錄頁面去登錄頁面:今天浪費了多少時間......無論如何它結束了,非常感謝每一個人。

+0

對於這樣的情況下,可以先[啓用分析](http://xdebug.org/docs/profile):

CSysTracer確實使用PHP's tick function特技。稍後,您可以通過[KCachegrind](http://kcachegrind.sourceforge.net/)或[wincachegrind](http://sourceforge.net/projects/wincachegrind/)檢查輸出文件。 – 2012-02-16 20:40:08

+0

謝謝,我會的。 – FredRoger 2012-02-16 21:53:23

回答

5
if (!$this->_acl->isAllowed($role, $resource, $privilege)) { 
    $request->setModuleName('default'); 
    $request->setControllerName('login'); 
    $request->setActionName('login'); 
    $request->setDispatched(false);    
} 

您確定您總是有權限訪問登錄控制器而不管角色嗎?

無論如何,這聽起來像你最終在一個無限循環,ZF的調度循環從未完成。

+0

你真是太棒了!我重新檢查了一下,我陷入了一個無限循環:沒有登錄頁面登錄頁面去登錄頁面:今天多麼浪費時間......無論如何它結束了! :-D謝謝 – FredRoger 2012-02-16 21:52:38

1

如果調試器不可用,則可以使用純PHP代碼。這是一個選項,使用稱爲CSysTracer的小型助手類。

基於該接口的:

abstract class CSTReportDelegate { 

    abstract public function emitVariableChange($variableName, $oldValue, $newValue); 
    abstract public function emitVariableSetNew($variableName, $newValue); 

} 

創造了這個具體的實例

class CSTSimpleReportDelegate extends CSTReportDelegate { 

    public function emitVariableChange($variableName, $oldValue, $newValue) { 
     echo '<br />[global/change] '. $variableName . ' : ' . print_r($oldValue, true) . ' &rarr; ' . print_r($newValue, true); 
    } 

    public function emitVariableSetNew($variableName, $newValue) { 
     echo '<br />[global/init] '. $variableName . ' &rarr; ' . print_r($newValue, TRUE); 
    } 

} 

...把​​它傳遞給CSysTracer:

CSysTracer::setReportDelegate(new CSTSimpleReportDelegate()); 

...和使用跟蹤啓用聲明這個:

CSysTracer::start(5); 

雖然CSTSimpleReportDelegate打印輸出,但它可以將內容寫入日誌文件,並且例如對某些語句做有選擇的寫操作。

請注意,此版本的CSysTracer跟蹤全局變量的變化。重寫它來記錄每條語句非常簡單。通過Xdebug的

class CSysTracer { 

    static protected 
     $reportDelegate; 

    static private 
     $globalState = array(); 

    static private 
     $traceableGlobals = array(); 

    static private 
     $globalTraceEnabled = FALSE; 

    const 
     DEFAULT_TICK_AMOUNT = 1; 

    static public 
    function setReportDelegate(CSTReportDelegate $aDelegate) { 
     self::$reportDelegate = $aDelegate; 
    } 


    static public 
    function start($tickAmount = self::DEFAULT_TICK_AMOUNT) { 

     register_tick_function (array('CSysTracer', 'handleTick')); 

    } 


    static public 
    function stop() { 

     unregister_tick_function(array('CSysTracer', 'handleTick')); 

    } 

    static public 
    function evalAndTrace($someStatement) { 

     declare(ticks = 1); { 
      self::start(); 
      eval($someStatement); 
      self::stop(); 
     } 
    } 

    static public 
    function addTraceableGlobal($varName) { 

     if (is_array($varName)) { 
      foreach($varName as $singleName) { 
       self::addTraceableGlobal($singleName); 
      } 
      return; 
     } 

     self::$traceableGlobals[ $varName ] = $varName; 

    } 

    static public 
    function removeTraceableGlobal($varName) { 
     unset(self::$traceableGlobals[ $varName ]); 
    } 

    /** 
    * Main function called at each tick. Calls those functions, which 
    * really perform the checks. 
    * 
    */ 
    static public 
    function handleTick() { 

     if (TRUE === self::$globalTraceEnabled) { 
      self::traceGlobalVariable(); 
     } 

    } 

    static public 
    function enableGlobalsTrace() { 
     self::$globalTraceEnabled = TRUE; 
    } 


    static public 
    function disableGlobalsTrace() { 
     self::$globalTraceEnabled = FALSE; 
    } 

    static public 
    function traceGlobalVariable() { 

     foreach(self::$traceableGlobals as $aVarname) { 

      if (! isset($GLOBALS[ $aVarname ])) { 
       continue; 
      } 

      if (! isset(self::$globalState[ $aVarname ])) { 

       self::$reportDelegate->emitVariableSetNew($aVarname, $GLOBALS[ $aVarname ]); 
       self::$globalState[ $aVarname ] = $GLOBALS[ $aVarname ]; 
       continue; 
      } 

      if (self::$globalState[ $aVarname ] !== $GLOBALS[ $aVarname ]) { 

      self::$reportDelegate->emitVariableChange($aVarname, self::$globalState[ $aVarname ], $GLOBALS[ $aVarname ]); 

      } 

      self::$globalState[ $aVarname ] = $GLOBALS[ $aVarname ]; 

     } 

    } 

} 
相關問題