New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add public shortcodes #262

Closed
tprinty opened this Issue Feb 5, 2015 · 33 comments

Comments

Projects
None yet
@tprinty

tprinty commented Feb 5, 2015

Hello,

I am not clear on how to add a public shortcode? Can you provide an example?

Thanks
-Tom

@tprinty

This comment has been minimized.

tprinty commented Feb 5, 2015

I got this to work.... In class-myplugin-public on the define-hooks()
I added
$this->loader->add_action( 'shortcode', $plugin_public, 'shortcode_function' );
add_shortcode( 'shortcode', array( $plugin_public, 'shortcode_function') );

@slushman

This comment has been minimized.

slushman commented Feb 5, 2015

An alternative (in case you want to add other shortcodes) would be to create a public function that contains all the add_shortcode declarations. Then the separate function for processing the shortcode. Something like:

define_hooks() {
$this->loader->add_action( 'shortcode', $plugin_public, 'register_shortcodes' );
}

public function register_shortcodes() {
add_shortcode( 'shortcode', array( $this, 'shortcode_function') );
add_shortcode( 'anothershortcode', array( $this, 'another_shortcode_function') );
}

@bruno-rodrigues

This comment has been minimized.

bruno-rodrigues commented Feb 11, 2015

@slushman When you used:

    define_hooks() { 
        $this->loader->add_action( 'shortcode', $plugin_public, 'register_shortcodes' );
    }

Didn't you mean?:

    define_hooks() {
        $this->loader->add_action( 'init', $plugin_public, 'register_shortcodes' );
    }

There is no hook to 'shortcode'.

Thanks for sharing your method, helped me a lot!

@slushman

This comment has been minimized.

slushman commented Feb 11, 2015

Doh! Yes, Bruno, bad copy/paste. The hook should be init.

@thewebsitedev

This comment has been minimized.

thewebsitedev commented Mar 4, 2015

@slushman Why do we need a separate function for hooks? Why can't we simply use $this->loader->add_action( 'init', $plugin_public, 'register_shortcodes' ); inside define_public_hooks() function?

Sorry if I misunderstood this comment - #262 (comment)

@t1mduma5

This comment has been minimized.

t1mduma5 commented Mar 5, 2015

Does anyone have or know where i can find a complete shortcode plugin based on this boilerplate and @slushman's recommendation for multiple shortcodes that I could look at? I feel like I am missing some info. I would be happy to share a folder in Dropbox or, get it from here if it's on here.

Thanks in advance.

@DevinVinson

This comment has been minimized.

Owner

DevinVinson commented Apr 3, 2015

What I've done recently is add an add_shortcode function to the loader class. That way you can add shortcodes that are admin or public leaning just like you would a filter or action.

I'm on the fence of calling them always one or the other but this way it can be up to you or even both.

In loader:

    /**
     * Add a new shortcode to the collection to be registered with WordPress
     *
     * @since     1.0.0
     * @param     string        $tag           The name of the new shortcode.
     * @param     object        $component      A reference to the instance of the object on which the shortcode is defined.
     * @param     string        $callback       The name of the function that defines the shortcode.
     */
    public function add_shortcode( $tag, $component, $callback) {
        $this->shortcodes = $this->add( $this->shortcodes, $tag, $component, $callback );
    }

then change the run function to:

    /**
     * Register the filters, actions, and shortcodes with WordPress.
     *
     * @since    1.0.0
     */
    public function run() {

        foreach ( $this->filters as $hook ) {
            add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
        }

        foreach ( $this->actions as $hook ) {
            add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
        }

        foreach ( $this->shortcodes as $hook ) {
            add_shortcode( $hook['hook'], array( $hook['component'], $hook['callback'] ) );
        }

    }
@rohan-deshpande

This comment has been minimized.

rohan-deshpande commented Apr 27, 2015

Hmm looks good but won't this is throwing a bunch of errors for me in the add method regarding missing arguments.

@slushman

This comment has been minimized.

slushman commented Apr 27, 2015

@ gthapar: Sorry for the super-late response! The way I'm describing in #262 is just an abbreviated version of the define_public_hooks method already in the boilerplate. The way the boilerplate is setup, all the hooks are done together in one method. The 'register_shortcodes' method in the public class is where you'd actually register the shortcode and another method in the public class would take care of what happens in that shortcode.

@t1mduma5 also: you can see how all this flows in a plugin I put together called Now Hiring: https://github.com/slushman/now-hiring

I've only defined one shortcode, but adding another one would simply be a matter of adding another register_shortcode() in the 'register_shortcodes' method in the public class and writing the appropriate method to handle whatever that other shortcode does.

@DevinVinson

This comment has been minimized.

Owner

DevinVinson commented May 6, 2015

@rohan-deshpande You can edit the required arguments so that it doesn't.

@jg314

This comment has been minimized.

jg314 commented May 15, 2015

@DevinVinson, your suggestions at #262 (comment) worked great for me. I did go ahead and add a $shortcode property and adjusted the add_shortcode() method slightly to include the $priority and $accepted_args arguments which got rid of the errors. It now reads:

public function add_shortcode( $tag, $component, $callback, $priority = 10, $accepted_args = 2 ) {
        $this->shortcodes = $this->add( $this->shortcodes, $tag, $component, $callback, $priority, $accepted_args );
    }

Thanks for the help.

@goranefbl

This comment has been minimized.

goranefbl commented Aug 26, 2015

This should come in plugin boilerplate. Its easy to remove unnecessary code if you dont need shortcodes in your plugin.

@glouk7

This comment has been minimized.

glouk7 commented Oct 22, 2015

Hi, i am creating a custom plugin based on boilerplate plugin, and i use a shortcode to display public data.
$this->loader->add_action( 'test-plugin', $plugin_public, 'display_front_page' );
add_shortcode( 'test-plugin', array( $plugin_public, 'display_front_page') );

The issue is that on every public page, that the shortcode is used, at the end of the page i get the number 1.
I really cannot find where is this number 1 produced from.

Any idea?

@goranefbl

This comment has been minimized.

goranefbl commented Oct 22, 2015

Check return vs echo, can you post your whole code?

On 22 Oct 2015, at 10:49, George notifications@github.com wrote:

Hi, i am creating a custom plugin based on boilerplate plugin, and i use a shortcode to display public data.
$this->loader->add_action( 'test-plugin', $plugin_public, 'display_front_page' );
add_shortcode( 'test-plugin', array( $plugin_public, 'display_front_page') );

The issue is that on every public page, that the shortcode is used, at the end of the page i get the number 1.
I really cannot find where is this number 1 produced from.

Any idea?


Reply to this email directly or view it on GitHub.

@rvarbanov

This comment has been minimized.

rvarbanov commented Nov 12, 2015

I am new to this plugin boilerplate, and I have a lot to learn about it still, but would you please explain to me what are the pros and cons of the two methods:

@slushman's method
#262 (comment)

define_public_hooks() {
    $this->loader->add_action( 'init', $plugin_public, 'register_shortcodes' );
}

public function register_shortcodes() {
    add_shortcode( 'shortcodename', array( $this, 'shortcode_function') );
    add_shortcode( 'anothershortcodename', array( $this, 'another_shortcode_function') );
}

and

@DevinVinson's method
#262 (comment)

    /**
     * Add a new shortcode to the collection to be registered with WordPress
     *
     * @since     1.0.0
     * @param     string        $tag           The name of the new shortcode.
     * @param     object        $component      A reference to the instance of the object on which the shortcode is defined.
     * @param     string        $callback       The name of the function that defines the shortcode.
     */
    public function add_shortcode( $tag, $component, $callback) {
        $this->shortcodes = $this->add( $this->shortcodes, $tag, $component, $callback );
    }
    /**
     * Register the filters, actions, and shortcodes with WordPress.
     *
     * @since    1.0.0
     */
    public function run() {

        foreach ( $this->filters as $hook ) {
            add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
        }

        foreach ( $this->actions as $hook ) {
            add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
        }

        foreach ( $this->shortcodes as $hook ) {
            add_shortcode( $hook['hook'], array( $hook['component'], $hook['callback'] ) );
        }

    }

I am looking for - we do it this way or that way because...

I could not think of a good situation when a plugin will need to register multiple shortcodes. If your plugin has more than one you probably need to create new plugins for the extra shortcodes

@slushman

This comment has been minimized.

slushman commented Nov 12, 2015

Hey Radi,
I think either is perfectly fine. The first way is what I started with and I think it matches more closely to the Codex examples.

However, I've started using the latter method recently and now prefer it. I look at shortcodes as a hook, of sorts, and using the loader class to declare which function processes a shortcode seems more efficient than declaring a function that then points to other functions. I'm sure Devin has better reasons. :)

As far as multiple shortcodes, I've run into a few situations recently where the end-user needed a separate shortcode to display different content that wouldn't be easily accomplished using a shortcode attribute. WooCommerce has several examples of this kind of thing. I see it provides the non-technical end-user a method of pseudo-designing a page for their needs without needing to write code. I'm not quite done with the functionality around those additional shortcodes, so I don't believe its up on Github just yet.

@DevinVinson

This comment has been minimized.

Owner

DevinVinson commented Nov 12, 2015

There are a lot of reasons why a plugin would be adding multiple shortcodes. So think of that as a given.

With that said, I think either will work though I like adding to the loader since it means the formatting and logic stays the same.

@rvarbanov

This comment has been minimized.

rvarbanov commented Nov 13, 2015

Thank you for replying so fast! I will take your word for it.

Probably this it not the right place to discuss this, but I am curious in what situations would you want/need multiple different shortcodes in your plugin?

@webmarka

This comment has been minimized.

webmarka commented Nov 13, 2015

For instance, I'm just doing a plugin which is creating multiples shortcodes automatically for a template system where each field becomes a shortcode of type [prefix_my_field]. Usefull instead of writing them down, especially if it's dynamically generated.

@LeeRobertsMe

This comment has been minimized.

Contributor

LeeRobertsMe commented Nov 13, 2015

I add mine via the loader as well.

@rvarbanov

This comment has been minimized.

rvarbanov commented Nov 13, 2015

OK, so I followed your lead and implemented the add_shortcode method in the loader, but now I get this:

Notice: Undefined property: Pluginname_Loader::$shortcodes in ...\wp-content\plugins\pluginname\includes\class-pluginname-loader.php on line 95

and line 95 is a comment

@webmarka

This comment has been minimized.

webmarka commented Nov 13, 2015

Did you declared var $shortcodes in the beginning of file "class-pluginname-loader.php" ?

protected $shortcodes;

By the way, your files should be renamed with your plugin name, but that's not an issue I think.

@rvarbanov

This comment has been minimized.

rvarbanov commented Nov 13, 2015

I am sorry, I was working late last night and for some reason I had hardcoded that warning in my shortcode return...

LOL

@sftranna

This comment has been minimized.

sftranna commented Apr 21, 2016

I am unable to get my shortcode working as described by @DevinVinson andupdated by @jg314
here is my loader file's code
protected $shortcodes;

/**
 * Initialize the collections used to maintain the actions and filters.
 *
 * @since    1.0.0
 */
public function __construct() {

    $this->actions = array();
    $this->filters = array();
            $this->shortcodes = array();

}

public function add_shortcode( $tag, $component, $callback, $priority = 10, $accepted_args = 2 ) {
$this->shortcodes = $this->add( $this->shortcodes, $tag, $component, $callback, $priority, $accepted_args );
}
public function run() {

    foreach ( $this->filters as $hook ) {
        add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
    }

    foreach ( $this->actions as $hook ) {
        add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
    }

            foreach ( $this->shortcodes as $hook ) {
                add_shortcode(  $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
            }

}

and code from public class file is
public function define_hooks() {
$this->loader->add_shortcode( "testShortcode", $this->Ec_Authorizenet, "shortcode_function", $priority = 10, $accepted_args = 2 );
}

    public function shortcode_function(){
        echo 'Test the plugin';
    }
@goranefbl

This comment has been minimized.

goranefbl commented Apr 21, 2016

Can u place whole public class file, use gist

Sent from my iPhone

On 21 Apr 2016, at 05:09, sftranna notifications@github.com wrote:

I am unable to get my shortcode working as described by @DevinVinson andupdated by @jg314
here is my loader file's code
protected $shortcodes;

/**

  • Initialize the collections used to maintain the actions and filters.
    *

  • @SInCE 1.0.0
    */
    public function __construct() {

    $this->actions = array();
    $this->filters = array();
    $this->shortcodes = array();

}
public function add_shortcode( $tag, $component, $callback, $priority = 10, $accepted_args = 2 ) {
$this->shortcodes = $this->add( $this->shortcodes, $tag, $component, $callback, $priority, $accepted_args );
}
public function run() {

foreach ( $this->filters as $hook ) {
    add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}

foreach ( $this->actions as $hook ) {
    add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}

        foreach ( $this->shortcodes as $hook ) {
            add_shortcode(  $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
        }

}
and code from public class file is
public function define_hooks() {
$this->loader->add_shortcode( "testShortcode", $this->Ec_Authorizenet, "shortcode_function", $priority = 10, $accepted_args = 2 );
}

public function shortcode_function(){
    echo 'Test the plugin';
}


You are receiving this because you commented.
Reply to this email directly or view it on GitHub

@sftranna

This comment has been minimized.

sftranna commented Apr 21, 2016

@slushman

This comment has been minimized.

slushman commented Apr 21, 2016

You'll want to put this line:

$this->loader->add_shortcode( "testShortcode", $this->plugin_name, "shortcode_function", $priority = 10, $accepted_args = 2 );

Inside the define_public_hooks() function in the main plugin file. Check out these changes:

$this->loader->add_shortcode( "testShortcode", $public_class, "shortcode_function", 10, 2 );

Change "$this->plugin_name" above to reference the public class and remove the "$priority" and "$accepted_args" variables.

@sftranna

This comment has been minimized.

sftranna commented Apr 21, 2016

Thanks @slushman and @goranefbl this solved the issue.

@slushman i am now following your plugin https://github.com/slushman/now-hiring as a template for my plugin. Thanks for the working example. Love this 💯

@webdados

This comment has been minimized.

webdados commented Sep 8, 2016

@sftranna I'm using your example at https://gist.github.com/sftranna/2dae207cc9912f7b64fec88bacb7066d but the shortcodes defined inside the public class on define_hooks are not being added at all.

Shouldn't the define_hooks function be called somewhere?

@webdados

This comment has been minimized.

webdados commented Sep 8, 2016

@sftranna I've added $this->loader->add_action( 'init', $plugin_public, 'define_hooks' ); to the define_public_hooks function on the main class but I'm now getting "Call to a member function add_shortcode() on a non-object" on the define_hooks function maybe because $this is not a Loader class function.

@FiGOBLAC

This comment has been minimized.

FiGOBLAC commented Sep 8, 2016

@webdados looking at your gist file I believe the function you are trying to call is 'shortcode_function' so you need to change to $loader->add_action( 'init', $plugin_public, 'shortcode_function' ) You are getting the 'non-object' error because you are trying to call the loader class in a file where it doesn't exist. You don't need to use $this->loader->add_shortcode(...) unless you are using @DevinVinson method because you are already adding the shortcodes within the 'shortocde_function'.

@FiGOBLAC

This comment has been minimized.

FiGOBLAC commented Sep 8, 2016

@webdados Also your define_hooks function is not necessary so you should remove it.

@navotera

This comment has been minimized.

navotera commented Apr 21, 2017

i fix those shortcode script by this line :

 public function add_shortcode( $tag, $component, $callback, $priority = 10, $accepted_args = 1) {
        $this->shortcodes = $this->add( $this->shortcodes, $tag, $component, $callback, $priority, $accepted_args );
    }

garretthunter added a commit to garretthunter/WordPress-Plugin-Boilerplate that referenced this issue Feb 26, 2018

Added shortcode support
Started with Devin's code from DevinVinson#262 (comment)

garretthunter added a commit to garretthunter/WordPress-Plugin-Boilerplate that referenced this issue Feb 26, 2018

Added shortcode support
Based on Devin's suggestions from DevinVinson#262 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment