Calling Controller (App.php) functions from setup.php (and other controllers)

sage9
webpack

#1

Hello.

I updated to the latest Sage 9.0.4 and was wondering what happened with the Controller update: I can’t seem to call App::myFunction() from within setup.php anymore? This worked in previous releases, but perhaps it’s wrong to do that in any case.

How can I properly access those methods here?

Just for better understanding, I’m doing something like this for example in setup.php:

/**
 * Theme assets
 */
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
    wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
    $script_params = array(
        'theme_dir_uri' => App::themeDirURI(), // this worked in previous Controller versions
        'ajax_url' => App::ajaxURL(),
        'ajax_nonce' => wp_create_nonce('my_nonce'),
        'home_url'     => home_url(),
        'translations' => array(
            'back_to_top' => __('Back to top', 'my'),
            'back_to_home' => __('Back to home page', 'my')
        ),
    );
    wp_localize_script('sage/main.js', 'GLOBAL_OBJECT', $script_params);
}, 100);

Now using App::myfunction() throws: Call to undefined function .. so I’m clearly doing something wrong from the start.

Thanks!


#2

Hi @trainoasis,

It’s due to the namespace change. If you are using static functions outside of Blade templates, then you need to use the correct namespace. From Controller 2.0.0, PSR4 autoloading is used. So the full namespace for a Controller file is now App\Controllers\

So, in this case, seeing as setup.php is in App namespace, you would use Controllers\App::themeDirURI(). The Controller loader removes the need for this namespace in Blade templates, so there you can simply reference the Controller class name and the static function.

Let me know if that makes sense.


#3

That’s exactly what does it @withjacoby, thank you.

I wasn’t sure where I would figure this one out to be honest.


#4

@withjacoby if you would be so kind, the same issue arises inside custom controllers, for example

public static function makeFlexibleContent()
    {	
    	$data = self::getJumboData();
    	echo Template('components.dynamic-template.jumbotron', $data); 

Template() function not working. Gotta get the correct namespace but am not sure how to proceed or where to find it? How do you know what to add there? Wanna know for the future issues that I’ll have, don’t just wanna ask you every time if possible :slight_smile:

Am totally at a loss here, tried various Controllers\App namespace variations, to no avail. (of course, not knowing how namespaces work here is not helping).


#5

I’m not sure what you are trying to accomplish here, but there is no function called Template() in Sage. Do you mean template()?

Perhaps you could explain the end goal and I can help from there.


#6

Here’s a reply I wrote a bit ago that might help you out with understanding namespaces: Controller namespace issue, different behavior on localhost and development server (solved?)

Finding out what namespace a class, method, or function is in is generally pretty simple:

  • Find the file where the function/method/class is defined
  • Go to the top of the file and look for namespace
  • If you’re looking for a…
    • function then that’s it, just prepend the namespace when calling the function
    • class then that’s it, just prepend the namespace when calling the class
    • method then you’ll need to prepend the namespace, then class, when calling the method

Take the example file below:

<?php

namespace Roots;

class Sage {
    public static function hello()
    {
        return 'hello from a method';
    }
}

function goodbye()
{
    return 'goodbye from a function';
}

To instantiate this class in another file, you would write:

$class = new Roots\Sage();

To call the static method hello() from another file, you would write:

$greeting = Roots\Sage::hello();

To call the function goodbye() from another file, you would write:

$farewell = Roots\goodbye();

If the other file has a namespace, and that namespace is not Roots, then you need to prepend a slash to all of your calls, i.e.:

$greeting = \Roots\Sage::hello();

That should be enough info to get you started.


#7

I thought template() at first as well (function inside helpers.php), but am using Template() in my production code with previous Sage versions and it’s working as expected. I found that here on discourse some time ago, but here used to output shortcodes as @MWDelaney shows: https://discourse.roots.io/u/MWDelaney): Shortcodes that use Blade templates and get Controller data. I do admit I don’t know where this functions comes from.

It helps when outputting template code from Ajax or when you want a function that you can use that outputs the whole view based on controller info.

Does that make any sense or am I abusing certain paradigm?


#8

Thanks, that’s very helpful. It seems my main issue is I don’t know where Template() comes from. There’s template() in helpers.php, but on my live site Template() works without seeing any Template() anywhere. Perhaps I’m just missing some knowledge there :slight_smile:

Follow up: made it work using your instructions: current file has namespace App\Controllers; and thus I had to move to a different namespace using prepended slash so \App\Template() does work!

Didn’t know you can use Template() OR template() and both work.

Thanks for your quick lecture, love it.


#9

Thanks @withjacoby, made it work using \App\Template(). It seems both template() and Template() work, although I do not know why.

Didn’t know I can move to a different root namespace using prepended slash, so there you have it.

If you do know about naming conventions and why both functions work, please share :slight_smile:

Thanks for your time!


#10

Glad to hear! No problem.