Магический метод PHP __invoke, пустые переменные экземпляра

Я столкнулся с проблемой при вызове __invoke() для объекта. Является ли метод __invoke() независимым от переменных экземпляра? Мне нужно вызвать __invoke() непосредственно в моих шаблонах из-за некоторой инъекции ZF2 для вызова $this->getView()->render(...) (иначе getView() возвращает значение null), и я хотел бы установить переменные экземпляра там. Любое обходное решение?

Смотрите мой код:

namespace Person\Person\View\Helper;


use Zend\View\Helper\AbstractHelper;

class PersonShowWidget extends AbstractHelper
{

    protected $model = null;

    public function __construct(array $options = null)
    {
        $this->parseOptions($options);
    }

    public function __invoke()
    {

        var_dump($this->model); //returns null
        return $this->getView()->render('person/show/show_widget', array(
                'title' => 'Cliente',
                'model' => $this->model,
            )
        );
    }

    public function setOptions(array $options = null)
    {
        $this->parseOptions($options);
    }

    protected function parseOptions(array $options = null)
    {
        if (!is_null($options) && is_array($options)) {
            if (isset($options['model'])) {
                $model = $options['model'];
                if (isset($model['id'])) {
                    $this->model['id'] = $model['id'];
                } else {
                    throw new \Exception;
                }
                if (isset($model['form'])) {
                    $this->model['form'] = $model['form'];
                } else {
                    throw new \Exception;
                }
            }
        }

        var_dump($this->model); //returns valid data

    }
}

Я вызвал конструктор с некоторыми параметрами или методом setOptions перед вызовом __invoke().

Спасибо,


person vicaba    schedule 03.09.2014    source источник


Ответы (1)


Вы должны инициализировать хелпер представления с фабрикой. Таким образом, вы можете убедиться, что конструктор вызывается до вызова метода __invoke. И нет... метод __invoke() не зависит от переменных экземпляра.

В модуле.php

public function getViewHelperConfig()
{
    return array(
        'factories' => array(
            'personShowWidget' => function ($helpers) {
                $array = array();
                $helper = new Person\Person\View\Helper\PersonShowWidget($array);
                return $helper;
            },
        )
    );
}

Или в файле module.config.php

'view_helpers' => array
(
    'factories' => array(
        'personShowWidget' => function ($helpers) {
            $array = array();
            $helper = new Person\Person\View\Helper\PersonShowWidget($array);
            return $helper;
        },
    )
)

С точки зрения производительности вам лучше создать класс Factory вместо вызываемого. Дополнительная информация: http://framework.zend.com/manual/2.0/en/modules/zend.module-manager.module-manager.html

Редактировать:

Похоже, вы неправильно используете ViewHelper. Вам не нужно создавать экземпляр самостоятельно. Просто используйте ViewHelper в представлении. Так почему бы просто не передать параметр $options as методу __invoke?

public function __invoke(array $options = null)
{
    $this->setOptions($options);

    return $this->getView()->render('person/show/show_widget', array(
            'title' => 'Cliente',
            'model' => $this->model,
        )
    );
}

В контроллере передайте массив параметров в представление:

return array(
    'options' => $options,
);

И вызовите ViewHelper в представлении:

<?php echo $this->personShowWidget($this->options); ?>

Помните: таким образом вам не нужна фабрика для инициализации ViewHelper. Просто добавьте его в вызываемые.

пример module.config.php:

'view_helpers' => array(
    'invokables' => array(
        'personShowWidget' => 'Person\Person\View\Helper\PersonShowWidget',
    ),
),
person bitWorking    schedule 03.09.2014
comment
Возможно, я делаю это концептуально неправильно, я пытаюсь создать новый PersonShowWidget в контроллере, настроить его с помощью метода setOptions, а затем отобразить (отобразить) его в представлении. Может быть, метод getView() возвращает null, потому что я не получаю его через ViewManager внутри представления? - person vicaba; 04.09.2014
comment
Я делаю это так, как вы сейчас упомянули, проблема заключалась в том, что если я создаю viewhelper в контроллере, setView() никогда не вызывался. Теперь я пытаюсь отобразить его в контроллере, потому что я хотел бы преобразовать его в модальное окно и отправить код только при нажатии кнопки. - person vicaba; 05.09.2014
comment
Решение: stackoverflow.com/questions/15559441/ - person vicaba; 05.09.2014