I already have a routing method that matches this pattern:
/hello/:name
that set name to be a dynamic path, I want to know how to make it:
/hello/{name}
with the same regex. How to add optional trailing slash to it, like this?
/hello/:name(/)
or
/hello/{name}(/)
This is the regex I use for /hello/:name
#^/hello/([a-zA-Z0-9\-\_]+)$#D
The regex is auto generated from PHP class
private function getRegex($pattern){
$patternAsRegex = "#^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($pattern)) . "$#D";
return $patternAsRegex;
}
If the route is /hello/:name(/) I want it to make the match with optional thing else continue normal
This will create a regular expression for the $pattern route with both :name and {name} parameters, as well as the optional slash. As a bonus, it will also add a ?<name> to make the parameter easier to handle down the line.
For example, a route pattern of /hello/:name(/) will get the regular expression #^/hello/(?<name>[a-zA-Z0-9\_\-]+)/?$#D. When matched with a URL, like preg_match( <regex above>, '/hello/sarah', $matches) that would give you $matches['name'] == 'sarah'.
There are some tests to be found below the actual function.
function getRegex($pattern){
if (preg_match('/[^-:\/_{}()a-zA-Z\d]/', $pattern))
return false; // Invalid pattern
// Turn "(/)" into "/?"
$pattern = preg_replace('#\(/\)#', '/?', $pattern);
// Create capture group for ":parameter"
$allowedParamChars = '[a-zA-Z0-9\_\-]+';
$pattern = preg_replace(
'/:(' . $allowedParamChars . ')/', # Replace ":parameter"
'(?<$1>' . $allowedParamChars . ')', # with "(?<parameter>[a-zA-Z0-9\_\-]+)"
$pattern
);
// Create capture group for '{parameter}'
$pattern = preg_replace(
'/{('. $allowedParamChars .')}/', # Replace "{parameter}"
'(?<$1>' . $allowedParamChars . ')', # with "(?<parameter>[a-zA-Z0-9\_\-]+)"
$pattern
);
// Add start and end matching
$patternAsRegex = "#^" . $pattern . "$#D";
return $patternAsRegex;
}
// Test it
$testCases = [
[
'route' => '/hello/:name',
'url' => '/hello/sarah',
'expectedParam' => ['name' => 'sarah'],
],
[
'route' => '/bye/:name(/)',
'url' => '/bye/stella/',
'expectedParam' => ['name' => 'stella'],
],
[
'route' => '/find/{what}(/)',
'url' => '/find/cat',
'expectedParam' => ['what' => 'cat'],
],
[
'route' => '/pay/:when',
'url' => '/pay/later',
'expectedParam' => ['when' => 'later'],
],
];
printf('%-5s %-16s %-39s %-14s %s' . PHP_EOL, 'RES', 'ROUTE', 'PATTERN', 'URL', 'PARAMS');
echo str_repeat('-', 91), PHP_EOL;
foreach ($testCases as $test) {
// Make regexp from route
$patternAsRegex = getRegex($test['route']);
if ($ok = !!$patternAsRegex) {
// We've got a regex, let's parse a URL
if ($ok = preg_match($patternAsRegex, $test['url'], $matches)) {
// Get elements with string keys from matches
$params = array_intersect_key(
$matches,
array_flip(array_filter(array_keys($matches), 'is_string'))
);
// Did we get the expected parameter?
$ok = $params == $test['expectedParam'];
// Turn parameter array into string
list ($key, $value) = each($params);
$params = "$key = $value";
}
}
// Show result of regex generation
printf('%-5s %-16s %-39s %-14s %s' . PHP_EOL,
$ok ? 'PASS' : 'FAIL',
$test['route'], $patternAsRegex,
$test['url'], $params
);
}
Output:
RES ROUTE PATTERN URL PARAMS
-------------------------------------------------------------------------------------------
PASS /hello/:name #^/hello/(?<name>[a-zA-Z0-9\_\-]+)$#D /hello/sarah name = sarah
PASS /bye/:name(/) #^/bye/(?<name>[a-zA-Z0-9\_\-]+)/?$#D /bye/stella/ name = stella
PASS /find/{what}(/) #^/find/(?<what>[a-zA-Z0-9\_\-]+)/?$#D /find/cat what = cat
PASS /pay/:when #^/pay/(?<when>[a-zA-Z0-9\_\-]+)$#D /pay/later when = later
Simply replace your regex with this for optional / :
#^/hello/([a-zA-Z0-9-_]+)/?$#
Related
So I'm trying to make this little script work for fun and just cant get it to work,
I have an array of random names that are assigned their 'random' email addresses, I want to check if the email address have extension:
'#hotmail.com',
'#hotmail.ca', or
'#yahoo.ca' . if they are then echo something like 'Daniel, your email addresses extension is $extension, you qualify'
and if they don't just say 'Kayla, your email address is $extension, you don't qualify.
I want to add a foreach statement explaining that for each person in the array $ClassRoom2, i've tried using strstr() but it doesn't work inside the foreach because it can only have one string.
heres what i got so far:
qualify = "";
$ClassRoom2 = array(
'Daniel' => 'fresco#hotmail.com',
'Mike' => 'dkoko#yahoo.ca',
'Meranda' => 'brunnn_23#hotmail.ca',
'Will' => 'yumyum03#wp.pl',
'Brittey' => 's0sd#outlook.com',
'Kayla' => 'hocklife#freebie.com' );
switch ($ClassRoom2) {
case '#hotmail.com':
echo 'You are using extension '. $final; $qualify = 1; break;
case '#hotmail.ca':
echo 'You are using extension '. $final; $qualify = 1; break;
case '#yahoo.com':
echo 'You are using extension '. $final; $quality = 1; break;
case '#yahoo.ca':
echo 'You are using extension '. $final; $qualify = 1; break;
case '#live.ca':
echo 'You are using extension '. $final; $quality = 1; break;
default:
echo 'its something else'; $qualify = 0;
break;
}
if ($qualify == 1) {
echo "Congratulations, you quality for the contest. The extension you chose was <b>$final</b>";
} else {
echo "Sorry mate! you didn't quality for the contest.";
}
Use explode() to get the domain part and compare it
$parts = explode("#", "johndoe#domain.com");
echo ($parts[1]=='domain.com') ? 'qualify' : 'not qualify';
Sorry for my late reaction, I was still testing my code example.
If you want to stick with the switch you currently designed, you could use a simple preg_match to extract the string you need. Here is a little example (you can remove the comment and put in your switch there):
<?php
$ClassRoom2 = array(
'Daniel' => 'fresco#hotmail.com',
'Mike' => 'dkoko#yahoo.ca',
'Meranda' => 'brunnn_23#hotmail.ca',
'Will' => 'yumyum03#wp.pl',
'Brittey' => 's0sd#outlook.com',
'Kayla' => 'hocklife#freebie.com'
);
foreach ($ClassRoom2 as $name=>$email) {
$matches = [];
preg_match( "/(#.+)/", $email, $matches);
// Do things with $matches[0] here (your switch for eg)
// switch ($matches[0]) {
// case '#hotmail.com':
// ...
print '<br/> ' . $matches[0];
}
?>
If you want, you can fiddle arround with preg matches on this website: regexr
Update You can actually do a lot with preg_match, once you get the hang of it :)
foreach ($ClassRoom2 as $name=>$email) {
$matches = preg_match( "/#(hotmail.com|hotmail.ca|yahoo.ca|yahoo.com|live.ca)/", $email);
// if ($matches) // or simply replace the preg_match in the if
print '<br/> ' . $email . ($matches ? ' qualifies' : ' <strong>does not qualify</strong> ') . 'for the email test';
}
I would put the list of entries and the qualifying extensions on separate arrays then check each people entry and parse their information to see if each qualify, like this:
$peoplelist = array(
'Daniel' => 'fresco#hotmail.com',
'Mike' => 'dkoko#yahoo.ca',
'Meranda' => 'brunnn_23#hotmail.ca',
'Will' => 'yumyum03#wp.pl',
'Brittey' => 's0sd#outlook.com',
'Kayla' => 'hocklife#freebie.com'
);
$qualify = array(
'hotmail.com',
'hotmail.ca',
'yahoo.com',
'yahoo.ca',
'live.ca',
);
foreach( $peoplelist as $name => $email )
{
$parts = explode( "#", $email );
$extension = strtolower( trim( array_pop( $parts ) ) );
echo "Hi, ".$name.". You are using extension #".$extension.". <br /> \n";
if( in_array( $extension, $qualify ) )
{
echo "Congratulations, you quality for the contest. <br /> \n";
}
}
Good day everyone. I have the following two functions one for adding a rule and the other one for matching that rule. The problem is that when i use two params one of them doesn't get changed and i don't understand why it doesn't work. any help is apreciated.
public function add($name, $pattern, $controller, $action = null, array $params = array())
{
if(!isset($this->routeCollection[$name]))
$this->routeCollection[$name] =
array(
'pattern' => $pattern,
'controller' => $controller,
'action' => $action,
'params' => $params,
);
}
public function findMatch($url)
{
foreach ($this->routeCollection as $routeMap) {
$this->regex = $this->buildRegex($routeMap['pattern'], $routeMap['params']);
// Let's test the route.
if (preg_match($this->regex, $url)) {
return array('controller' => $routeMap['controller'], 'action' => $routeMap['action']);
}
}
return array('controller' => $this->routeCollection['404']['controller'], 'action' => $this->routeCollection['404']['action']);
}
public function buildRegex($uri, array $params)
{
// Find {params} in URI
if (preg_match_all('/\{(?:[^\}]+)\}/', $uri, $this->matches, PREG_SET_ORDER)) {
foreach ($this->matches as $isMatch) {
// Swap {param} with a placeholder
$this->uri = str_replace($isMatch, "%s", $uri);
}
// Build final Regex
$this->finalRegex = '/^' . preg_quote($this->uri, '/') . '$/';
$this->finalRegex = vsprintf($this->finalRegex, $params);
var_dump($this->finalRegex);
} else {
$this->finalRegex = '/^(' . preg_quote($uri, '/') . ')$/';
$this->finalRegex = str_replace(array('\.', '\-'), array('.', '-'), $this->finalRegex);
}
return $this->finalRegex;
}
// Usage:
$routeCollection->add('CatalogByCategory', '/catalog/category/{slugLink}', 'Ex:Controller:Catalog', 'ViewByCategory',
array('slugLink' => ('[a-z0-9]+(?:-[a-z0-9]+)*') ));
$routeCollection->add('ListCatalogPageByCategory', '/catalog/category/{sluglinks}/{pageNumber}', 'Ex:Controller:Catalog', 'ListCatalog',
array('sluglinks' => ('[a-z0-9]+(?:-[a-z0-9]+)*'), 'pageNumber' => ('[1-9][0-9]*') ));
// From Dump:
string '/^\/catalog\/category\/[a-z0-9]+(?:-[a-z0-9]+)*$/' (length=49)
string '/^\/catalog\/category\/\{sluglinks\}\/[a-z0-9]+(?:-[a-z0-9]+)*$/' (length=64)
foreach ($this->matches as $isMatch) {
// Swap {param} with a placeholder
$this->uri = str_replace($isMatch, "%s", $uri);
}
You keep overwriting $this->uri with the value of $uri being run through a replacement - in this case, it's getting set with {sluglinks} being replaced, then set again with only {pageNumber} being replaced.
You should use $this->uri = $uri;, and then always use $this->uri.
I'm trying to retrieve an item from a multi-dimensional array through a string that describes the path into the array (like first.second.third).
I've chosen the approach as shown here (also available on ideone):
<?php
// The path into the array
$GET_VARIABLE = "a.b.c";
// Some example data
$GLOBALS["a"]= array("b"=>array("c"=>"foo"));
// Construct an accessor into the array
$variablePath = explode( ".", $GET_VARIABLE );
$accessor = implode( "' ][ '", $variablePath );
$variable = "\$GLOBALS[ '". $accessor . "' ]";
// Print the value for debugging purposes (this works fine)
echo $GLOBALS["a"]["b"]["c"] . "\n";
// Try to evaluate the accessor (this will fail)
echo $$variable;
?>
When I run the script, it will print two lines:
foo
PHP Notice: Undefined variable: $GLOBALS[ 'a' ][ 'b' ][ 'c' ] in ...
So, why does this not evaluate properly?
I think the $$ notation only accepts a variable name (ie. the name of a variable). You are actually trying to read a variable named "$GLOBALS[ 'a' ][ 'b' ][ 'c' ]", which does not exist.
As an alternative ($GET_VARIABLE seems to be your input string), you could try this:
$path = explode('.', $GET_VARIABLE);
echo $GLOBALS[$path[0]][$path[1]][path[2]];
Wrap this in a suitable loop to make it more dynamic; it seems to be trivial.
It looks like PHP is treating your entire string like a variable name, and not as an array.
You could try using the following approach instead, as it would also probably be simpler.
<?php
// The path into the array
$GET_VARIABLE = "a.b.c";
// Some example data
$GLOBALS["a"]= array("b"=>array("c"=>"foo"));
// Construct an accessor into the array
$variablePath = explode( ".", $GET_VARIABLE );
//$accessor = implode( "' ][ '", $variablePath );
//$variable = "\$GLOBALS[ '". $accessor . "' ]";
// Print the value for debugging purposes (this works fine)
echo $GLOBALS["a"]["b"]["c"] . "\n";
// Try to evaluate the accessor (this will fail)
echo $GLOBALS[$variablePath[0]][$variablePath[1]][$variablePath[2]];
?>
Here's some code I wrote to access $_SESSION variables via dot notation. You should be able to translate it fairly easily.
<?php
$key = "a.b.c";
$key_bits = explode(".", $key);
$cursor = $_SESSION;
foreach ($key_bits as $bit)
{
if (isset($cursor[$bit]))
{
$cursor = $cursor[$bit];
}
else
{
return false;
}
}
return $cursor;
Here's one more solution using a helper function:
function GetValue($path, $scope = false){
$result = !empty($scope) ? $scope : $GLOBALS;
// make notation uniform
$path = preg_replace('/\[([^\]]+)\]/', '.$1', $path); // arrays
$path = str_replace('->', '.', $path); // object properties
foreach (explode('.', $path) as $part){
if (is_array($result) && array_key_exists($part, $result)){
$result = $result[$part];
} else if (is_object($result) && property_exists($result, $part)){
$result = $result->$part;
} else {
return false; // erroneous
}
}
return $result;
}
And example usage:
// Some example data
$GLOBALS["a"] = array(
'b' => array(
'c' => 'foo',
'd' => 'bar',
),
'e' => (object)array(
'f' => 'foo',
'g' => 'bar'
)
);
$bar = array(
'a' => $GLOBALS['a']
);
echo $GLOBALS['a']['b']['c'] . "\n"; // original
// $GLOBALS['a']['b']['c']
echo GetValue('a.b.c') . "\n"; // traditional usage
// $GLOBALS['a']['b']['c']
echo GetValue('a[b][c]') . "\n"; // different notation
// $bar['a']['b']['c']
echo GetValue('a.b.c', $bar) . "\n"; // changing root object
// $GLOBALS['a']['e']->f
echo GetValue('a[e]->f') . "\n"; // object notation
I am writing a class that handles routing of my PHP webservice but I need to correct the regex, and I want to know what would be the most effecient way to parse the url.
Example urls:
POST /users
GET /users
GET /users&limit=10&offset=0
GET /users/search&keyword=Richard
GET /users/15/posts/38
What I want to create in PHP for class is this:
$router = new Router();
$router->addRoute('POST', '/users', function(){});
$router->addRoute('GET', '/users/:uid/posts/:pid', function($uid, $pid){});
$target = $router->doRouting();
The target variable would now contain an array with:
method
url
callback method
This is what I got so far:
class Router{
use Singleton;
private $routes = [];
private $routeCount = 0;
public function addRoute($method, $url, $callback){
$this->routes[] = ['method' => $method, 'url' => $url, 'callback' => $callback];
$this->routeCount++;
}
public function doRouting(){
$reqUrl = $_SERVER['REQUEST_URI'];
$reqMet = $_SERVER['REQUEST_METHOD'];
for($i = 0; $i < $this->routeCount; $i++){
// Check if the url matches ...
// Parse the arguments of the url ...
}
}
}
So I need a regex that first of all:
/mainAction/:argumentName/secondaryAction/:secondaryActionName
checks if that matches the $reqUrl (see at the for loop above)
Extracts the arguments, so we can use them in our callback function.
What I tried myself:
(code should be in the for loop # doRouting function)
// Extract arguments ...
$this->routing[$i]['url'] = str_replace(':arg', '.+', $this->routing[$i]['url']);
// Does the url matches the routing url?
if(preg_match('#^' . $this->routes[$i]['url'] . '$#', $reqUrl)){
return $this->routes[$i];
}
I really appreciate all help, thanks alot.
this basicly works now.
public function doRouting(){
// I used PATH_INFO instead of REQUEST_URI, because the
// application may not be in the root direcory
// and we dont want stuff like ?var=value
$reqUrl = $_SERVER['PATH_INFO'];
$reqMet = $_SERVER['REQUEST_METHOD'];
foreach($this->routes as $route) {
// convert urls like '/users/:uid/posts/:pid' to regular expression
$pattern = "#^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($route['url'])) . "$#D";
$matches = Array();
// check if the current request matches the expression
if($reqMet == $route['method'] && preg_match($pattern, $reqUrl, $matches)) {
// remove the first match
array_shift($matches);
// call the callback with the matched positions as params
return call_user_func_array($route['callback'], $matches);
}
}
}
PS: You dont need the $routeCount attribute
Great answer #MarcDefiant. Cleanest PHP router I came across. Did a small modification to support regular expression as well. Not sure why you use preq_quote ?
Small todo would be to cast the array to a assoc array. E.g. replace ['0' => 1] with ['id' => 1]
function matchRoute($routes = [], $url = null, $method = 'GET')
{
// I used PATH_INFO instead of REQUEST_URI, because the
// application may not be in the root direcory
// and we dont want stuff like ?var=value
$reqUrl = $url ?? $_SERVER['PATH_INFO'];
$reqMet = $method ?? $_SERVER['REQUEST_METHOD'];
$reqUrl = rtrim($reqUrl,"/");
foreach ($routes as $route) {
// convert urls like '/users/:uid/posts/:pid' to regular expression
// $pattern = "#^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($route['url'])) . "$#D";
$pattern = "#^" . preg_replace('/:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', $route['url']) . "$#D";
// echo $pattern."\n";
$params = [];
// check if the current request params the expression
$match = preg_match($pattern, $reqUrl, $params);
if ($reqMet == $route['method'] && $match) {
// remove the first match
array_shift($params);
// call the callback with the matched positions as params
// return call_user_func_array($route['callback'], $params);
return [$route, $params];
}
}
return [];
}
$match = matchRoute([
[
'method' => 'GET',
'url' => '/:id',
'callback' => function($req) {
exit('Hello');
}
],
[
'method' => 'GET',
'url' => '/api/(.*)', // Match all /api/hello/test/...
'callback' => function($req) {
print_r($req);
exit('cool');
}
]
]);
list($route,$params) = $match;
call_user_func_array($route['callback'], [$params]);
I'm using PHP to build the URL of the current page. Sometimes, URLs in the form of
www.example.com/myurl.html?unwantedthngs
are requested. I want to remove the ? and everything that follows it (querystring), such that the resulting URL becomes:
www.example.com/myurl.html
My current code is this:
<?php
function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {
$pageURL .= "s";
}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"] . ":" .
$_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
}
return $pageURL;
}
?>
You can use strtok to get string before first occurence of ?
$url = strtok($_SERVER["REQUEST_URI"], '?');
strtok() represents the most concise technique to directly extract the substring before the ? in the querystring. explode() is less direct because it must produce a potentially two-element array by which the first element must be accessed.
Some other techniques may break when the querystring is missing or potentially mutate other/unintended substrings in the url -- these techniques should be avoided.
A demonstration:
$urls = [
'www.example.com/myurl.html?unwantedthngs#hastag',
'www.example.com/myurl.html'
];
foreach ($urls as $url) {
var_export(['strtok: ', strtok($url, '?')]);
echo "\n";
var_export(['strstr/true: ', strstr($url, '?', true)]); // not reliable
echo "\n";
var_export(['explode/2: ', explode('?', $url, 2)[0]]); // limit allows func to stop searching after first encounter
echo "\n";
var_export(['substr/strrpos: ', substr($url, 0, strrpos( $url, "?"))]); // not reliable; still not with strpos()
echo "\n---\n";
}
Output:
array (
0 => 'strtok: ',
1 => 'www.example.com/myurl.html',
)
array (
0 => 'strstr/true: ',
1 => 'www.example.com/myurl.html',
)
array (
0 => 'explode/2: ',
1 => 'www.example.com/myurl.html',
)
array (
0 => 'substr/strrpos: ',
1 => 'www.example.com/myurl.html',
)
---
array (
0 => 'strtok: ',
1 => 'www.example.com/myurl.html',
)
array (
0 => 'strstr/true: ',
1 => false, // bad news
)
array (
0 => 'explode/2: ',
1 => 'www.example.com/myurl.html',
)
array (
0 => 'substr/strrpos: ',
1 => '', // bad news
)
---
Use PHP Manual - parse_url() to get the parts you need.
Edit (example usage for #Navi Gamage)
You can use it like this:
<?php
function reconstruct_url($url){
$url_parts = parse_url($url);
$constructed_url = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
return $constructed_url;
}
?>
Edit (second full example):
Updated function to make sure scheme will be attached and none notice msgs appear:
function reconstruct_url($url){
$url_parts = parse_url($url);
$constructed_url = $url_parts['scheme'] . '://' . $url_parts['host'] . (isset($url_parts['path'])?$url_parts['path']:'');
return $constructed_url;
}
$test = array(
'http://www.example.com/myurl.html?unwan=abc',
`http://www.example.com/myurl.html`,
`http://www.example.com`,
`https://example.com/myurl.html?unwan=abc&ab=1`
);
foreach($test as $url){
print_r(parse_url($url));
}
Will return:
Array
(
[scheme] => http
[host] => www.example.com
[path] => /myurl.html
[query] => unwan=abc
)
Array
(
[scheme] => http
[host] => www.example.com
[path] => /myurl.html
)
Array
(
[scheme] => http
[host] => www.example.com
)
Array
(
[path] => example.com/myurl.html
[query] => unwan=abc&ab=1
)
This is the output from passing example URLs through parse_url() with no second parameter (for explanation only).
And this is the final output after constructing URL using:
foreach($test as $url){
echo reconstruct_url($url) . '<br/>';
}
Output:
http://www.example.com/myurl.html
http://www.example.com/myurl.html
http://www.example.com
https://example.com/myurl.html
best solution:
echo parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
No need to include your http://example.com in your <form action=""> if you're submitting a form to the same domain.
$val = substr( $url, 0, strrpos( $url, "?"));
Most Easiest Way
$url = 'https://www.youtube.com/embed/ROipDjNYK4k?rel=0&autoplay=1';
$url_arr = parse_url($url);
$query = $url_arr['query'];
print $url = str_replace(array($query,'?'), '', $url);
//output
https://www.youtube.com/embed/ROipDjNYK4k
You'll need at least PHP Version 5.4 to implement this solution without exploding into a variable on one line and concatenating on the next, but an easy one liner would be:
$_SERVER["HTTP_HOST"].explode('?', $_SERVER["REQUEST_URI"], 2)[0];
Server Variables: http://php.net/manual/en/reserved.variables.server.php
Array Dereferencing: https://wiki.php.net/rfc/functionarraydereferencing
You can use the parse_url build in function like that:
$baseUrl = $_SERVER['SERVER_NAME'] . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
You can try:
<?php
$this_page = basename($_SERVER['REQUEST_URI']);
if (strpos($this_page, "?") !== false) $this_page = reset(explode("?", $this_page));
?>
If you want to get request path (more info):
echo parse_url($_SERVER["REQUEST_URI"])['path']
If you want to remove the query and (and maybe fragment also):
function strposa($haystack, $needles=array(), $offset=0) {
$chr = array();
foreach($needles as $needle) {
$res = strpos($haystack, $needle, $offset);
if ($res !== false) $chr[$needle] = $res;
}
if(empty($chr)) return false;
return min($chr);
}
$i = strposa($_SERVER["REQUEST_URI"], ['#', '?']);
echo strrpos($_SERVER["REQUEST_URI"], 0, $i);
could also use following as per the php manual comment
$_SERVER['REDIRECT_URL']
Please note this is working only for certain PHP environment only and follow the bellow comment from that page for more information;
Purpose: The URL path name of the current PHP file, path-info is N/A
and excluding URL query string. Includes leading slash.
Caveat: This is before URL rewrites (i.e. it's as per the original
call URL).
Caveat: Not set on all PHP environments, and definitely only ones with
URL rewrites.
Works on web mode: Yes
Works on CLI mode: No
explode('?', $_SERVER['REQUEST_URI'])[0]
To remove the query string from the request URI, replace the query string with an empty string:
function request_uri_without_query() {
$result = $_SERVER['REQUEST_URI'];
$query = $_SERVER['QUERY_STRING'];
if(!empty($query)) {
$result = str_replace('?' . $query, '', $result);
}
return $result;
}
Because I deal with both relative and absolute URLs, I updated veritas's solution like the code below.
You can try yourself here: https://ideone.com/PvpZ4J
function removeQueryStringFromUrl($url) {
if (substr($url,0,4) == "http") {
$urlPartsArray = parse_url($url);
$outputUrl = $urlPartsArray['scheme'] . '://' . $urlPartsArray['host'] . ( isset($urlPartsArray['path']) ? $urlPartsArray['path'] : '' );
} else {
$URLexploded = explode("?", $url, 2);
$outputUrl = $URLexploded[0];
}
return $outputUrl;
}
Assuming you still want to get the URL without the query args (if they are not set), just use a shorthand if statement to check with strpos:
$request_uri = strpos( $_SERVER['REQUEST_URI'], '?' ) !== false ? strtok( $_SERVER["REQUEST_URI"], '?' ) : $_SERVER['REQUEST_URI'];
Try this
$url_with_querystring = 'www.example.com/myurl.html?unwantedthngs';
$url_data = parse_url($url_with_querystring);
$url_without_querystring = str_replace('?'.$url_data['query'], '', $url_with_querystring);
Try this:
$urrl=$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']
or
$urrl=$_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']