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);
    }
}

ヘルパーはコントローラーでは使用されません。すべてが正しいかどうかを確認するためにアプリを試したところ、次のエラーが発生しました。

致命的なエラー: 171 行目の /usr/share/php/ZendFramework-1.11.11/Zend/Filter/PregReplace.php で最大実行時間が 30 秒を超えました

このコール スタックを使用すると、次のようになります。

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 つのスタックは変更されず、5 番目のスタックはmax_execution_time(30 秒 => 31.7462、40 秒 => 42.6546 など) を反映しています。

だから私Zend_Controller_Front->dispatch( )は問題の原因であると思われますが、なぜ常に最大の時間がかかるのですか? 私は少し混乱しています。誰かが私がどこを掘るべきかについて考えを持っていますか?

編集: デバッグをさらに進めます。ユーザーが許可されていない場合、ヘルパーで 4 つの要求の設定が間違っているのではないかと疑っています。ヘルパー コードも編集し、コメントを追加しました。

EDIT2: パトリック、その通り!!! 再確認したところ、無限ループに陥っていました: don't-have-access-to-login-page => go-to-login-page :-Dみんな。

4

2 に答える 2

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

ロールに関係なく、常にログイン コントローラーにアクセスする権限を持っていますか?

とにかく、ZF のディスパッチ ループが完了しない無限ループになってしまうようです。

于 2012-02-16T20:46:55.527 に答える
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 は、グローバル変数の変更を追跡することに注意してください。各ステートメントをログに記録するように書き換えるのは非常に簡単です。

CSysTracer は、PHP の tick 関数を使用してトリックを実行します。

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 ];

        }

    }

}
于 2012-02-16T20:47:35.347 に答える