forTemplate Error when passing searchForm results to function

<%- if @topic_view.topic.tags.present? %>
<%= t 'js.tagging.tags' %>: <%- @topic_view.topic.tags.each do |t| %> <%= t %> <%- end %>
<% end %>

Silverstripe Version: 4.4.x-dev

Question: I get the error Uncaught BadMethodCallException: Object->__call(): the method 'forTemplate' does not exist on 'SilverStripe\ORM\ArrayList when I passed the results obtained from a searchFrom object to a function. What can I do to fix this?'
Following the instructions here, I have implemented a search function for my site: https://docs.silverstripe.org/en/3/tutorials/site_search/ (I know this is for the previous version of silverstripe, but for some reason it mostly works). The only problem is that some search results aren’t correct (ie. the query searched is not contained within the page). To correct this, I wrote a function to filter out pages that are returned but not correct. The only problem is that when I try to pass the results returned by the searchForm to this filtering function, I get the error Uncaught BadMethodCallException: Object->__call(): the method 'forTemplate' does not exist on 'SilverStripe\ORM\ArrayList. The issue is with my code in the template. I know this because I have tested passing the results to an empty function and it still results in the same error. I’m not really sure what to do to fix this.

Here is the code I have in Page_results.ss that causes the issue:

<% loop filterResults($Results) %>
<% end_loop %>

If instead of passing $Results, I pass garbage (ex. “foo”), then I don’t get the error, so I know this is what is causing it.

Any ideas?

Hi 18goldr,

It seems you are conflating the ideas of a templating language, and a procedural language (PHP) - the template is not the place to call functions. The ability to do so was introduced for very simplistic calls (e.g. string formatting), and all the parameters are generally coerced into strings - this is what is happening here. Your result set (which is an ArrayList) is being transformed into a value the template engine can pass into a function call - it does this by trying to process it for rendering, calling forTemplate on the object it has. This method does not exist, so the error is thrown.

The way to get around this is to move the logic you have into PHP - instead of passing a parameter in to the function, try to get the result set directly when calling filterResults.

e.g.

function filteredResults()
{
    $results = $this->results();

If you’re interested in reading further on why this seems a bit more tricky than it needs to be (with regards to function calls in templates), you can search the web about the “MVC” architecture and “separation of concerns” :slight_smile: