I'm working on my first OOP (MVC) based plugin.

Everything works perfect, enqueue front/back-end styles, admin menu pages, shortcodes creation, etc...

I load my main plugin class using the init hook.

From the controller I instantiate the class Custom_VC_Elements (with constructor active).

class Custom_VC_Elements {

public function __construct() {
    // Armon Product link shortcode
    add_shortcode( 'armon_product_link', array( $this, 'armon_product_link_shortcode' ) );
    // Armon Product link VC element
    add_action( 'vc_before_init', array( $this, 'armon_product_link_vc' ) ); 

// Add armon_product_link element to VC
public function armon_product_link_vc() {
        // All vc_map args here ...
} // Class

The add_shortcode is working without any problems... Somehow the vc_before_init hook is not.

I'm asking the question here and not on the Visual Composer forums, because vc_before_init hook works perfect from the main plugin file, so outside all plugin classes.

I tried the following:

  • Use class name $Custom_VC_Elements instead off $this.
  • Create a class Custom_VC_Elements_init and create a instance of that class like so:
    add_action( 'vc_before_init', array( WPWDtools::load_class( "Custom_VC_Elements_init", "class-custom-vc-elements-init.php", 'add-ons' ), 'armon_product_link_vc' ) );
  • First hook into admin_init and then into vc_before_init.
  • First hook into plugins_loaded and then into vc_before_init.

I don't get any php error's, wp_debug = true ... So debugging this is not easy..

Like I said, this is my first OOP based plugin, so please try to explain your answer.

Many thanks!

Regards, Bjorn


It now works when I (from the main plugin file) require_once a file with the vc_before_init hook. So, before my plugin 'init' hook which instantiates my main plugin (abstract) class. Snippet main plugin file:

// Testing
require_once WPWDTOOLS_ABSPATH . 'add-ons/custom-vc-elements-init.php';
// Load WPWDtools class, which holds common functions and variables.
require_once WPWDTOOLS_ABSPATH . 'classes/class-wpwdtools.php';
// Start plugin.
add_action( 'init', array( 'WPWDtools', 'run' ) );

I still don't understand this behaviour..? When I check inside my main plugin file if the vc_before_init hook is already fired it returns true... But my current 'fix' (setting the hook outside any class) still works..? In short, it doesn't matter where or how I wrap vc_before_init in a class, it allways fails..

  • 1
    First idea in my mind: when your constructor is called, the 'vc_before_init' already fired.
    – gmazzap
    Sep 28, 2015 at 11:14
  • Yes, I thought the same.. But I only use the hook 'init' to instantiate plugin's main class. From the main class I instantiate the Controller. The controller instantiate the Custom_VC_Elements class..
    – Bjorn
    Sep 28, 2015 at 11:19
  • Right, @gmazzap is suggesting that, by the time your Controller has been instantiated, vc_before_init has already fired.
    – phatskat
    Sep 28, 2015 at 13:55
  • Yes, and I try to explain that my program fires up on the 'init' hook, and then before any other hook is called it hits the 'vc_before_init' hook. So 'vc_before_init' is called under the 'init' hook... I hope you understand what i mean ^^.
    – Bjorn
    Sep 28, 2015 at 16:46

2 Answers 2


I found the solution... First I thought the problem had something to do with wrapping the hook inside a class.. But after some more testing (sometimes you need to take a step back), it appears the hook vc_before_init has already fired on the init hook with the (default) priority of 10...

My current theme (Salient) has made a custom Visual Composer, that is provided in the theme package.. After checking the theme hooks with 'Prioritize Hooks' plugin. I found that the theme has the following: add_action( 'init', 'add_nectar_to_vc', 5 );

I now use add_action( 'init', array( 'WPWDtools', 'run' ), 4 ); to start-up my plugin, and now everything works as expected.

Without diving into my theme any further, I suspect that it forces the vc_before_init hook to fire early (on 'init' with priority:5).

I want to thank @phatskat & @gmazzap for helping me. You guys where wright, telling me the hook probably already fired.


vc_before_init hook works perfect from the main plugin file, so outside all plugin classes.

You can try hooking it there then maybe. If you can instantiate the class in the main file as needed, and then hook into it, you should be fine:

$my_elements = new Custom_VC_Elements();
add_action( 'vc_before_init', array( $my_elements, 'armon_product_link_vc' ) );

Not sure if this works well with your classes, however. The other option would be to use a hook that happens later, as it sounds like vc_before_init may already have happened. To test this, you could do:


// Top of plugin file - NB that you should never use $GLOBALS
// in production, but this is purely for debugging

add_action( 'vc_before_init', 'test_my_vc_timing' );

function test_my_vc_timing() {

// In your class
class Custom_VC_Elements {
    public function __construct() {
        // Snip...
        // DEBUGGING!
    } // Snip...
} // Class

If you can hook into vc_before_init in your classes constructor, then the var_dump should return false. If it's true, then the action has already run by the time your class is instantiated.

  • I was thinking the same and was debugging with did_action(), but I like your snippet. So when I add it to the main plugin file, the boolean returns true..??? But I still have a working test 'vc_before_init' inside the second file that is called from the main plugin file with recuire_once.. This still works..???
    – Bjorn
    Sep 28, 2015 at 18:02
  • Check my edit inside the main question.
    – Bjorn
    Sep 28, 2015 at 20:58

Your Answer

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

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