A PHP function that prints the url based on path I'm trying to come up with a smart wordpress inspired PHP function that builds an url for my CMS. It has some different requirements that are almost all fulfilled so far.


Must use correct domain
Must be able to use subfolder (Eg. /blog/index.php)
Must be able to specify protocol (if http or https)
Must accept queries (Eg. ?sort=date)


The purpose is to make it easier to print urls when developing through my site so that I don't have to type the whole url myself. It's also so the CMS can run on as many different websites as possible, both with subfolders and without.

My code so far:

function _url( $path = null, $args = "" ) {

    $protocol = "http";

    if ( isset($_SERVER['HTTP_HOST']) &amp;&amp; !empty($_SERVER['HTTP_HOST']) ) {
        $domain = $_SERVER['HTTP_HOST'];
    } else {
        $domain = $_SERVER['SERVER_NAME'];
    }

    if ( isset($_SERVER['HTTPS']) ) {
        $protocol = ($_SERVER['HTTPS'] &amp;&amp; $_SERVER['HTTPS'] != "off") ? "https" : "http";
    }

    if ( isset($_SERVER['PHP_SELF']) &amp;&amp; strlen(dirname($_SERVER['PHP_SELF'])) &gt; 1 ) {
        $subfolder = dirname($_SERVER['PHP_SELF']);
    } else {
        $subfolder = "";
    }

    if ( !$path ) {
        $path = str_replace( $subfolder, "", strtok($_SERVER["REQUEST_URI"],'?') );
    }

    $url = $protocol . "://" . $domain . $subfolder . $path . $args;

    return $url;
}


An example of use:

// A website where the domain is http://domain.com
echo _url( "/about.php" );

// A website where the domain path is https://domain.com/blog/
echo _url( "/users.php", "?sort=date");


Which prints:


http://domain.com/about.php
https://domain.com/blog/users.php?sort=date


I'm pretty satisfied so far with my code. But I'm 100% sure that there is a smarter way. I tried to dig out the functions that wordpress use, but I couldn't figure it out.

Any help or proposals are appreciated. I hope it makes sense.
I am not sure that $_SERVER['SERVER_NAME'] would be a valuable fallback for $_SERVER['HOST_NAME'] as this can be really any arbitrary string.
Keep your 'protocol' portion of code together.  Also you can streamline conditional for https case.


Example:

$protocol = 'http';
if (!empty($_SERVER['HTTPS']) &amp;&amp; $_SERVER['HTTPS'] === "on") {
    $protocol = 'https';
};


You could also simplify here and just eliminate this https check if you simply build your URL string like //domain.com/uri with no protocol shown.  This would mimic current behavior of simply continuing current protocol.  You might consider adding parameter to force http vs. https if you ever need to move between the two protocols. 


It does not make sense to me why the path of the currently executing script or the current request URI would have anything to do with formulating the URI portion of the URL when this URI value is being explicitly passed in as a parameter to this function.
I do not follow the logic on the null use case for URI.  Why would this case exist?  Is this just to link a page to itself?
You should add validation around parametric input.  In this case, I would guess you need to validate URI as null or non-zero-length string. You might need to validate that that $args is empty string or starts with ?.