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 {