Get URL of any PHP file in WordPress

Getting URL of the current page or current PHP file is a very common task. And that is not exceptional in WordPress. For example: when you include a plugin in a theme or using LESS PHP compiler. There're some available techniques, but I found that all of them are not good enough to work in all situation, so I hope what I write in this post is a better approach.

Let's look at these methods before getting to the final solution:

Get current URL via $wp->request

This technique is introduced by Konstantin Kovshenin. It uses $wp->request and $wp->query_string to get current URL of a page in the front end

global $wp;
$url = add_query_arg( $wp->query_string, '', home_url( $wp->request ) );

It's good enough if you only want URL for the current page and on the front end. It doesn't help if you want to have URL to a plugin file.

An updated version of this technique by Stephen Harris:

global $wp;
$url = home_url( add_query_arg( [], $wp->request ) );

Get URL of current PHP file, common approach

There're several tutorials on the Internet about this technique, all of them are similar to this:

$is_https = isset( $_SERVER['HTTPS'] ) && ( $_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1 )
    || isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https';

$url = $is_https ? 'https://' : 'http://';
if ( $_SERVER['SERVER_PORT'] != '80' ) {
    $url .= $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
} else {
    $url .= $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}

Or the WordPress way:

$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

This also works quite well. The logic is similar to 1st method, it based on request URI, server name.

But it has only one disadvantage: this method work only with current requested PHP file. And that totally fails if you want to get URL to a plugin of WordPress (you probably never access to plugin PHP file directly, right?)

Replace WP_CONTENT_DIR by WP_CONTENT_URL

The logic is simple: all our PHP files are located in wp-content dir, thus replacing WP_CONTENT_DIR by WP_CONTENT_URL is a good hope to get correct URL:

$file = __FILE__; // Current PHP file, but can be any.
$url = str_replace( WP_CONTENT_DIR, WP_CONTENT_URL, $file );

Of course, this is very simple and works in most cases. These 2 variables are initialized when WordPress is loaded. We don't need to consider about server path, server request, query string list 1st and 2nd methods. Safe enough.

But there're 2 problems with this method:

In Windows environment, due to inconsistent of using backward slash (/) and forward slash (\) in the path by WordPress (see how it defines these constants without considering this problem), the function doesn't return correct URL.

Test code:

add_action( 'init', function () {
    $file = __FILE__;
    $url = str_replace( WP_CONTENT_DIR, WP_CONTENT_URL, $file );
    echo
        '<pre>',
        '__FILE__      : ' . $file . '<br>',
        'WP_CONTENT_DIR: ' . WP_CONTENT_DIR . '<br>',
        'WP_CONTENT_URL: ' . WP_CONTENT_URL . '<br>',
        'URL           : ' . $url . '<br>',
        '</pre>'
    ;
    die;
} );

Result:

__FILE__      : D:\Dropbox\UniServer\www\wp\wp-content\mu-plugins\test.php
WP_CONTENT_DIR: D:\Dropbox\UniServer\www\wp/wp-content
WP_CONTENT_URL: http://localhost:8080/wp/wp-content
URL           : D:\Dropbox\UniServer\www\wp\wp-content\mu-plugins\test.php

Second problem comes from Multisite environment with Domain Mapping plugin installed. Because the constant WP_CONTENT_URL is defined via function get_option( 'siteurl' ), it doesn't give you the correct URL to wp-content folder in sub-site.

Assume we have a multisite with main domain test.com, and a sub-site with domain exam.com. If we run the same test code as above, we'll see this results:

On the main site (correct):

__FILE__      : /var/home/testuser/www/test.com/wp-content/mu-plugins/test.php
WP_CONTENT_DIR: /var/home/testuser/www/test.com/wp-content
WP_CONTENT_URL: http://test.com/wp-content
URL           : http://test.com/wp-content/mu-plugins/test.php

On a sub-site (incorrect):

__FILE__      : /var/home/testuser/www/test.com/wp-content/mu-plugins/test.php
WP_CONTENT_DIR: /var/home/testuser/www/test.com/wp-content
WP_CONTENT_URL: http://test.com/exam/wp-content
URL           : http://test.com/exam/wp-content/mu-plugins/test.php

Final (working) solution:

If you run your site in Linux environment and not in Multisite mode, you can use the 3rd method above. It's short and works like a charm!

But if you want a solution that works in all situation, try this:

$file = __FILE__;

// Get correct URL and path to wp-content
$content_url = untrailingslashit( dirname( dirname( get_stylesheet_directory_uri() ) ) );
$content_dir = untrailingslashit( WP_CONTENT_DIR );

// Fix path on Windows
$file = wp_normalize_path( $file );
$content_dir = wp_normalize_path( $content_dir );

$url = str_replace( $content_dir, $content_url, $file );

Basically, this solution is an additional version of 3rd method above with 2 fixes mentioned. Please try this, and if you have any suggestion or idea, please let me know via comments!

🔥 HOT: Interested in boosting your WordPress SEO? My Slim SEO plugin is a super lighweight and automated plugin that handles most the hard work for you: meta tags, sitemap, redirection, schema & link building.

👉 Have a look and you will love it: wpslimseo.com

Leave a Reply

Your email address will not be published. Required fields are marked *


Copyright © 2024 Deluxe Blog Tips. All rights reserved.

My products: Meta Box | Slim SEO