Action helper resets called function parameters

Hello,

I need to call a function in a controller that resides in a different plugin than the one it’s called from.

For this, Zend 1.12 proposes the Action helper, which is supposed to pass arguments to the called function, but it does not :

$args = [[$entity->id], true, true];
$this->view->action('draw-collections', 'graph', 'graph', $args);

… as per the doc here https://framework.zend.com/manual/1.12/en/zend.view.helpers.html#zend.view.helpers.initial.action;.

The function is called, but the array passed as $args, the fourth parameter, seems to be reset somewhere in the process, resulting in a ‘Too few arguments’ exception because the array is empty.

I tried with only one simple string parameter and the result is the same : nothing comes through.

I’m trying to trace what’s happening in the Action helper, but I could really use some advice to understand what’s going on.

A better way to do the same thing (calling a function from a controller in another plugin’s controller) would maybe be even better.

Really hope someone knows something about this.

Thanks for reading.

Can you go into more detail about what it is you need to do, what the other plugin’s function is? What makes sense to do here varies on whether you’re trying to call another action or just some other method that happens to be in a controller. There are also options like _forward directly in the controller that might be preferable for “reusing” an existing action.

On the “too few arguments” error, you’d probably be best off posting the full exception and trace.

Thanks for your quick answer.

The first plugin draws graphs based on entities relations.

The second (calling) one produces various content blocks which are later used to build a page.

So the final goal is to recover the first plugin’s output and inject it in one of the second’s one ‘blocks’ of content (an HTML string which will later be concatenated with the rest of the page).

The error :

**Fatal error**: Uncaught ArgumentCountError: Too few arguments to function Graph_GraphController::drawCollectionsAction(), 0 passed in /data/www/Omeka/bacasable/application/libraries/Zend/Controller/Action.php on line 515 and at least 1 expected in /data/www/Omeka/bacasable/plugins/Graph/controllers/GraphController.php:39

If I modify the function signature to provide default values to arguments, the call succeeds but they are all defaults, indicating they in fact don’t reach the function itself.

I tried the _forward method but the result is the same : no parameters passed.

I think something weird happens between Zend 1.12 and PHP 7.4 (I know). Maybe some typing or function declaration syntax. Only guessing.

In Graph itself is that method getting called some interesting way? I’m not sure if that’s your plugin also or not.

Typically “action” controller methods in Zend Framework don’t actually take any arguments in the method signature, so that’s probably the source of your problem. Parameters get sent along in a request object, not to the method signature.

Just from looking around briefly, the version of Graph that I can see doesn’t have this method as an “action” method, which makes sense… the rename to include Action would then have been an attempt to make the foward/action methods work with it?

If you’re just looking to call it as a method and it doesn’t really have controller-specific functionality or dependencies, the simplest option is probably going to be to just make the method static so you can call it directly as Graph_GraphController::drawCollections. You could also move it to a separate class or the module class and similarly call it.

1 Like

Typically “action” controller methods in Zend Framework don’t actually take any arguments in the method signature, so that’s probably the source of your problem. Parameters get sent along in a request object, not to the method signature.

Yes, that’s an important concept I didn’t take into account, you’re right. It’s the whole dispatch process which I’m not very familiar with.

Just from looking around briefly, the version of Graph that I can see doesn’t have this method as an “action” method, which makes sense… the rename to include Action would then have been an attempt to make the foward/action methods work with it?

You’re right again. I wrote the plugin and should probably rewrite it (but no time, too many other things going on, etc.) and the “Action” at the end was indeed a pathetic last chance salvaging attempt. Which, as you know, didn’t and couldn’t work.

I did try to find a way to call this method statically but couldn’t get it to work. The syntax you suggest Graph_GraphController::drawCollections doesn’t cut it (Class 'Graph_GraphController' not found). Maybe I should include some file or instantiate something explicitly ?

As for writing a helper, refactoring the code and similar solutions, that’s what I’m trying to avoid because it means a lot more work.

Thank you very much, I appreciate your answers a lot. They help me clarify some key concepts which are still a bit fuzzy for me, and give me new leads to explore.

The problem you’re having calling the controller is just that it’s not autoloaded.

A require_once before your call should be enough:

require_once PLUGIN_DIR . '/Graph/controllers/GraphController.php';

However, it does look from a quick look at your plugin that you do have some dependencies on being an instance method there, so you may have other problems. (All the “draw” functions don’t really return anything but just set entries into $this->nodes, which won’t work from a static call).

Changing the “draw” functions to work statically wouldn’t be an enormous amount of work (probably the move is just to make them return an array of nodes, then change your actions that use them to array_merge the calls to each draw function together to get a final array of all the nodes, rather than using $this->nodes). Once they’re all static they could be left in place or easily moved to another class or the main plugin class (which wouldn’t have the autoload issue you’re seeing now).

Another route you could go to try to avoid those kinds of changes would be to leave everything in place as it is in the original plugin, including drawCollections, but just create a new drawCollectionsAction (or some other name) that takes no arguments in in its signature and just itself calls the old drawCollections, pulls the necessary data from the request and does what you need. Then you could use something like _forward or the action helper with that new, compliant action.

Wow, now that’s some awesome advice.

I’m a little proud (maybe unduly) of my object style implementation, so I think I’ll go for the Action method, which seems less work intensive and leaves more code as it is.

I’ll update this thread with the code when it’ll work.

Thanks a ton.

Well, I eventually went around the problem in a way that is not at all relevant to the points discussed here.

Sorry to disappoint if anyone was expecting something interesting, which I doubt.

Thanks again, for the guidance anyway.