When I develop plugins I test them on multiple versions of WordPress by symlinking my plugin directory in the different wp-content
directories. This is great since I only have to edit the files once, but it breaks an important construct to generate references to resources in my plugin: __FILE__
refers to the physical plugin location, not the one in wp-content
. How should I solve this?
My directory structure looks like this:
/path/to/wordpress/development/dir/
plugin-development/
monkeyman-rewrite-analyzer/
monkeyman-rewrite-analyzer.php
js/
monkeyman-rewrite-analyzer.js
versions/
3.1/
wp-content/
plugins/
monkeyman-rewrite-analyzer
as a symlink to the above plugin
3.1-multi-dir/
wp-content/
plugins/
monkeyman-rewrite-analyzer
as a symlink to the above plugin
3.1-multi-domain/
wp-content/
plugins/
monkeyman-rewrite-analyzer
as a symlink to the above plugin
If I want to enqueue the Javascript file, I should use plugins_url( 'monkeyman-rewrite-analyzer.js', [base file] )
, but using __FILE__
here will not work, because the actual file path will be /path/to/wordpress/development/dir/plugin-development/monkeyman-rewrite-analyzer/monkeyman-rewrite-analyzer.php
, not /path/to/wordpress/development/dir/versions/*/wp-content/plugins/monkeyman-rewrite-analyzer/monkeyman-rewrite-analyzer.php
, so WordPress cannot strip the first part out and generate a URL relative to the WordPress installation.
The problem can partially be addressed with a must-use plugin hooking into the
plugins_url
filter.It won’t handle all other cases where
plugin_basename()
is used, such asregister_activation_hook()
and co.More info: http://core.trac.wordpress.org/ticket/16953
I currently use a trick to get the WordPress-relative file location:
wp_get_active_and_valid_plugins()
returns the file paths, andwp_settings.php
loops over them and includes the files. So the global$plugin
variable will refer to your current plugin (of course only when the plugin is loaded, so I save it in a prefixed global variable):Because plugins can also be loaded as must-use or network plugins and these loops use other variable names, the complete code looks like this:
The fallback is still
__FILE__
, so if someone changes the loop variable name in the future my code should still work for 99% of all installations, only my development setup will fail and I can release a new version with ease.A comment in bug 46260 suggests to use
$_SERVER["SCRIPT_FILENAME"]
instead of__FILE__
. Does this work?$_SERVER["SCRIPT_FILENAME"]
works if you use it right. You just have to use it to set a base path, and then include your files using a path relative to that base path.Something like:
Note, this is more useful when you don’t have access to wp-blog-header.php yet (i.e. in processing an ajax-based form request)