Using helper functions inside of a Blade template

I’m trying to use a function from the helpers.php inside of my index.blade.php.

I have required the php script
require_once(get_theme_file_path() . '/app/helpers.php');
and tried to access the function by calling App\get_excerpt_by_id($featuredPoem->ID); but I keep getting

Call to undefined function App\get_excerpt_by_id()

I’m sure I must be doing some really stupid mistake but I just can’t figure out what it is.
Help?

3 Likes

Hey @Tom-m,

Given this code in helpers.php:

function yarr() {
  return 'yarr';
}

This should work in index.blade.php.

{{ App\yarr() }}

FYI you don’t need to require helpers.php! It’s being automatically loaded by Sage already.

If that doesn’t help, if you post the actual code from each file I’m happy to look more closely.

8 Likes

Works perfectly, thanks!

Great! Glad I could help.

There’s a chance your task is better suited to Controller than it is to a calling a function from within your template.

Controllers can set up template data so that you can just call {{ $yarr }} whenever you need it. They keep template data separate from the more gritty functions of the theme, and keep the ugly logic separate from the template files themselves.

Controllers is how Sage does {!! App::title() !!} (see the function in app/controllers/app.php).

1 Like

That’s a good point, @MWDelaney. I’m just learning to work with the new structure and tools incorporated into Sage 9 myself–what would a good guideline be for distinguishing between when something would go in a controller as opposed to a more generalized location like helpers.php?

Perhaps something like this:

  1. Template logic / data preparation for use in one template → put it in the controller for that template
  2. Template logic / data preparation for use in multiple templates in the theme → put it in the App controller. Or maybe as a component using traits?
  3. Actions and filters → setup.php, filters.php, or your own additional files (e.g., if doing a lot of filters/actions for a specific plugin’s hooks, you might add pluginName.php to the app folder)
  4. Other code used by the theme → helpers.php or your own additional files in the app folder

@Tom-m, I may be overexplaining, but in case you’re learning this for the first time like me, here’s a crash course.

Assuming your function returns some data you want to use in your template(s), here are a couple of ways the earlier example might be implemented via controllers.

For use in multiple templates
The code in helpers.php would be moved to app/controllers/app.php:

<?php

namespace App;

use Sober\Controller\Controller;

class App extends Controller
{
    // the preexisting code ....
    
    // your new code
    public function myYarr() {
      return 'yarr';
    }
}

When you create a public method in a controller and return something from it, a variable that contains that data is automatically made available in the corresponding templates (without having to include or require the controller). The variable name will be the name of the method, converted to snake case. In the case of the app controller, it is available in all templates.

In your template, you’d just do this:

{{ $my_yarr }}

And ‘yarr’ would be printed. Note how the method name myYarr() became the variable $my_yarr.

For use just in the index template
Sage doesn’t ship with a controller for the index template, so we’ll have to create one. You can create a new controller by adding a file in the controllers folder that matches the name of the template. In this case, add index.php to the app/controllers folder.

Start with this in your new index.php file:

<?php

namespace App;

use Sober\Controller\Controller;

class Index extends Controller
{
    
}

Notes:

  1. We’re placing the contents of the file in the App namespace, like the rest of Sage.
  2. We’re including the SoberWP Controller namespace so that we have access to what it contains.
  3. We’re creating a new class, also named Index–this is your controller. It’s an extension of SoberWP’s Controller class, which means it inherits certain things from the Controller class and we don’t have to build everything from scratch for each of our controllers.

We can add our myYarr method to this new controller now:

<?php

namespace App;

use Sober\Controller\Controller;

class Index extends Controller
{
    public function myYarr() {
      return 'yarr';
    }
}

And again we can now use it in the template by doing: {{ $my_yarr }}. In this case, though, we can only do this in the index template, because we defined the method in the Index controller rather than the App controller.

Because we’re dealing with the index template, you may be calling your method from within the loop and a static method may be more appropriate. Info here: GitHub - soberwp/controller: Composer package to enable a controller when using Blade with Sage 9. I’m still a little less clear on the when’s and why’s of static methods in controllers. Possibly @MWDelaney can help here?

Hope that’s useful! You can read more about controllers in Sage 9 here: https://github.com/soberwp/controller. I also have found some threads on this forum very helpful for getting oriented. Here are two:

https://discourse.roots.io/t/best-practice-resources-for-blade/8341/3

https://discourse.roots.io/t/acf-variables-in-blade-template/10180

Though note that the code examples early on in the first one refer to earlier versions of Sage 9 before the SoberWP controller was added.

8 Likes

That’s basically how I think about it. helpers.php sets up templating as a concept; it doesn’t set up the actual data being used in the template; that’s what Controllers are for.

Don’t forget that if you add a file to /app, you’ll need to add it to the include array in functions.php, too.

Regarding static functions in Controllers, since non-static function data is set up before the template loads, {{ $yarr }} will always return the same value, regardless of whether you’re currently inside a loop. Calling the method statically will run the function when you call it rather than before the template loads; so if you’re inside a loop, you’ll get data associated with that loop.

Does that help?

6 Likes

Yep, that’s super helpful. Thank you!

Wow, beautiful. This will make my templates so much cleaner.
Thanks a lot guys for taking the time to explain it :+1:

4 Likes