2

I'm creating a theme framework and using a class to initiate all basic function of the theme (adding theme support, menus, etc). I've got stuck when I tried to enqueue the scripts and styles though:

I'm using add_action( 'init', array(&$this, 'EnqueueScrits'), 10, 1); and do_action( 'init', $enqueued ); to call method with the $enqueued param. That's working fine, however when I try to use the same technique in order to add wp_enqueue_style the $param are getting mixed up (the $param for scripts are also used for styles).

My solution then was to create a chain reaction to the first add_action like so:

but then nothing happens and the action is not called at all (it seems like that anyway). Does anyone knows a better solution for this or what am I missing?

EDIT: Here's the full code. My class:

class Nomade
{

    public function __construct($menus, $features, $enqueued, $styled)
    {

        // Define base constants
        define('THEME_FRAMEWORK', 'nomade');
        define('NOMADE_VERSION', '1.0');

        // Define directories
        define('NOMADE_DIR', get_template_directory());
        define('NOMADE_LIB_DIR', get_template_directory() . '/library');

        $this->AddThemeSupport($features);
        $this->MenuBuilder($menus);

        // Add support for WordPress features
        add_action('after_setup_theme', array(__CLASS__, 'MenuBuilder'));
        add_action( 'after_setup_theme', array(__CLASS__, 'AddThemeSupport'));
        add_action( 'init', array(&$this, 'EnqueueScrits'), 10, 1);

        do_action( 'init', $enqueued );

    }

    public function AddThemeSupport($features)
    {

        if(is_array($features))
        {

            foreach ($features as $feature) {

                add_theme_support($feature);

            }

        }

    }

    public function MenuBuilder($menus)
    {

        if (is_array($menus)) {

            foreach ($menus as $location => $name) {

                register_nav_menus(array(

                    $location => $name

                ));

            }

        }

    }

    public function EnqueueScrits($enqueued)
    {

        if (is_array($enqueued)) {

            foreach ($enqueued as $value) {

                wp_enqueue_script( $value["name"], $value["location"], array("jquery"), $value["version"], true );

            }

        }

    }

}

And here how I instantiate the object (in a separate file):

<?php

// Depedencies: menu registrer and builder
include('application.class.php');

// Set menus
$menus = array( 'main_menu' => 'Main Menu', 'footer_menu' => 'Footer Menu', 'side_menu' => 'Sidebar Menu' );

// Set theme features
$features = array( 'menus', 'custom-background', 'custom-header', 'post-thumbnail' );

// Register scripts array
$register = array( 'scripts' => 'NOMADE_DIR' . '/js/scripts.js' );

// Enqueue scripts array
$enqueued = array(  
    array("name" => "general", "location" => get_template_directory_uri() . '/js/general.js', "version" => 1)
);

$styled = array(
    array("name" => "main", "location" => "lac1", "version" => 2, "media" => "all")
);

// Instantiate Nomade (main application)
$Nomade = new Nomade($menus, $features, $enqueued, $styled);

Thanks for the help in advance

4
  • 1
    If you are inside a class way would you need to pass the parameter? can't you use a property?
    – Bainternet
    Apr 14, 2013 at 14:35
  • The parameters are being created (as arrays with whatever configuration I required for that particular theme only) once the object is instantiated in a separate file. This way I can keep the main application logic separated from configuration data. Apr 14, 2013 at 14:41
  • Can you post your code with more context?
    – s_ha_dum
    Apr 14, 2013 at 14:47
  • Now seeing your edit: Remove the do_action call - it is not necessary. In the line above that (add_action( 'init', array(&$this, 'EnqueueScrits'), 10, 1);), change the action from init to wp_enqueue_scripts, i.e. make that add_action( 'wp_enqueue_scripts', array(&$this, 'EnqueueScrits'));. And finally, make the $enqueued array accessible by your EnqueueScrits method by assigning it to a class property (as I have laid out below) from within the constructor and access it via $this->enqueued from within your EnqueueScrits method. Do the same for the other 3 variables. Apr 15, 2013 at 19:40

1 Answer 1

2

The init action...

is one of many WordPress core action hooks. Hence it does not require, i.e. should not be accompanied by, a manual do_action call.

You only need to manually run do_action for custom, previously non-existent, action hooks.

Further, init is not the action which you want to hook the script enqueuing with. There is an action specifically for this purpose.

Your situation

if ( ! class_exists( 'WPSE_Your_Class' ) ) :
class WPSE_Your_Class
{

    private $enqueued = array();

    public function enqueue_all_scripts()
    {
        if ( is_array( $this->enqueued ) && ! empty( $this->enqueued ) ) {
            foreach ( $this->enqueued as $script ) {
                wp_register_script(
                    $script['handle'],
                    $script['src'],
                    array( 'jquery' ),
                    $script['version'],
                    true
                );
                wp_enqueue_script( $script['handle'] );
            }
        }
    }

    public function __construct( $enqueued = array() )
    {
        $this->enqueued = $enqueued;
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_all_scripts' ) );
    }

}
endif;

Pass the $enqueued array to the object instance via the constructor of your class.
Assign that value to a class property and thereafter hook the enqueue_all_scripts method to wp_enqueue_scripts.
Make said method dependent on the previously populated class property.

Create a new instance like so:

$enqueued = array(
      array(
           'handle' => 'some-handle',
           'src' => 'http://some-url.com/path/to/script/scripts.js',
           'version' => '1.0'
      ),
      array(
           'handle' => 'another-handle',
           'src' => 'http://some-url.com/path/to/script/another_scripts.js',
           'version' => '1.1'
      )
      // possibly more
);
$your_class_instance = new WPSE_Your_Class( $enqueued );

Sidenote

As an aside, &$this is PHP4, and, as I recently learned, it is useless to attempt to support PHP4, since the core won't run on it anyway.

Edit - your full code rewritten

The above is the way I'd do it. That's certainly not the only option and most likely not the slickest possible, but it does work. Given your edit, I've adjusted your code while trying to preserve some of your own naming conventions and coding style:

class Nomade
{

    /* class properties */
    private $enqueued = array();
    private $features = array();
    private $menus = array();
    private $styled = array();

    /* constructor */
    public function __construct( $menus, $features, $enqueued, $styled )
    {
        // Assign values to class properties
        $this->enqueued = $enqueued;
        $this->features = $features;
        $this->menus = $menus;
        $this->styled = $styled;

        // Define base constants
        define('THEME_FRAMEWORK', 'nomade');
        define('NOMADE_VERSION', '1.0');

        // Define directories
        define('NOMADE_DIR', get_template_directory());
        define('NOMADE_LIB_DIR', get_template_directory() . '/library');

        $this->AddThemeSupport();
        $this->MenuBuilder();

        // Add support for WordPress features
        add_action( 'after_setup_theme', array( $this, 'MenuBuilder' ) );
        add_action( 'after_setup_theme', array( $this, 'AddThemeSupport' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'EnqueueScripts' ) );
    }

    public function AddThemeSupport()
    {
        if( is_array( $this->features ) && ! empty( $this->features ) )
        {
            foreach ( $this->features as $feature ) {
                add_theme_support( $feature );
            }
        }
    }

    public function MenuBuilder()
    {
        if( is_array( $this->menus ) && ! empty( $this->menus ) )
        {
            register_nav_menus( $this->menus );
        }
    }

    public function EnqueueScripts()
    {
        if( is_array( $this->enqueued ) && ! empty( $this->enqueued ) )
        {
            foreach ( $this->enqueued as $value ) {
                wp_enqueue_script(
                    $value["name"],
                    $value["location"],
                    array("jquery"),
                    $value["version"],
                    true
                );
            }
        }
    }

}
6
  • Thanks for your answer Johannes. However the reason I'm using do_action is because the I'm passing a parameter to the function which is enqueuing the scripts. Also, the method that enqueues the scripts is located inside the class, but the data (the array that contains which scripts to enqueue) is being passed only when the object is instantiated in a separate file. I've tried using your method, but it didn't work. I'm posting my full code so you can see what I've done and what might be wrong... Apr 15, 2013 at 19:14
  • If you copied the above as is, the only reason I can see for it not working would be the object instantiation being too late. Is the mentioned separate file interpreted before the relevant action hook has run? Apr 15, 2013 at 19:31
  • This file is being included in the functions.php, so it follows the standard interpretation order, I suppose. I'll create a new file copying literally everything you wrote above and try again. I'll get back to you shortly. Thank you again for your help! Much appreciated Apr 15, 2013 at 19:50
  • I apologise! It does work! I must have mistyped something when I copied it initially. One question though, in my __construct, how should I add so many arrays? public function __construct( $enqueued = array(), $another_array = array(), so on so forth? )or should I create an array with nested arrays? Apr 15, 2013 at 19:55
  • Making the parameters optional (by assigning empty arrays) isn't strictly necessary anyhow. That's only helpful if you'd like to instantiate the class without all parameters at some point. Whether to pass it four parameters or one as a nested array is really up to your preference / coding style. It doesn't matter, either will work. Also, I took the liberty to adjust your now supplied full code above, so see that for further info. Apr 15, 2013 at 20:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.