代码之家  ›  专栏  ›  技术社区  ›  Noah Goodrich

如何在PHP中强制对对象的属性或方法进行方法调用?

  •  1
  • Noah Goodrich  · 技术社区  · 15 年前

    在我的视图中(使用Zend_视图使视图成为对象),我调用对象属性和方法来填充模板,如下所示:

    <?= $this->user->name ?> // Outputs John Doe
    <br/>
    <?= $this->user->getCompany()->name ?> // Outputs Acme
    <br/>
    <?= $this->method() ?> // Outputs foobar
    

    如果我让所有属性请求(如“user”)都通过uuu get(),是否有任何方法可以捕获后续调用,从而强制对最终输出的值进行方法调用?例如,我可以自动转义输出。

    正如我现在看到的,我要么在输入进入数据库时转义输入,要么像Smarty那样使用编译模板,要么切换到将每个变量分配给View对象,以便它可以直接控制在输出数据之前强制转义。

    6 回复  |  直到 15 年前
        1
  •  1
  •   Decent Dabbler    14 年前

    你可以找个装饰师。请参见此简化示例:

    class ViewObject_Decorator
    {
        protected $_decoratedObject;
    
        protected $_view;
    
        public function __construct( $object, Zend_View view )
        {
            $this->_decoratedObject = $object;
            $this->_view = $view;
        }
    
        public function __get( $property )
        {
            return $this->_view->escape( $this->_decoratedObject->$property );
        }
    
        /*
            maybe implement __call to proxy to decoratedObject methods, etc...
        */
    }
    

    那么你的提议呢 __get

    public function __get( $property )
    {
        // decorate the requested object, and send the view along with it.
        return new ViewObject_Decorator( $this->$property, $this );
    }
    
        2
  •  0
  •   DeveloperChris    15 年前

    我一开始说不。那是因为你不能让返回的值“通过”\uuu get(),但经过思考后意识到你可以绕过它。就我个人而言,我认为这将是低效的,并且还会导致其他问题,例如在不转义的情况下获取$name。

    为此,您需要在每个类中使用uu get($var),然后在转义变量后返回该变量。

    可能非常浪费,虽然我个人会使用

    <?= $this->user->escaped_name() ?>
    

    __get($var){ 
      if ($var == 'name')
         return escape($this->name);
    }
    

    这只是一个示例,假设$name是非公共成员。如果它是数组中的一个元素,则需要对数组进行适当的索引,例如:

    return escape($this->data['name']);
    

    注:我不知道zend_的观点,但我认为这不会有任何区别

        3
  •  0
  •   chelmertz user1604064    15 年前

    你试过使用 Zend_View_Abstract::addFilterPath() Zend_View_Abstract::addFilter()

    看见 Output Filters in Zend_View

        4
  •  0
  •   smack0007    15 年前

    您可以扩展视图对象,然后重写_get()方法,以根据需要转义所有输出。

    您可以使用:

    $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
    $viewRenderer->setView(new My_View());
    

    将视图对象更改为您创建的视图对象。

        5
  •  0
  •   Rob Allen    15 年前

    手动方式是直接在模板中使用escape()视图辅助对象,如下所示:

    <?= $this->escape($this->user->name) ?> // Outputs John Doe
    <br/>
    <?= $this->escape($this->user->getCompany()->name) ?> // Outputs Acme
    <br/>
    <?= $this->escape($this->method()) ?> // Outputs foobar
    

    Zend_View_Stream 用于自动将短标记转换为长标记。这是通过以下方式启用的:

    $view->setUseStreamWrapper(true);
    

    您需要对其进行扩展,以自动避免使用 <?= . 包装器中要使用的代码如下所示:

    $find = '/<?=[ ]*([^;>]*?|[^;?]*?)[; ]*?>/';
    $replace = "<?php echo $this->escape($1); ?>";
    $this->data = preg_replace($find, $replace, $this->data);
    

    显然,使用流包装器也会影响性能。

    详情如下:

        6
  •  0
  •   Kornel    15 年前

    使用 PHPTAL 作为你的 view .

    默认情况下,它会跳过所有内容(将模板编译为具有所有必要功能的PHP) htmlspecialchars() 自动添加呼叫)。

    ${this/user/getCompany/name} <!-- it's safe! -->