0

This sounds like a silly problem, but I was searching for an answer, and couldn't find anything. And the things that I did find, I tried and didn't work or were very vague.

Content

  • My Problem
  • What I tried
  • What to do?
  • FIXED

My problem

I am building a plugin, where you can use a shortcode. I added the shortcode and build my markup. Outputting the shortcode inside a blog post works great. When I had my styles and scripts inside the markup, it also works. Now I want to have them separated, each in their own file.
I have one folder for all my shortcode related functions and files, so I don't need to leave the folder to get my styles.css or my scripts.js.
I tried linking to them with various attempts, and nothing seems to work.

What I tried

Using the basic <link> and <script> tag to link to the files inside the markup, obviously didn't work.

Inside the file where I'm initialising my shortcode:

add_action( "wp_enqueue_scripts", "registerScriptsStyles" );

public function registerScriptsStyles() {
    wp_register_script( 'iw_ShortcodeScript', plugins_url("ShortcodeScript.js", __FILE__ ), "", "1.0.1", true );
    wp_register_style( 'iw_ShortcodeStyle', plugins_url("ShortcodeStyle.css", __FILE__ ), "", "1.0.1" );
    wp_enqueue_script( 'iw_ShortcodeScript' );
    wp_enqueue_style( 'iw_ShortcodeStyle' );
  }

Didn't work. So I tried

add_action( "init", "registerScriptsStyles" );
add_action( "wp_qneueue_scripts", "enqueueScriptsStyles" );

public function registerScriptsStyles() {
    wp_register_script( 'iw_ShortcodeScript', plugins_url("ShortcodeScript.js", __FILE__ ), "", "1.0.1", true );
    wp_register_style( 'iw_ShortcodeStyle', plugins_url("ShortcodeStyle.css", __FILE__ ), "", "1.0.1" );
  }

  
  public function enqueueScriptsStyles() {
    wp_enqueue_script( 'iw_ShortcodeScript' );
    wp_enqueue_style( 'iw_ShortcodeStyle' );
  }

Also didn't work.

I read somewhere, that I need to enqueue them inside the page where I want them, so I tried enqueueing them inside the markup for the shortcode, which also didn't work.

Next, I tried enqueueing them inside the function where I am requiring my shortcode.

add_shortcode(  "Info_Wheel", array(  $this,  "layout"  )  );

public  function  layout()  {
    wp_enqueue_script(  'iw_ShortcodeScript'  );
    wp_enqueue_style(  'iw_ShortcodeStyle'  );
    require  $this->iw_plugin_path .  "/Blocks/Pages/ShortcodeAPI/ShortcodeLayout.php";
}

Also didn't work.

What to do?

I can't seem to find a solution to what I want. I must obviously do something wrong, but what is it? Reading the documentaion didn't help, as they're too vague for this, in my opinion.

And again, the shortcode works and is being displayed, the only problem is with the Styles and Scripts not being loaded. Below is my current Code in my editor for the Shortcode API.
If anyone could help me out, that would be great.

<?php

namespace Blocks\Pages\ShortcodeAPI;
use Blocks\Base\Controller;

class  Shortcode  extends  Controller  {
    public  function  register()  {
        add_action(  "init",  "registerScriptsStyles"  );
        // add_action( "wp_qneueue_scripts", "enqueueScriptsStyles" );
        add_shortcode(  "Info_Wheel", array(  $this,  "layout"  )  );
    }

    public  function  layout()  {
        wp_enqueue_script(  'iw_ShortcodeScript'  );
        wp_enqueue_style(  'iw_ShortcodeStyle'  );
        require  $this->iw_plugin_path .  "/Blocks/Pages/ShortcodeAPI/ShortcodeLayout.php";
    }

    public  function  registerScriptsStyles()  {
        wp_register_script(  'iw_ShortcodeScript', plugins_url("ShortcodeScript.js",  __FILE__  ),  "",  "1.0.1",  true  );
        wp_register_style(  'iw_ShortcodeStyle', plugins_url("ShortcodeStyle.css",  __FILE__  ),  "",  "1.0.1"  );
    }
    
    public  function  enqueueScriptsStyles()  {
        wp_enqueue_script(  'iw_ShortcodeScript'  );
        wp_enqueue_style(  'iw_ShortcodeStyle'  );
    }
}

FIXED

This is what I have done to fix this, like it was already suggested in the comments of the answer. Another thing that no one noticed until just a few moments ago, I mistyped enqueue in the hook. You can still see it above.
All of the code is inside my Shortcode.php file.

 class Shortcode extends Controller {

  public function register() {
    add_action( "wp_enqueue_scripts", array($this, "registerScriptsStyles" ) );
    add_action( "wp_enqueue_scripts", array($this, "enqueueScriptsStyles" ) );
    add_shortcode( "Info_Wheel", array( $this, "layout" ) );
  }

  public function layout() : string {
    ob_start();
    require $this->iw_plugin_path . "/Blocks/Pages/ShortcodeAPI/ShortcodeLayout.php";
    return ob_get_clean();
  }

  public function registerScriptsStyles() {
    wp_register_script( 'iw_ShortcodeScript', plugins_url( "/Blocks/Pages/ShortcodeAPI/ShortcodeScript.js", $this->iw_plugin_path . "Info-Wheel.php"), array(), "1.0.1", true);
    wp_register_style( 'iw_ShortcodeStyle', plugins_url( "/Blocks/Pages/ShortcodeAPI/ShortcodeStyle.css", $this->iw_plugin_path . "Info-Wheel.php"), array(), "1.0.1");
  }

  public function enqueueScriptsStyles() {
    wp_enqueue_script( 'iw_ShortcodeScript' );
    wp_enqueue_style( 'iw_ShortcodeStyle' );
  }
 }

1 Answer 1

1

plugins_url expects the second parameter to be the main plugin file, which is why __FILE__ is used in examples, it's assuming the code is in that file, but yours is not.

To fix this, you will need to retrieve __FILE__ in your main plugin file, store it, and pass it to your shortcode objects for use in plugins_url

There is also another major problem you're unaware of

Shortcodes return their content as a string, but you've output the content directly. This breaks a lot of things because now the shortcode is output when it's processed, not when it's displayed.

This breaks a lot of things:

  • nested shortcodes
  • XMLRPC
  • any code that relies on the rendered content or the_content filter
  • Some REST API endpoints
  • Possibly even RSS feeds and some plugin sitemaps
  • Lots of things plugins and themes do

A classic sign that a plugin/theme is doing this is when shortcodes appear before the content regardless of where they were placed, or shortcodes appearing in the wrong order.

You can fix this though by using an output buffer to catch the output and assign it to a variable.

I would recommend changing your function signature to include the string return type. Doing this means it will create a PHP fatal error if your shortcode is built incorrectly ( and your shortcode is built incorrectly ):

public function layout() : string {
6
  • 1. The shortcode file is inside thisfolder: MyPlugin\Blocks\Pages\ShortcodeAPI\Shortcode.php Inside MyPLugin is MyPlugin.php. So does this mean, __FILE__ has to be the name of the main file, or would be the root enough? 2. I now wrote php public function layout() : string { ob_start(); require $this->iw_plugin_path . "URL"; return ob_get_clean(); } That should be correct, then. Nov 27, 2020 at 11:49
  • So I now use the correct pathing for wp_register_script/style(), but it still doesn't do anything. Where do I write code so the style is being loaded? Nov 27, 2020 at 12:28
  • it has to be the main plugin PHP file, aka the file with the plugin header at the top that WP loads first. Note that this is assuming your plugin is a PHP file in a subfolder e.g. wp-content/plugins/yourplugin/plugin.php. If your plugin is a file in the plugins folder that loads more files from a subfolder then that needs changing as the plugin folder structure is incorrect. As for your shortcode, that looks better
    – Tom J Nowell
    Nov 27, 2020 at 13:01
  • How is the plugin folder structure wrong? I'm using OOP. Inside my Ìnfo-Wheel.php file I run a class function from Init:: register_services(), which runs all of the needed functions for my plugin. Everything works, besides having to figure out how to load the CSS/JS file. Here is an image to my folder structure. I tried running the add_action(), to enqueue my files, but still nothing. Nov 27, 2020 at 13:13
  • 1
    Tom's saying if your main plugin file was in the general plugins directory it would be incorrect - but your file structure does not meet this description. The path in plugins_url() needs to reference the main loaded plugin file. In this case, from the Shortcode.php file, that might look like plugins_url( 'Blocks/Pages/ShortcodeApi/ShortcodeScript.js', dirname( dirname( __DIR__ ) ) . '/Info-Wheel.php' ). Or you could expose Info-Wheel.php's path in a property or function, or pass it into the classes it constructs, etc.
    – bosco
    Nov 27, 2020 at 14:27

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.