Getting the “after root URL” with PHP

jkon 2 Tallied Votes 663 Views Share

I found myself starting to answer a question that I have answered many times , so I thought why not making a code snippet and just reference this.

This is a short code snippet only to demonstrate how this thing work (with apache and rewrite engine on) , in real life PHP code shouldn't be under the public_html / www folder in any case (with maybe only one exception a index.php that its main task is to include something (or instantiate a class) from the src folder)

Lets suppose that you have an example folder under the domain example.com , you have some urls
eg1: http://example.com/example?var=value (this in this approach is equivalent to http://example.com/example/?var=value)
eg2: http://example.com/example/threadName/topicName

and you want to get the ?var=value or threadName/topicName or what ever after the http://example.com/example/ part. This is a very common senario that I have seen in many variations.

So lets do it:
Under the example directory we have an .htaccess file

DirectoryIndex index.php RewriteEngine On RewriteCond %{ENV:URI} ^$ RewriteRule ^(.*)$ - [ENV=URI:$1] RewriteCond %{ENV:BASE} ^$ RewriteCond %{ENV:URI}::%{REQUEST_URI} ^(.*)::(.*?)\1$ RewriteRule ^ - [ENV=BASE:%2] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule .* %{ENV:BASE}index.php [QSA,L]

And an index.php file :

<?php error_reporting( E_ALL ); ini_set( 'display_errors' ,'1' ); // set UTF-8 encoding mb_internal_encoding( "UTF-8" ); // eg1: lets suppose that your domain is http://example.com // and that we (the .htaccess file and this index.php) is under the // example directory $protocol = StringUtils::beforeFirst( $_SERVER["SERVER_PROTOCOL"] ,"/" ) . ( empty( $_SERVER["HTTPS"] ) ? '' : ( $_SERVER["HTTPS"] == "on" ) ? "s" : "" ); // The protocol part , eg1 > http $httpHost = isset( $_SERVER["HTTP_HOST"] ) ? trim( $_SERVER["HTTP_HOST"] ,"/" ) : null; // the host , eg1 > example.com $phpSelf = $_SERVER["PHP_SELF"]; // the normal current url of the index.php // , eg1 > http://example.com/example/index.php $rootUrl = StringUtils::toLowerCase( $protocol ) . "://" . $httpHost . StringUtils::beforeLast( $phpSelf ,"/" ); // The rootUrl (where the htaccess is) , eg1 > http://example.com/example $fullRequestUri = StringUtils::toLowerCase( $protocol ) . "://" . $httpHost . $_SERVER["REQUEST_URI"]; // The fullRequestedUrl (including the ? if is any or any other after // slashes. eg1 > http://example.com/example/example/?var=value // or eg1> http://example.com/example/action?var=value // or anything $afterRootUrl = StringUtils::afterFirst( StringUtils::toLowerCase( $protocol ) . "://" . $httpHost . $fullRequestUri , $rootUrl . "/" ); // The after root url , eg1 > action?var=value // Now you have the after root Url and you can do what ever you like // to it echo $afterRootUrl; /** * StringUtils class contains static methods for common string * operations * * @version THIS IS A MINIFIED VERSION having only the methods I need * for this code snippet */ class StringUtils { /** * Returns how many characters the string is * * @param <b>string $string</b> * The string * @return number */ public static function length($string) { return mb_strlen( $string ); } /** * Counts the occurrences of a string inside another string and returns * the result * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if will be * case sensitive. By default true. * @return number */ public static function count($string ,$search ,$caseSensitive = true) { return $caseSensitive ? mb_substr_count( $string ,$search ) : mb_substr_count( self::toLowerCase( $string ) ,self::toLowerCase( $search ) ); } /** * Return the index of <b>the first occurance</b> of a part of a * string to the string * * @param <b>string $string</b> * The string to be searched * @param <b>string $search * string</b> The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if will * be case sensitive. By default true. * @return number */ public static function firstIndexOf($string ,$search ,$caseSensitive = true) { return $caseSensitive ? mb_strpos( $string ,$search ) : mb_stripos( $string , $search ); } /** * Return the index of <b>the last occurance</b> of a part of a string * to the string * * @param * <b>$string string</b> The string to be searched * @param * <b>$search string</b> The string to search for * @param * <b>$caseSensitive boolean :optional</b> Defines if the search * will be case sensitive. By default true. * @return number */ public static function lastIndexOf($string ,$search ,$caseSensitive = true) { return $caseSensitive ? mb_strrpos( $string ,$search ) : mb_strripos( $string ,$search ); } /** * Converts a string to lower case * * @param <b>string $string</b> * The sting to be converted * @return string */ public static function toLowerCase($string) { return mb_strtolower( $string ); } /** * Returns a part of the string from a character and for as many * characters as provided * * @param * <b>$string string</b> The string to retrieve the part from * @param * <b>$start string </b> The index of the first character * (0 for the first one) * @param * <b>$length string</b> The length of the part the will be * extracted from the string * @return string */ public static function substring($string ,$start ,$length = null) { return ( $length === null ) ? ( mb_substr( $string ,$start ) ) : ( $length == 0 ? "" : mb_substr( $string ,$start ,$length ) ); } /** * Returns the part of a string <b>before the first</b> occurrence of * the string to search for. * If the string doesn't contain the needle returns the string itself * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if the search * will be case sensitive. By default true. * @return string */ public static function beforeFirst($string ,$search ,$caseSensitive = true) { return self::count( $string ,$search ,$caseSensitive ) === 0 ? $string : self::substring($string ,0 ,self::firstIndexOf( $string ,$search ,$caseSensitive ) ); } /** * Returns the part of a string <b>before the last</b> occurrence of * the string to search for. * If the string doesn't contain the needle returns the string itself * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param * <b>$caseSensitive boolean :optional</b> Defines if the * search will be case sensitive. By default true. * @return string */ public static function beforeLast($string ,$search ,$caseSensitive = true) { return self::count( $string ,$search ,$caseSensitive ) === 0 ? $string : self::substring( $string ,0 ,self::lastIndexOf( $string ,$search ,$caseSensitive ) ); } /** * Returns the part of a string <b>after the first</b> occurrence of the * string to search for. * If the string doesn't contain the needle returns an empty string * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if the search * will be case sensitive. By default true. * @return string */ public static function afterFirst($string ,$search ,$caseSensitive = true) { return self::count( $string ,$search ,$caseSensitive ) === 0 ? "" : self::substring( $string , self::firstIndexOf( $string ,$search ,$caseSensitive ) + self::length( $search ) ); } } ?>

And we are done , now you have the after root url in the $afterRootUrl variable and you can do what ever you like with it.

cereal commented: thanks for sharing! :)+14
diafol commented: always a joy to read your snippets. Thanks jkon+14
<?php error_reporting( E_ALL ); ini_set( 'display_errors' ,'1' ); // set UTF-8 encoding mb_internal_encoding( "UTF-8" ); // eg1: lets suppose that your domain is http://example.com // and that we (the .htaccess file and this index.php) is under the // example directory $protocol = StringUtils::beforeFirst( $_SERVER["SERVER_PROTOCOL"] ,"/" ) . ( empty( $_SERVER["HTTPS"] ) ? '' : ( $_SERVER["HTTPS"] == "on" ) ? "s" : "" ); // The protocol part , eg1 > http $httpHost = isset( $_SERVER["HTTP_HOST"] ) ? trim( $_SERVER["HTTP_HOST"] ,"/" ) : null; // the host , eg1 > example.com $phpSelf = $_SERVER["PHP_SELF"]; // the normal current url of the index.php // , eg1 > http://example.com/example/index.php $rootUrl = StringUtils::toLowerCase( $protocol ) . "://" . $httpHost . StringUtils::beforeLast( $phpSelf ,"/" ); // The rootUrl (where the htaccess is) , eg1 > http://example.com/example $fullRequestUri = StringUtils::toLowerCase( $protocol ) . "://" . $httpHost . $_SERVER["REQUEST_URI"]; // The fullRequestedUrl (including the ? if is any or any other after // slashes. eg1 > http://example.com/example/example/?var=value // or eg1> http://example.com/example/action?var=value // or anything $afterRootUrl = StringUtils::afterFirst( StringUtils::toLowerCase( $protocol ) . "://" . $httpHost . $fullRequestUri , $rootUrl . "/" ); // The after root url , eg1 > action?var=value // Now you have the after root Url and you can do what ever you like // to it echo $afterRootUrl; /** * StringUtils class contains static methods for common string * operations * * @version THIS IS A MINIFIED VERSION having only the methods I need * for this code snippet */ class StringUtils { /** * Returns how many characters the string is * * @param <b>string $string</b> * The string * @return number */ public static function length($string) { return mb_strlen( $string ); } /** * Counts the occurrences of a string inside another string and returns * the result * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if will be * case sensitive. By default true. * @return number */ public static function count($string ,$search ,$caseSensitive = true) { return $caseSensitive ? mb_substr_count( $string ,$search ) : mb_substr_count( self::toLowerCase( $string ) ,self::toLowerCase( $search ) ); } /** * Return the index of <b>the first occurance</b> of a part of a * string to the string * * @param <b>string $string</b> * The string to be searched * @param <b>string $search * string</b> The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if will * be case sensitive. By default true. * @return number */ public static function firstIndexOf($string ,$search ,$caseSensitive = true) { return $caseSensitive ? mb_strpos( $string ,$search ) : mb_stripos( $string , $search ); } /** * Return the index of <b>the last occurance</b> of a part of a string * to the string * * @param * <b>$string string</b> The string to be searched * @param * <b>$search string</b> The string to search for * @param * <b>$caseSensitive boolean :optional</b> Defines if the search * will be case sensitive. By default true. * @return number */ public static function lastIndexOf($string ,$search ,$caseSensitive = true) { return $caseSensitive ? mb_strrpos( $string ,$search ) : mb_strripos( $string ,$search ); } /** * Converts a string to lower case * * @param <b>string $string</b> * The sting to be converted * @return string */ public static function toLowerCase($string) { return mb_strtolower( $string ); } /** * Returns a part of the string from a character and for as many * characters as provided * * @param * <b>$string string</b> The string to retrieve the part from * @param * <b>$start string </b> The index of the first character * (0 for the first one) * @param * <b>$length string</b> The length of the part the will be * extracted from the string * @return string */ public static function substring($string ,$start ,$length = null) { return ( $length === null ) ? ( mb_substr( $string ,$start ) ) : ( $length == 0 ? "" : mb_substr( $string ,$start ,$length ) ); } /** * Returns the part of a string <b>before the first</b> occurrence of * the string to search for. * If the string doesn't contain the needle returns the string itself * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if the search * will be case sensitive. By default true. * @return string */ public static function beforeFirst($string ,$search ,$caseSensitive = true) { return self::count( $string ,$search ,$caseSensitive ) === 0 ? $string : self::substring($string ,0 ,self::firstIndexOf( $string ,$search ,$caseSensitive ) ); } /** * Returns the part of a string <b>before the last</b> occurrence of * the string to search for. * If the string doesn't contain the needle returns the string itself * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param * <b>$caseSensitive boolean :optional</b> Defines if the * search will be case sensitive. By default true. * @return string */ public static function beforeLast($string ,$search ,$caseSensitive = true) { return self::count( $string ,$search ,$caseSensitive ) === 0 ? $string : self::substring( $string ,0 ,self::lastIndexOf( $string ,$search ,$caseSensitive ) ); } /** * Returns the part of a string <b>after the first</b> occurrence of the * string to search for. * If the string doesn't contain the needle returns an empty string * * @param <b>string $string</b> * The string to be searched * @param <b>string $search</b> * The string to search for * @param <b>boolean $caseSensitive * :optional</b> Defines if the search * will be case sensitive. By default true. * @return string */ public static function afterFirst($string ,$search ,$caseSensitive = true) { return self::count( $string ,$search ,$caseSensitive ) === 0 ? "" : self::substring( $string , self::firstIndexOf( $string ,$search ,$caseSensitive ) + self::length( $search ) ); } } ?>
jkon672 Posting Whiz in Training Featured Poster

Of course if there is a chance to have special UTF8 characters (e.g. spaces or non Latin letters) in URL you should url decode the $afterRootUrl

$afterRootUrl = urldecode($afterRootUrl);
Member Avatar for cereal
cereal1,524 Nearly a Senior Poster Featured Poster

Hi,

so it's like the parse_url() function, correct?

jkon672 Posting Whiz in Training Featured Poster

Hello cereal ,
Well actually it is not like parse_url , lets see an example but many more can be made,

Lets say that you have this .htaccess and this index.php in http://example.com/article
and the url is http://example.com/article/Weather/the-most-hot-year there is no way parse_url can tell you that the after root (the current folder where .htaccess and index.php is) is http://example.com/article and the after Root url Weather/the-most-hot-year.

cereal commented: perfectly clear, thanks for the explanation+14
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.

close