Want to remove p2variable from url string, below are 3 cases if case 3 also remove ? sign.
case 1: http://www.domain.com/myscript.php?p1=xyz&p2=10&p3=ghj
result: http://www.domain.com/myscript.php?p1=xyz&p3=ghj
case 2: http://www.domain.com/myscript.php?p2=10&p3=ghj
result: http://www.domain.com/myscript.php?p3=ghj
case 3: http://www.domain.com/myscript.php?p2=10
result: http://www.domain.com/myscript.php
Want to achieve result with single preg_replace expression.
Don't use regular expressions when dealing with URL values. It's much easier (and safer) to handle them as a URL instead of plain text.
This could be one way to do it:
Split the url first and parse the query string
Take the parameter out
Rebuild the url
The below code is an example of such an algorithm:
// remove $qs_key from query string of $url
// return modified url value
function clean_url_qs($url, $qs_key)
{
// first split the url in two parts (at most)
$parts = explode('?', $url, 2);
// check whether query string is passed
if (isset($parts[1])) {
// parse the query string into $params
parse_str($parts[1], $params);
// unset if $params contains $qs_key
if (array_key_exists($qs_key, $params)) {
// remove key
unset($params[$qs_key]);
// rebuild the url
return $parts[0] .
(count($params) ? '?' . http_build_query($params) : '');
}
}
// no change required
return $url;
}
Test code:
echo clean_url('http://www.domain.com/myscript.php?p1=xyz&p2=10&p3=ghj', 'p2'), "\n";
echo clean_url('http://www.domain.com/myscript.php?p2=10&p3=ghj', 'p2'), "\n";
echo clean_url('http://www.domain.com/myscript.php?p2=10', 'p2'), "\n";
Found this in one of my old projects (a bit of shitcode, but...), may help you:
$unwanted_param = 'p2';
$s = 'http://www.domain.com/myscript.php?p1=xyz&p2=10&p3=ghj';
$s = parse_url($s);
$params = explode('&', $s['query']);
$out_params = array();
foreach ($params as $key => &$param) {
list($name, $value) = explode('=', $param);
if ($unwanted_param == $name) {
unset($params[$key]);
} else {
$out_params[$name] = $value;
}
}
$query = '?' . http_build_query($out_params);
$result = $s['scheme'] . '://' . $s['host'] . $s['path'] . $query;
var_dump($result);
Using preg_replace, something like
$url = preg_replace('!([\?&]p2=[^&\?$]+)!i', '', $url);
However, personally I'd do the following
if (strpos($url, '?') !== false) {
list($domain, $qstring) = explode('?', $url, 2);
parse_str($qstring, $params);
if (isset($params['p2'])) {
unset($params['p2']);
}
$qstring = !empty($params) ? '?' . http_build_query($params) : '';
$url = $domain . $qstring;
}
Related
I want to extract all used parameters of a link as a text string. Example:
$link2 = http://example.com/index.html?song=abcdefg;
When using the above link $param should give out all the parameters '?song=abcdefg'. Unfortunately I do not know the id index.html nor the parameters and their respective data values.
As much as I am informed there is the function $_GET, which creates an array, but I need a string.
You can use parse_url:
$link2 = 'http://example.com/index.html?song=abcdefg';
$param = '?' . parse_url($link2, PHP_URL_QUERY);
echo $param;
// ?song=abcdefg
Many librairies exist to parse url, you can use this one for an exemple :
https://github.com/thephpleague/uri
use League\Uri\Schemes\Http as HttpUri;
$link2 = 'http://example.com/index.html?song=abcdefg';
$uri = HttpUri::createFromString($link2);
// then you can access the query
$query = $uri->query;
You also can try this one :
https://github.com/jwage/purl
A weird way to do this is
$link2 = 'http://example.com/index.html?song=abcdefg';
$param = strstr($link2, "?");
echo $param // ?song=abcdefg
strstr($link2, "?") will get everything after the first position of ?; including the leading ?
you can loop over the get array and parse it into a string:
$str = "?"
foreach ($_GET as $key => $value) {
$temp = $key . "=". $value . "&";
$str .= $temp
}
rtrim($str, "&")//remove leading '&'
You can use http_build_query() method
if ( isset ($_GET))
{
$params = http_build_query($_GET);
}
// echo $params should return "song=abcdefg";
With $_SERVER['REQUEST_URI'], I get a URL that could be:
index.php
or
index.php?id=x&etc..
I'd like to do two things:
Find if there is a ?something after index.php name with regular expression.
If there is in the url a specific var (id=x) and delete it from the url.
For example:
index.php?id=x => index.php
index.php?a=11&id=x => index.php?a=11
How can I do this?
To check if there is a ?something after index.php, you could use the built-in function parse_url(), like so:
if (parse_url($url, PHP_URL_QUERY)) {
// ?something exists
}
To remove the id, you could use parse_str(), get the query parameters, store them in an array, and unset the particular id.
And since you also want to re-create the URL after the particular element is deleted from the query part of the URL, then you could use http_build_query().
Here's a function for that:
function removeQueryString($url, $toBeRemoved, $match)
{
// check if url has query part
if (parse_url($url, PHP_URL_QUERY)) {
// parse_url and store the values
$parts = parse_url($url);
$scriptname = $parts['path'];
$query_part = $parts['query'];
// parse the query parameters from the url and store it in $arr
$query = parse_str($query_part, $arr);
// if id == x, unset it
if (isset($arr[$toBeRemoved]) && $arr[$toBeRemoved] == $match) {
unset($arr[$toBeRemoved]);
// if there less than 1 query parameter, don't add '?'
if (count($arr) < 1) {
$query = $scriptname . http_build_query($arr);
} else {
$query = $scriptname . '?' . http_build_query($arr);
}
} else {
// no matches found, so return the url
return $url;
}
return $query;
} else {
return $url;
}
}
Test cases:
echo removeQueryString('index.php', 'id', 'x');
echo removeQueryString('index.php?a=11&id=x', 'id', 'x');
echo removeQueryString('index.php?a=11&id=x&qid=51', 'id', 'x');
echo removeQueryString('index.php?a=11&foo=bar&id=x', 'id', 'x');
Output:
index.php
index.php?a=11
index.php?a=11&qid=51
index.php?a=11&foo=bar
Demo!
If it must be a regular expression :
$url='index.php?a=11&id=1234';
$pattern = '#\id=\d+#';
$url = preg_replace($pattern, '', $url);
echo $url;
output
index.php?a=11&
There is a trailing &, but the above removes any id=xxxxxxxx
I found a bit of code for stripping a query string and adding a new value to it, but I want to be able to do this with an array of options. Could someone give me a hand in modifying this code to do that?
Current code:
function add_querystring_var($url, $key, $value) {
$url = preg_replace('/(.*)(\?|&)' . $key . '=[^&]+?(&)(.*)/i', '$1$2$4', $url . '&');
$url = substr($url, 0, -1);
$value = $value ? "=".urlencode($value) : '';
if (strpos($url, '?') === false)
return ($url . '?' . $key . $value);
else
return ($url . '&' . $key . $value);
}
And I want it to do a foreach for each key and value given and then rebuild the new url.
Example: add_querystring_var(curPageURL(), array("order","sort"), array("swn","DESC"))
So I want the following URL http://www.example.com/students when put through the example above would return http://www.example.com/students?order=swn&sort=DESC
Does anyone know how I can do this? I'm new to this area of PHP. :)
UPDATE:
I forgot to mention sometimes the url may have other queries in it, so I want it to replace the ones that I enter into my array.
Example 1: http://www.example.com/students?page=2 would need to turn into http://www.example.com/students?page=2&order=swn&sort=DESC
Example 2: http://www.example.com/students?page=2&order=name&sort=ASC would need to turn into http://www.example.com/students?page=2&order=swn&sort=DESC
function add_querystring_var($url, $additions) {
$parsed = parse_url($url);
if (isset($parsed['query'])) {
parse_str($parsed['query'], $query);
} else {
$query = array();
}
$parsed['query'] = http_build_query(array_merge($query, $additions));
return http_build_url($parsed);
}
Use it this way:
$new_url = add_querystring_var($url, array('order' => 'swn', 'sort' => 'DESC'));
If you're getting errors saying that http_build_url is not defined, see
PHP http_build_url() and PECL Install
You're kind of reinventing the wheel with that function... first off, you'd be better off using urlencode() on your key/value data rather than that regular expression (and I see that you're not encoding your value string at all)
As dpDesignz mentions in his comment - there is a built-in function available: http_build_query()
$querydata = array('foo' => array('bar', 'baz'),
'baz'=>'boom',
'cow'=>'milk',
'php'=>'hypertext processor');
$querystring = http_build_query($data, '', '&');
Or, to use your example:
$querydata = array("order" => "swn", "sort" => "DESC");
$url = curPageURL();
$concat = "?";
if (strpos($url, "?") !== false)) {
$concat = "&"
}
$url .= $concat . http_build_query($data, '', '&');
I want to add GET parameters to URLs that may and may not contain GET parameters without repeating ? or &.
Example:
If I want to add category=action
$url="http://www.acme.com";
// will add ?category=action at the end
$url="http://www.acme.com/movies?sort=popular";
// will add &category=action at the end
If you notice I'm trying to not repeat the question mark if it's found.
The URL is just a string.
What is a reliable way to append a specific GET parameter?
Basic method
$query = parse_url($url, PHP_URL_QUERY);
// Returns a string if the URL has parameters or NULL if not
if ($query) {
$url .= '&category=1';
} else {
$url .= '?category=1';
}
More advanced
$url = 'http://example.com/search?keyword=test&category=1&tags[]=fun&tags[]=great';
$url_parts = parse_url($url);
// If URL doesn't have a query string.
if (isset($url_parts['query'])) { // Avoid 'Undefined index: query'
parse_str($url_parts['query'], $params);
} else {
$params = array();
}
$params['category'] = 2; // Overwrite if exists
$params['tags'][] = 'cool'; // Allows multiple values
// Note that this will url_encode all values
$url_parts['query'] = http_build_query($params);
// If you have pecl_http
echo http_build_url($url_parts);
// If not
echo $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . '?' . $url_parts['query'];
You should put this in a function at least, if not a class.
Here's a shorter version of the accepted answer:
$url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . 'category=action';
Edit: as discussed in the accepted answer, this is flawed in that it doesn't check to see if category already exists. A better solution would be to treat the $_GET for what it is - an array - and use functions like in_array().
$data = array('foo'=>'bar',
'baz'=>'boom',
'cow'=>'milk',
'php'=>'hypertext processor');
$queryString = http_build_query($data);
//$queryString = foo=bar&baz=boom&cow=milk&php=hypertext+processor
echo 'http://domain.com?'.$queryString;
//output: http://domain.com?foo=bar&baz=boom&cow=milk&php=hypertext+processor
This function overwrites an existing argument
function addToURL( $key, $value, $url) {
$info = parse_url( $url );
parse_str( $info['query'], $query );
return $info['scheme'] . '://' . $info['host'] . $info['path'] . '?' . http_build_query( $query ? array_merge( $query, array($key => $value ) ) : array( $key => $value ) );
}
Example with updating existent parameters.
Also url_encode used, and possibility to don't specify parameter value
<?
/**
* Add parameter to URL
* #param string $url
* #param string $key
* #param string $value
* #return string result URL
*/
function addToUrl($url, $key, $value = null) {
$query = parse_url($url, PHP_URL_QUERY);
if ($query) {
parse_str($query, $queryParams);
$queryParams[$key] = $value;
$url = str_replace("?$query", '?' . http_build_query($queryParams), $url);
} else {
$url .= '?' . urlencode($key) . '=' . urlencode($value);
}
return $url;
}
Use strpos to detect a ?. Since ? can only appear in the URL at the beginning of a query string, you know if its there get params already exist and you need to add params using &
function addGetParamToUrl(&$url, $varName, $value)
{
// is there already an ?
if (strpos($url, "?"))
{
$url .= "&" . $varName . "=" . $value;
}
else
{
$url .= "?" . $varName . "=" . $value;
}
}
<?php
$url1 = '/test?a=4&b=3';
$url2 = 'www.baidu.com/test?a=4&b=3&try_count=1';
$url3 = 'http://www.baidu.com/test?a=4&b=3&try_count=2';
$url4 = '/test';
function add_or_update_params($url,$key,$value){
$a = parse_url($url);
$query = $a['query'] ? $a['query'] : '';
parse_str($query,$params);
$params[$key] = $value;
$query = http_build_query($params);
$result = '';
if($a['scheme']){
$result .= $a['scheme'] . ':';
}
if($a['host']){
$result .= '//' . $a['host'];
}
if($a['path']){
$result .= $a['path'];
}
if($query){
$result .= '?' . $query;
}
return $result;
}
echo add_or_update_params($url1,'try_count',1);
echo "\n";
echo add_or_update_params($url2,'try_count',2);
echo "\n";
echo add_or_update_params($url3,'try_count',3);
echo "\n";
echo add_or_update_params($url4,'try_count',4);
echo "\n";
/**
* #example addParamToUrl('/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
* #example addParamToUrl('//example.com/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
* #example addParamToUrl('https://example.com/path/to/?find=1&FILTER=Y', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
*
* #param $url string url
* #param array $addParams
*
* #return string
*/
function addParamToUrl($url, array $addParams) {
if (!is_array($addParams)) {
return $url;
}
$info = parse_url($url);
$query = array();
if ($info['query']) {
parse_str($info['query'], $query);
}
if (!is_array($query)) {
$query = array();
}
$params = array_merge($query, $addParams);
$result = '';
if ($info['scheme']) {
$result .= $info['scheme'] . ':';
}
if ($info['host']) {
$result .= '//' . $info['host'];
}
if ($info['path']) {
$result .= $info['path'];
}
if ($params) {
$result .= '?' . http_build_query($params);
}
return $result;
}
$parameters = array();
foreach ($get as $key => $value)
{
$parameters[] = $key.'='.$value;
}
$url = 'http://example.com/movies?'.implode('&', $parameters);
One-liner:
$url .= (strpos($url, '?') ? '&' : '?') . http_build_query($additionalParams);
using http_build_query is recommended because it encodes special characters (for example spaces or # in email addresses)
Improved version for 2022
This allows existing parameters to be replaced, and also preserves existing URL fragment (the part after # at the end of an URL)
function addParametersToUrl(string $url, array $newParams): string
{
$url = parse_url($url);
parse_str($url['query'] ?? '', $existingParams);
$newQuery = array_merge($existingParams, $newParams);
$newUrl = $url['scheme'] . '://' . $url['host'] . ($url['path'] ?? '');
if ($newQuery) {
$newUrl .= '?' . http_build_query($newQuery);
}
if (isset($url['fragment'])) {
$newUrl .= '#' . $url['fragment'];
}
return $newUrl;
}
Testing:
$newParams = [
'newKey' => 'newValue',
'existingKey' => 'new',
];
echo addParametersToUrl('https://www.example.com', $newParams);
// https://www.example.com?newKey=newValue&existingKey=new
echo addParametersToUrl('https://www.example.com/', $newParams);
// https://www.example.com/dir/?newKey=newValue&existingKey=new
echo addParametersToUrl('https://www.example.com/dir/', $newParams);
// https://www.example.com/dir/?newKey=newValue&existingKey=new
echo addParametersToUrl('https://www.example.com/dir/file?foo=bar', $newParams);
// https://www.example.com/dir/file?foo=bar&newKey=newValue&existingKey=new
echo addParametersToUrl('https://www.example.com/dir/file?foo=bar&existingKey=old', $newParams);
// https://www.example.com/dir/file?foo=bar&existingKey=new&newKey=newValue
echo addParametersToUrl('https://www.example.com/dir/file?foo=bar&existingKey=old#hash', $newParams);
// https://www.example.com/dir/file?foo=bar&existingKey=new&newKey=newValue#hash
echo addParametersToUrl('https://www.example.com/dir/file#hash', $newParams);
// https://www.example.com/dir/file?newKey=newValue&existingKey=new#hash
echo addParametersToUrl('https://www.example.com/dir/file?foo=bar#hash', $newParams);
// https://www.example.com/dir/file?foo=bar&newKey=newValue&existingKey=new#hash
I think you should do it something like this.
class myURL {
protected $baseURL, $requestParameters;
public function __construct ($newURL) {
$this->baseurl = $newURL;
$this->requestParameters = array();
}
public function addParameter ($parameter) {
$this->requestParameters[] = $parameter;
}
public function __toString () {
return $this->baseurl.
( count($this->requestParameters) ?
'?'.implode('&', $this->requestParameters) :
''
);
}
}
$url1 = new myURL ('http://www.acme.com');
$url2 = new myURL ('http://www.acme.com');
$url2->addParameter('sort=popular');
$url2->addParameter('category=action');
$url1->addParameter('category=action');
echo $url1."\n".$url2;
After searching for many resources/answers on this topic, I decided to code my own. Based on #TaylorOtwell's answer here, this is how I process incoming $_GET request and modify/manipulate each element.
Assuming the url is: http://domain.com/category/page.php?a=b&x=y
And I want only one parameter for sorting: either ?desc=column_name or ?asc=column_name. This way, single url parameter is enough to sort and order simultaneously. So the URL will be http://domain.com/category/page.php?a=b&x=y&desc=column_name on first click of the associated table header row.
Then I have table row headings that I want to sort DESC on my first click, and ASC on the second click of the same heading. (Each first click should "ORDER BY column DESC" first) And if there is no sorting, it will sort by "date then id" by default.
You may improve it further, like you may add cleaning/filtering functions to each $_GET component but the below structure lays the foundation.
foreach ($_GET AS $KEY => $VALUE){
if ($KEY == 'desc'){
$SORT = $VALUE;
$ORDER = "ORDER BY $VALUE DESC";
$URL_ORDER = $URL_ORDER . "&asc=$VALUE";
} elseif ($KEY == 'asc'){
$SORT = $VALUE;
$ORDER = "ORDER BY $VALUE ASC";
$URL_ORDER = $URL_ORDER . "&desc=$VALUE";
} else {
$URL_ORDER .= "&$KEY=$VALUE";
$URL .= "&$KEY=$VALUE";
}
}
if (!$ORDER){$ORDER = 'ORDER BY date DESC, id DESC';}
if ($URL_ORDER){$URL_ORDER = $_SERVER[SCRIPT_URL] . '?' . trim($URL_ORDER, '&');}
if ($URL){$URL = $_SERVER[SCRIPT_URL] . '?' . trim($URL, '&');}
(You may use $_SERVER[SCRIPT_URI] for full URL beginning with http://domain.com)
Then I use resulting $ORDER I get above, in the MySQL query:
"SELECT * FROM table WHERE limiter = 'any' $ORDER";
Now the function to look at the URL if there is a previous sorting and add sorting (and ordering) parameter to URL with "?" or "&" according to the sequence:
function sort_order ($_SORT){
global $SORT, $URL_ORDER, $URL;
if ($SORT == $_SORT){
return $URL_ORDER;
} else {
if (strpos($URL, '?') !== false){
return "$URL&desc=$_SORT";
} else {
return "$URL?desc=$_SORT";
}
}
}
Finally, the table row header to use the function:
echo "<th><a href='".sort_order('id')."'>ID</a></th>";
Summary: this will read the URL, modify each of the $_GET components and make the final URL with parameters of your choice with the correct form of usage of "?" and "&"
public function addGetParamToUrl($url, $params)
{
foreach ($params as $param) {
if (strpos($url, "?"))
{
$url .= "&" .http_build_query($param);
}
else
{
$url .= "?" .http_build_query($param);
}
}
return $url;
}
another improved function version. Mix of existing answers with small improvements (port support) and bugfixes (checking keys properly).
/**
* #param string $url original url to modify - can be relative, partial etc
* #param array $paramsOverride associative array, can be empty
* #return string modified url
*/
protected function overrideUrlQueryParams($url, $paramsOverride){
if (!is_array($paramsOverride)){
return $url;
}
$url_parts = parse_url($url);
if (isset($url_parts['query'])) {
parse_str($url_parts['query'], $params);
} else {
$params = [];
}
$params = array_merge($params, $paramsOverride);
$res = '';
if(isset($url_parts['scheme'])) {
$res .= $url_parts['scheme'] . ':';
}
if(isset($url_parts['host'])) {
$res .= '//' . $url_parts['host'];
}
if(isset($url_parts['port'])) {
$res .= ':' . $url_parts['port'];
}
if (isset($url_parts['path'])) {
$res .= $url_parts['path'];
}
if (count($params) > 0) {
$res .= '?' . http_build_query($params);
}
return $res;
}
Try this function to add URL parameters.
Then you can disable the link when parameter is set so there is no url parameter duplicate.
<?php
function addQueryString($a)
{
if (empty($_SERVER['QUERY_STRING']))
return '?' . $a;
else if (!empty($_SERVER['QUERY_STRING']))
return '?' . $_SERVER['QUERY_STRING'] . '&' . $a;
}
?>
test
sat
In case you are using WordPress you can simply use
add_query_args(['sort' => 'asc'], 'http:/example.com/?search=news')
Docs https://developer.wordpress.org/reference/functions/add_query_arg/
I have a few strings to combine to build a full path. e.g.
$base = "http://foo.com";
$subfolder = "product/data";
$filename = "foo.xml";
// How to do this?
$url = append_url_parts($base, $subfolder, $filename); ???
String concatenation won't do, that would omit the necessary forward slashes.
In Win32 I'd use PathCombine() or PathAppend(), which would handle adding any necessary slashes between strings, without doubling them up. In PHP, what should I use?
Try this:
$base = "http://foo.com";
$subfolder = "product/data";
$filename = "foo.xml";
function stripTrailingSlash(&$component) {
$component = rtrim($component, '/');
}
$array = array($base, $subfolder, $filename);
array_walk_recursive($array, 'stripTrailingSlash');
$url = implode('/', $array);
when it comes down to something like this I like to use a special function with unlimited parameters.
define('BASE_URL','http://mysite.com'); //Without last slash
function build_url()
{
return BASE_URL . '/' . implode(func_get_args(),'/');
}
OR
function build_url()
{
$Path = BASE_URL;
foreach(func_get_args() as $path_part)
{
$Path .= '/' . $path_part;
}
return $Path;
}
So that when I use the function I can do
echo build_url('home'); //http://mysite.com/home
echo build_url('public','css','style.css'); //http://mysite.com/public/css/style.css
echo build_url('index.php'); //http://mysite.com/index.php
hope this helps you, works really well for me especially within an Framework Environment.
to use with params you can append the url like so for simplicity.
echo build_url('home') . '?' . http_build_query(array('hello' => 'world'));
Would produce: http://mysite.com/home?hello=world
not sure why you say string concat won't do, because something like this is basically similar to a string concat. (untested semi-pseudo)
function append_url_parts($base, $subf, $file) {
$url = sprintf("%s%s%s", $base, (($subf)? "/$subf": ""), (($file)? "/$file": ""));
return $url;
}
with string concat, we'd have to write a slightly longer block like so:
function append_url_parts($base, $subf, $file) {
$subf = ($subf)? "/$subf": "";
$file = ($file)? "/$file": "";
$url = "$base$subf$file";
return $url;
}
I usually go simple:
<?
$url = implode('/', array($base, $subfolder, $filename));
Either that or use a framework, and then use whatever route system it has.
There are a few considerations first.
Are you interested in getting the current path of the script or some other path?
How flexible do you need this to be? Is it something that is going to change all the time? Is it something an admin will set once and forget?
You want to be careful not to include the slash bug where your document has a slash added at the end because you were too lazy to figure out how to separate directory vars from the file var. There will only be one file and one base per URL and unknown number of directories in each path, right? :)
If you want to make sure there are no duplicate slashes within the resultant path, I like this little function...simply pass it an array of path part you want combined and it will return a formatted path - no need to worry whether any of the parts contain a slash alerady or not:
function build_url($arr)
{
foreach ( $arr as $path ) $url[] = rtrim ( $path, '/' );
return implode( $url, '/' );
}
This should work on all versions of PHP too.
Not my code, but a handy function which takes an absolute URL and a relative URL and combines the two to make a new absolute path.
The function has been modified to ignore an absolute URL passed as relative ( basically anything that includes a schema ).
$url = "http://www.goat.com/money/dave.html";
$rel = "../images/cheese.jpg";
$com = InternetCombineURL($url,$rel);
public function InternetCombineUrl($absolute, $relative) {
$p = parse_url($relative);
if(isset($p["scheme"]))return $relative;
extract(parse_url($absolute));
$path = dirname($path);
if($relative{0} == '/') {
$cparts = array_filter(explode("/", $relative));
}
else {
$aparts = array_filter(explode("/", $path));
$rparts = array_filter(explode("/", $relative));
$cparts = array_merge($aparts, $rparts);
foreach($cparts as $i => $part) {
if($part == '.') {
$cparts[$i] = null;
}
if($part == '..') {
$cparts[$i - 1] = null;
$cparts[$i] = null;
}
}
$cparts = array_filter($cparts);
}
$path = implode("/", $cparts);
$url = "";
if($scheme) {
$url = "$scheme://";
}
if(isset($user)) {
$url .= "$user";
if($pass) {
$url .= ":$pass";
}
$url .= "#";
}
if($host) {
$url .= "$host/";
}
$url .= $path;
return $url;
}
I wrote this function for all cases to combine url parts with no duplicate slashes.
It accepts many arguments or an array of parts.
Some parts may be empty strings, that does not produce double slashes.
It keeps starting and ending slashes if they are present.
function implodePath($parts)
{
if (!is_array($parts)) {
$parts = func_get_args();
if (count($parts) < 2) {
throw new \RuntimeException('implodePath() should take array as a single argument or more than one argument');
}
} elseif (count($parts) == 0) {
return '';
} elseif (count($parts) == 1) {
return $parts[0];
}
$resParts = [];
$first = array_shift($parts);
if ($first === '/') {
$resParts[] = ''; // It will keep one starting slash
} else {
// It may be empty or have some letters
$first = rtrim($first, '/');
if ($first !== '') {
$resParts[] = $first;
}
}
$last = array_pop($parts);
foreach ($parts as $part) {
$part = trim($part, '/');
if ($part !== '') {
$resParts[] = $part;
}
}
if ($last === '/') {
$resParts[] = ''; // To keep trailing slash
} else {
$last = ltrim($last, '/');
if ($last !== '') {
$resParts[] = $last; // Adding last part if not empty
}
}
return implode('/', $resParts);
}
Here is a check list from unit test. Left array is input and right part is result string.
[['/www/', '/eee/'], '/www/eee/'],
[['/www', 'eee/'], '/www/eee/'],
[['www', 'eee'], 'www/eee'],
[['www', ''], 'www'],
[['www', '/'], 'www/'],
[['/www/', '/aaa/', '/eee/'], '/www/aaa/eee/'],
[['/www', 'aaa/', '/eee/'], '/www/aaa/eee/'],
[['/www/', '/aaa/', 'eee/'], '/www/aaa/eee/'],
[['/www', 'aaa', 'eee/'], '/www/aaa/eee/'],
[['/www/', '/aaa/'], '/www/aaa/'],
[['/www', 'aaa/'], '/www/aaa/'],
[['/www/', 'aaa/'], '/www/aaa/'],
[['/www', '/aaa/'], '/www/aaa/'],
[['/www', '', 'eee/'], '/www/eee/'],
[['www/', '/aaa/', '/eee'], 'www/aaa/eee'],
[['/www/', '/aaa', ''], '/www/aaa'],
[['', 'aaa/', '/eee/'], 'aaa/eee/'],
[['', '', ''], ''],
[['aaa', '', '/'], 'aaa/'],
[['aaa', '/', '/'], 'aaa/'],
[['/', 'www', '/'], '/www/'],
It can be used as implodePath('aaa', 'bbb') or implodePath(['aaa', 'bbb'])