1
\$\begingroup\$
function parse_request_uri() {
    $parts = [];

    if (array_key_exists('REQUEST_URI', $_SERVER)) {
        $request_path = explode('?', $_SERVER['REQUEST_URI']);

        $parts['base'] = rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/');
        $parts['path'] = substr(urldecode($request_path[0]), strlen($parts['base']) + 1);

        if ($parts['path'] === basename($_SERVER['PHP_SELF'])) {
            $parts['path'] = '/';
        } elseif ($parts['path'] === false) {
            $parts['path'] = '/';
        }

        $parts['path_parts'] = [];

        if ($parts['path'] !== '/') {
            $parts['path_parts'] = explode('/', $parts['path']);
        }

        if (isset($request_path[1])) {
            $parts['query_string'] = urldecode($request_path[1]);
            parse_str($parts['query_string'], $parts['query_vars']);
        }
    }

    return $parts;
}

Ideas?

Using following .htaccess:

Options +FollowSymLinks
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Examples:

URI Request: http://url/hello/world?hello=world

Results:

array(5) { 
  ["base"]=> string(0) "" 
  ["path"]=> string(11) "hello/world" 
  ["path_parts"]=> array(2) { 
    [0]=> string(5) "hello" 
    [1]=> string(5) "world" 
  } 
  ["query_string"]=> string(11) "hello=world" 
  ["query_vars"]=> array(1) { 
    ["hello"]=> string(5) "world" 
  } 
}

URI Request: http://url/index.php/hello/world?hello=world

Results:

array(5) { 
  ["base"]=> string(0) "" 
  ["path"]=> string(21) "index.php/hello/world" 
  ["path_parts"]=> array(3) { 
    [0]=> string(9) "index.php" 
    [1]=> string(5) "hello" [2]=> string(5) "world" 
  } 
  ["query_string"]=> string(11) "hello=world" 
  ["query_vars"]=> array(1) { 
    ["hello"]=> string(5) "world" 
  } 
}

Not sure if index.php actually should show up there as it is the file name the function is called in?

URI Request: http://url/index.php/hello/world/?hello=world

Results:

array(5) { 
  ["base"]=> string(0) "" 
  ["path"]=> string(22) "index.php/hello/world/" 
  ["path_parts"]=> array(4) { 
    [0]=> string(9) "index.php" 
    [1]=> string(5) "hello" 
    [2]=> string(5) "world" 
    [3]=> string(0) ""
  } 
  ["query_string"]=> string(11) "hello=world" 
  ["query_vars"]=> array(1) { 
    ["hello"]=> string(5) "world" 
  } 
}

The fourth element in parts should probably not be there?

Do you have any ideas on how I can improve the code (make it shorter) and remove the obvious flaws mentioned above or any other ideas you have?

\$\endgroup\$
1
  • \$\begingroup\$ Removing flaws is not what we do here, if the code doesn't work the way that you want it to, then it is considered broken, get those fixed and bring the code back for review \$\endgroup\$
    – Malachi
    Commented Sep 23, 2014 at 14:46

1 Answer 1

2
\$\begingroup\$

Ask what you need

Your function is useless. It can only parse the $_SERVER['REQUEST_URI'] uri. why? simply have the uri as a parameter for the function.

URI or URL?

You actually expect an URL (subpart of URI). Every URL is a URI, but not every URI is a URL. ISBN numbers for instance are URI's but not URLS ;)

Use built in functions

PHP has a really nifty parse_url function. Use it ;) It does nearly the exact same things as your function.

The only thing you add is you split the path and arguments up into an array.

So lets' fix that

function parse_request_url($url)
{
    $parsedUri = parse_url($url);

    //split the path into an array
    //we trim here to get rid of empty path ("")
    $parsedUri['path'] = explode('/', trim($parsedUri,'/'));

    //split query string
    $query = explode('&',$parsedUri['query']);
    $parsedQuery = array();
    foreach ( $query as $q ) {
        list($key,$value) = explode('=',$q);
        $parsedQuery[$key] = $value;
    }
    $parsedUri['query'] = $parsedQuery;

    return $parsedUri;
}

Note: this code is not tested, so could be buggy ;) But you get the idea

\$\endgroup\$
2
  • \$\begingroup\$ This doesn't take base path under consideration as well as it has its flaws,but thanks for the help, theres definitely improvements i can make \$\endgroup\$ Commented Sep 23, 2014 at 15:45
  • \$\begingroup\$ Removing the base path is something you could add with a ltrim. I would even do that outside of the function call. Functions shouldn't be all knowing ;) \$\endgroup\$
    – Pinoniq
    Commented Sep 24, 2014 at 9:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.