Skip to content
This repository has been archived by the owner on Jan 31, 2020. It is now read-only.

Invokable view variable shouldn't be invoked #85

Open
antiphp opened this issue Aug 22, 2016 · 5 comments
Open

Invokable view variable shouldn't be invoked #85

antiphp opened this issue Aug 22, 2016 · 5 comments

Comments

@antiphp
Copy link

antiphp commented Aug 22, 2016

Hi,

when passing an invokable object to the view and trying to access it, the object is being invoked automatically which may not be intended.

// Controller action
public function testAction()
{
    $viewModel = new ViewModel();
    $viewModel->test = new class {
        public function __invoke(array $params) {}
        public function getName() {
            return 'test';
        }
    };
    return $viewModel;
}

// View
echo $this->test->getName();

Expected output:
test

Actual output:
Argument 1 passed to class@anonymous::__invoke() must be of the type array, none given

The reason is here (Zend/View/Variables.php):

public function offsetGet($key)
{
    if (!$this->offsetExists($key)) {
        if ($this->isStrict()) {
            trigger_error(sprintf(
                'View variable "%s" does not exist',
                $key
            ), E_USER_NOTICE);
        }
        return;
    }

    $return = parent::offsetGet($key);

    // If we have a closure/functor, invoke it, and return its return value
    if (is_object($return) && is_callable($return)) {
        $return = call_user_func($return);
    }

    return $return;
}

The process of passing and accessing variables should not take care of the kind of the variables passed.

I really don't get the point of invoking them automatically. If someone needs automatic invocation we have view helpers. My suggestion is to remove the automatic invocation or if you can't let go, add an interface check.

@weierophinney
Copy link
Member

Interestingly, that's a new feature, and it was done to allow defining helpers without requiring implementation of HelperInterface (see #60). As such, any such change at this point would be a BC break. We'll have to evaluate if this should be the behavior going forward, or something we want to revert and/or change with the next major version of zend-view.

@antiphp
Copy link
Author

antiphp commented Aug 22, 2016

But how am I supposed to pass invokable objects then?

In short to show that my situation is not special (at least IMHO): I want to pass a command-like object to the view (ReplaceTranslation) and I want to show a preview of that command output (via its invokable method) as well as its name. I have more commands.

Workarounds I was thinking about:

  • pass just the return values of all required methods. Disadvantage: Usage of arrays again instead of objects
  • dump the object into an array-structure and pass it (optionally rebuild the object with that array-structure in the view again). Disadvantage: a) Arrays again b) Overhead c) Some object can't be rebuild easily
  • wrap the invokable object within another class. Disadvantage: a) Bad readability b) Wrapper has no real functionality, makes everything complicated
  • avoid invokable objects. Disdvantage: Loss of a widely used feature

All workarounds gave me a bad feeling.

I don't know how a case like this should be handled (because of BC) but I somehow think that the current implementation is wrong because I have no chance to pass invokable objects - that are not meant to be invoked automatically - in a clean way.

@roelvanduijnhoven
Copy link

Am also having this problem. Had same ideas around workarounds, but all of these feel bad. I reversed engineered that some prior version ZF2 (beta most likely) had a getRawValue method which could have helped.

@roelvanduijnhoven
Copy link

Though it does have some nice properties ;)!

In the end I chose to use the second approach, which was really not a big of a deal.

@weierophinney
Copy link
Member

This repository has been closed and moved to laminas/laminas-view; a new issue has been opened at laminas/laminas-view#18.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants