In WordPress, you can get the URL of any PHP file – Speedlink3 Communication And Technologies
WordPress

In WordPress, you can get the URL of any PHP file

Obtaining the URL of the current page or PHP file is a common task. That is not unusual in WordPress. For example, when including a plugin in a theme or when using the LESS PHP compiler. There are some techniques available, but I discovered that none of them are good enough to work in all situations, so I hope what I write in this post is a better approach.

Before we get to the final solution, let’s take a look at these methods:

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

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

It’s sufficient if you only need the URL for the current page and the front end. It’s useless if you want a URL to a plugin file.

Stephen Harris’s updated version of this technique:

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

2. 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:

$url = @$_SERVER['HTTPS'] == 'on' ? '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 in WordPress way:

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

This is also quite effective. The logic is similar to the first method in that it is based on the request URI and server name.

However, there is one drawback: this method only works with the currently requested PHP file. And that completely fails if you want to get the URL to a WordPress plugin (you probably never access the plugin PHP file directly, right?)

3. 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 anyone
$url = str_replace( WP_CONTENT_DIR, WP_CONTENT_URL, $file );

Of course, this is very simple and effective in the majority of cases. When WordPress is loaded, these two variables are set. The first and second methods do not require us to consider the server path, server request, or query string list. Enough to be safe.

However, there are two issues 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
  • The second issue stems from a Multisite environment with the 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 the primary domain test.com and a subdomain exam.com. If we run the same test code as before, we get the following 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

4. Final (working) solution:

If you run your site on Linux and not in Multisite mode, you can use the third method described above. It’s short and to the point!

However, if you want a solution that will work in any 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 );

Essentially, this solution is a modified version of the third method mentioned above, with two fixes. Please give this a shot, and if you have any suggestions or ideas, please share them in the comments!

Leave a Reply

Back to top button