Skip to content
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 · 35 comments
Closed

How to add public shortcodes #262

tprinty opened this issue Feb 5, 2015 · 35 comments

Comments

@tprinty
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

@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
Copy link

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

@thewebsitedev
Copy link

@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
Copy link

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
Copy link
Owner

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
Copy link

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

@slushman
Copy link

@ 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
Copy link
Owner

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

@jg314
Copy link

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
Copy link

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

@georgelouk
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link
Owner

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
Copy link

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
Copy link

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
Copy link
Contributor

I add mine via the loader as well.

@rvarbanov
Copy link

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
Copy link

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
Copy link

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

LOL

@sftranna
Copy link

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
Copy link

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
Copy link

@slushman
Copy link

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
Copy link

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 💯

@ghost ghost mentioned this issue Sep 2, 2016
@webdados
Copy link

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
Copy link

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
Copy link

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
Copy link

FiGOBLAC commented Sep 8, 2016

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

@navotera
Copy link

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
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
Based on Devin's suggestions from DevinVinson#262 (comment)
@kumarrahul-rkv
Copy link

@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.

It worked for me

@shara94
Copy link

shara94 commented Feb 27, 2022

Hello. I have a problem with elementor.

When I create a new Shortcode.

I have defined Protected $shortcode and public function shortcode() in loader, how was written here.

Usually, Shortcode works, but when I insert it with elementor and when I edit this page again, elementor says error: Session expired

https://image.prntscr.com/image/ajXgmN4qS72U0hmfclQdCA.png

how can I solve this problem?

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests