Как заставить вызов метода для свойства или метода объекта в PHP? - PullRequest
1 голос
/ 07 января 2010

В моем представлении (используя Zend_View, поэтому представление является объектом) я выполняю вызовы свойств и методов объекта для заполнения шаблона следующим образом:

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

Если я сделаю так, чтобы все запросы свойств (например, для «пользователя») проходили через __get (), есть ли какой-нибудь способ, которым я могу перехватить последующие вызовы, чтобы я мог принудительно вызвать вызов метода для окончательного выведенного значения? Например, чтобы я мог сделать автоматическое экранирование вывода.

Как я вижу это прямо сейчас, я должен либо избегать ввода, когда он поступает в базу данных, либо использовать скомпилированные шаблоны, как это делает Smarty, либо переключаться на присвоение каждой переменной объекту View, чтобы он имел прямой контроль для принудительного экранирования до вывода данных.

Ответы [ 6 ]

1 голос
/ 12 марта 2010

Вы можете использовать декоратор. Посмотрите этот упрощенный пример:

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 (предполагается, что это метод Zend_View?) Будет выглядеть примерно так:

public function __get( $property )
{
    // decorate the requested object, and send the view along with it.
    return new ViewObject_Decorator( $this->$property, $this );
}
0 голосов
/ 08 января 2010

Используйте PHPTAL в качестве представления .

По умолчанию все экранируется (компилирует шаблоны в PHP, в который автоматически добавляются все необходимые вызовы htmlspecialchars()).

${this/user/getCompany/name} <!-- it's safe! -->
0 голосов
/ 07 января 2010

Вы можете расширить объект представления и затем переопределить метод __get (), чтобы при необходимости экранировать весь вывод.

Вы можете использовать:

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

чтобы изменить вид объекта, который вы создаете.

0 голосов
/ 07 января 2010

Ручной способ - использовать помощник вида 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 Framework предоставляет Zend_View_Stream, который используется для автоматизации преобразования коротких тегов в длинные. Это включается с помощью:

$view->setUseStreamWrapper(true);

Вам потребуется расширить его, чтобы автоматически исключить любое использование <?=. Код для использования в оболочке выглядит примерно так:

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

Очевидно, что использование потоковой обертки также влияет на производительность.

Более подробная информация здесь:

0 голосов
/ 07 января 2010

Вы пробовали использовать Zend_View_Abstract::addFilterPath() и Zend_View_Abstract::addFilter()?

См. Выходные фильтры в Zend_View

0 голосов
/ 07 января 2010

Я начал с того, что сказал «Нет». Это потому, что вы не можете заставить возвращаемое значение пройти «до» __get (), но, подумав, поняли, что вы можете обойти его.Лично я думаю, что это будет неэффективно и также вызовет другие проблемы, такие как получение $ name без экранирования.

Для этого вам нужно использовать __get ($ var) в каждом классе, а затем возвращать переменную послеизбегая его.

вероятно очень расточительно, хотя я лично использовал бы

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

в классе для пользователя и класса, представляющего компанию

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

Это толькоодин пример и предполагает, что $ name не является публичным членом.если для его элемента в массиве потребуется соответствующая индексация в массиве, например:

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

Примечание: я ничего не знаю о zend_views, но я предполагаю, что это не будет иметь никакого значения

DC

...