975

I use this code to get the full URL:

$actual_link = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

The problem is that I use some masks in my .htaccess, so what we see in the URL is not always the real path of the file.

What I need is to get the URL, what is written in the URL, nothing more and nothing less—the full URL.

I need to get how it appears in the Navigation Bar in the web browser, and not the real path of the file on the server.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
DiegoP.
  • 45,177
  • 34
  • 89
  • 107
  • 24
    @Brade URL bar is on the user browser, so why would PHP have any functionalities regarding that? PHP is server side. – eis Oct 19 '13 at 11:53
  • 33
    @eis Believe me, there's plenty of reasons to want this. Landing pages that use the same template but need to be tracked separately, etc. And the fact is that PHP (or any server side lang) can return all the various parts of the URL, but never seem to provide the whole thing in one string. It just seems dumb. – Brade Oct 29 '13 at 19:14
  • 12
    Whole thing is never sent to server side as it shouldn't matter, which is the reason it's not readily available anywhere. I would regard any functionality relying on that broken. But, that's just my opinion. – eis Oct 29 '13 at 20:31
  • 3
    The need expressed in the question (full URL, as in the address bar) shadows the actual problem here: if one happens to need the "self URL" of a page on the server (for whatever reason, like filling FORM action URLs), it would certainly be better to get it from the server (e.g. $_SERVER) than trying to assemble it from bits and pieces, in random, bogus manners (as can be frequently seen). That URL would at least be correct, even if only an "effective URL", not necessarily the exact copy of the address bar (which is, indeed, out of the server's reach). – Sz. Dec 07 '13 at 12:12
  • 5
    My example above for the need of a self URL: "filling FORM action URLs" may be wrong, as PHP_SELF (path only, sans domain etc.) should be enough for that. But it doesn't necessarily mean that all other needs for the canonical self URL are invalid. If they indeed are, it would be awesome to see a thorough explanation, why. – Sz. Dec 07 '13 at 12:58
  • @lunakid it is often convenient to take the current URL, parse it and add some more parameters to it, it would be better if the system was able to generate a canonical URL for every page on it's own, but this is often ridiculously hard to achieve. – Timo Huovinen Apr 26 '14 at 08:15
  • I don't understand why people can't hardcode the full path in the config file itself? It is accessed everywhere in the applications and there are other hardcoded things there, too, like db name, user and pass. Why waste computing power to find out the full path, which can easily be spoofed by sending a different HTTP_HOST? – Gogol Aug 04 '15 at 12:34
  • 4
    One of the reasons why you should not hardcode your URL in config is when you have different platforms where your project will be installed on(dev, integration, production). Each one of them will have their specific URL, and you don't want to change your code according to which server your project is installed on. – Guillaume Fache Apr 27 '16 at 07:40
  • A simpler solution might hopefully come with PHP 7.2+ (proposed version) https://wiki.php.net/rfc/replace_parse_url – Avatar Sep 13 '17 at 11:13
  • @KaiNoack How would a replacement for [`parse_url(url)`](http://php.net/parse_url) solve the problem of first getting that url? – ax. Jan 09 '18 at 16:19
  • For that matter, just have a look at the whole array with `print_r($_SERVER)`, you'll see everything you need there :) – casraf Jul 20 '11 at 21:35

27 Answers27

2490

Have a look at $_SERVER['REQUEST_URI'], i.e.

$actual_link = "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

(Note that the double quoted string syntax is perfectly correct.)

If you want to support both HTTP and HTTPS, you can use

$actual_link = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

⚠️ This code has security implications because the client and the server can set HTTP_HOST and REQUEST_URI to arbitrary values. It is absolutely necessary to sanitize both values and do proper input validation (CWE-20). They must not be used in any security context.

hakre
  • 193,403
  • 52
  • 435
  • 836
ax.
  • 58,560
  • 8
  • 81
  • 72
  • it just returns the folder, but not the domain name. How do I add the domain name too in this string? – DiegoP. Jul 20 '11 at 21:35
  • ok but if the path is ending with a file.. example index.html, it will not work....how do I get the full URL, whatever it is inside the URL..is there a way? – DiegoP. Jul 20 '11 at 21:40
  • 2
    add the domain name the same way you did it with `$_SERVER[HTTP_HOST]` - see my updated answer. – ax. Jul 20 '11 at 21:41
  • 146
    What if you're on a https link? What if HTTP_HOST is not available or has been tampered with by client side? This answer seems incomplete and unreliable. – Manachi Apr 05 '13 at 02:07
  • 24
    Not much you can do about it, this is the proper method for the question asked. – Mfoo Apr 27 '13 at 12:45
  • 4
    this is missing the quotes around the index. should be `$_SERVER['HTTP_HOST']` – Matt Ryan Aug 23 '13 at 16:59
  • 3
    @mattryan it is not - see the "perfectly correct" link (especially the examples) at the end of my answer. – ax. Aug 23 '13 at 17:21
  • 200
    You can just add the check of HTTPS: `'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}/{$_SERVER['REQUEST_URI']}"` – ivkremer Feb 22 '14 at 21:33
  • 9
    If you're outputting the URL to a browser as a link, just leave the http: off. See: http://stackoverflow.com/questions/4978235/ – GameCharmer Feb 26 '14 at 12:34
  • 4
    Note that when using ISAPI with IIS, the value `$_SERVER['HTTPS']` will be `off` if the request was not made through the HTTPS protocol. – commonpike May 08 '14 at 10:21
  • 1
    Can we not just use `$_SERVER[REQUEST_SCHEME]` instead of setting `http` manually? – ᴍᴀᴛᴛ ʙᴀᴋᴇʀ Jul 15 '14 at 14:57
  • 2
    @MatthewT.Baker `$_SERVER['REQUEST_SCHEME']` is not reliable - see http://stackoverflow.com/questions/18008135/is-serverrequest-scheme-reliable – ax. Jul 18 '14 at 08:56
  • 2
    @ax. in regards to your comment on Aug 23 '13, at 17:21. The document which you reference clearly states that your original syntax is incorrect. Here is the pasted information from php.net on the page which you link: // This is wrong for the same reason as $foo[bar] is wrong outside a string. // In other words, it will still work, but only because PHP first looks for a // constant named foo; an error of level E_NOTICE (undefined constant) will be // thrown. echo "This is wrong: {$arr[foo][3]}"; Now please stop spreading incorrect information. – Darren Felton Aug 05 '14 at 21:08
  • 3
    @ax. Please then, enlighten me as to what is syntactically incorrect with this: $var = "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; I see nothing incorrect with that syntax. This however (your syntax): $var = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; will throw E_NOTICE level errors. – Darren Felton Aug 05 '14 at 22:41
  • 2
    @Meogi I keep reverting your edits because they are unnecessarily verbose, my version doesn't throw E_NOTICE errors, and this is my answer. Re: "your original syntax is incorrect": You are looking at and quoting the wrong part of the simple string syntax documentation I am referencing. So let me do it for you: `"He drank some $juices[koolaid1] juice."`. Do you see that there are no quotes around the koolaid1? So I will go ahead and revert your edit for the 3rd (and hopefully last) time. – ax. Aug 05 '14 at 22:43
  • 3
    @Meogi Try this: `error_reporting(-1); $_SERVER['HTTP_HOST'] = 'example.com'; echo "$_SERVER[HTTP_HOST]"; // Note that $_SERVER[HTTP_HOST] is enclosed in "s!` – ax. Aug 05 '14 at 22:55
  • 3
    @ax. Interesting. Well, I meant no disrespect in all this, and it is time to say you were correct. Thank you sir, I have indeed learned something new today. I will leave your post be. – Darren Felton Aug 05 '14 at 23:00
  • 3
    @ax. And yet, your syntax is discouraged in many places who adopt coding _standards_. Junior developers shouldn't be encouraged to omit enclosing quotes because it can and _has_ (in my experience) produced bad habits. That is why coding standards typically say that while you _can_ do a certain thing, it doesn't always mean it's the best or even _good_ practice. I rest my case saying that in the end, the edited version is still better than your version. – Yes Barry Aug 06 '14 at 00:41
  • 1
    @mmmshuddup My experience (and i think I have a little more than you) is different. Would you mind to point me to a few of the "coding standards adopted in many places" that discourage my syntax? I think your (and others) misunderstanding is that you think I suggest ommitting quotes and rely on the implicite constant to strings conversion (which throws E_NOTICEs). I _don't_ suggest this - my point is about conciseness _inside_ "-quoted strings, which doesn't require extra '-quotes around `HTTP_HOST`, nor `{}`s (as suggested by your edit) to offset the unneeded extra '-quotes. – ax. Aug 06 '14 at 09:29
  • 6
    @ax. And you think you have a little more than me? lol ok pal. If your arrogance wasn't displayed strongly enough by your abuse of the moderator tools in rolling back your answer, it definitely was displayed enough right here; thus discrediting everything else you had to say. Also, I _didn't_ misunderstand anything (You know what they say about assuming...), I know exactly what you're doing, and it's not good practice. – Yes Barry Aug 06 '14 at 14:46
  • 2
    @mmmshuddup My assumption about the experience was based on our ages (I am 41), the time we both do programming (I do since 1987), and our stackoverflow history. Feel free to correct me. But please do so with facts, e.g. point me to a few of the "coding standards adopted in many places" that discourage my syntax, give me some concrete arguments why you think your syntax is better - but don't get personal. Thanks! – ax. Aug 06 '14 at 15:11
  • 10
    These comments from both parties are no longer contributing to the original post, and do not add value. Tooltip on Add Comment states "Use comments to ask for more information or suggest improvements". Please stick to that. – Darren Felton Aug 06 '14 at 17:16
  • 5
    wow this answer is terrible - involves unnecessary questionable coding standards, which have nothing to do with the question - and even has crucial bugs. I advise the reader to look at other high scoring answers. – raveren Oct 30 '14 at 12:46
  • 2
    I wonder why nobody mentioned protocol-relative `//urls`? It solves all issues with http and https – vladkras Mar 20 '15 at 15:21
  • 2
    @vladkras How does `//` solve the issue of putting the complete URL of the current page into an email? Just for starters :) – ax. Mar 20 '15 at 21:17
  • 3
    This is taking under account server ports: `$protocol='http' . (isset($_SERVER['HTTPS']) ? 's' : ''); $host="{$_SERVER['HTTP_HOST']}"; $port=(($_SERVER['SERVER_PORT'] != 80 || $_SERVER['SERVER_PORT'] != 443) ? "" : ":" . $_SERVER['SERVER_PORT']); $request_uri="{$_SERVER['REQUEST_URI']}"; $server_url= $protocol.'://'.$host.$port.$request_uri; ` – webcoder Aug 04 '15 at 17:29
  • 1
    who has no one mentioned the use of $_SERVER['SCRIPT_URI'] which returns the server uri that is running the php script? – Decoded Feb 01 '16 at 07:55
  • 1
    @Decoded Because `$_SERVER['SCRIPT_URI']` is [only available when mod_rewrite is enabled](http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#EnvVar). – ax. Feb 01 '16 at 08:51
  • @webcoder: The `$port` check always outputs null as-is. This is needed: `$port=($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) ? ':' . $_SERVER['SERVER_PORT'] : '';` – noobish Apr 11 '16 at 18:45
  • @ax. I don't know if it's still relevant, but since nobody else can answer your coding standards question without getting heated, I will: while your syntax is perfectly valid PHP, many places have coding standards forbidding the use of double-quotes all together, due to their unusual behaviour with edge cases. For example, attempting to de-reference an object works (`"$foo->bar"`), but attempting to de-reference child objects fails (`"$foo->bar->baz"`). You can get similar results from arrays: `"$array[foo]"` works, while `"$array[foo][bar]"` doesn't. – Marcus Harrison Aug 19 '16 at 12:03
  • 1
    @ax. It doesn't help that many IDEs and text editors will not perform syntax highlighting (or use different syntax highlighting) on string constants, making it more difficult to find where variables are being used in strings. For this reason, many places (including, for example, the Zend project and the Magento project) will forbid the use of double-quotes in favour of using single-quoted strings with the concatenation operator. – Marcus Harrison Aug 19 '16 at 12:08
  • 1
    Whoops, appears I was wrong. Zend framework allows use of double-quotes and variable substitution in the coding standards: https://framework.zend.com/manual/1.11/en/coding-standard.coding-style.html I never saw it done during my time with Magento so I had assumed it was forbidden. My apologies. – Marcus Harrison Aug 19 '16 at 12:50
  • 3
    @ivkremer, I think you have a superflous slash in there between `{$_SERVER['HTTP_HOST']}` and `{$_SERVER['REQUEST_URI']}` – adam rowe Nov 17 '16 at 15:35
  • @adamrowe, you're right. That's strange nobody said this before. – ivkremer Nov 18 '16 at 09:31
  • @DoHoaVinh In most cases the browser will not send the #anchor to the server and as such PHP can not display it without help of javascript. See https://stackoverflow.com/a/3081862/1276062 – Kyborek Nov 30 '17 at 13:44
  • `#` is not necessarily part of http, don't use hashfragment serverside. It's ment to be used in the client only. Another hint: Properly use `'` and `"`. Only defined constants can be used without quotes => this is wrong: `$_SERVER[HTTP_HOST]`. This is good: `$_SERER['HTTP_HOST']`. – Daniel W. Feb 02 '18 at 10:27
  • @DanFromGermany `"$_SERVER[HTTP_HOST]"`(note the `"`) is NOT wrong - see the "perfectly correct" link and the discussion. – ax. Feb 02 '18 at 11:05
  • 1
    @ax. its bad practice, 1. dont put variables straight into strings 2. dont treat array keys like constants – Daniel W. Feb 02 '18 at 14:12
  • @DanFromGermany 2. `"$_SERVER[HTTP_HOST]"` does NOT treat `HTTP_HOST` as constant 1. This is your opinion, and there are other opinions (incl. mine). This has both been said in the comments before (please check). If there are no new arguments (like links to "its bad practice"), please refrain from adding more comments. Thanks! – ax. Feb 02 '18 at 14:56
  • `isset($_SERVER['HTTPS']` is not a complete check as it might be `false` – nikksan Apr 17 '18 at 10:35
  • maybe you need port too: `'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}:{$_SERVER['SERVER_PORT']}{$_SERVER['REQUEST_URI']}"` – Harkály Gergő May 22 '18 at 14:42
  • 1
    @MagnusEriksson I am not here to convince anyone to improve his or her coding skills. If you don't want it, don't do it. If your skills pass the average wordpress plugin coder, you will realise conventions and best practice is way more valuable than taking a shortcut by putting a variable straight into double quotes. – Daniel W. Jul 09 '18 at 13:14
  • @DanFromGermany - And I'm not advocating for one way or the other. My first comment was: _"or is this simply one of those "you shouldn't" that people keep repeating without actually knowing why"_ and you just came with claims like _"anyone who claims elsewise is really not into enterprise PHP "_ which I wanted some source for. In the lack of proper arguments, I'm marking this down as: _"Some people on internet says this is best practices, for some unknown reason"_. Anyway, this is _very_ off-topic so I'm out... – M. Eriksson Jul 09 '18 at 13:23
  • 1
    @MagnusEriksson This whole Q/A is a good reason not to put variables straight into strings. Look what people come up with, confusing constants and strings: `"http://$_SERVER[HTTP_HOST]"`. Or take this VERY simplified snippet: `$a = '1'; $aa = '2'; echo "$aa";` - does it print 1 or 2? is it readable? Does every IDE get that? Those PHP beginner styles are only OK because the parser tolerates it and tries its best to handle the shitty syntax. Stop claiming I didn't give you reasons not to put vars into strings without `{}` or `" . "` - I already gave you reasons. – Daniel W. Jul 09 '18 at 13:44
  • 1
    @DanFromGermany - That's because half the people here haven't read up on string expressions at all (and it's hard to understand how things work if you haven't read up on it, best practice or not). Also, that's why you can use `"{$a}a" or "{$aa}"`. That also clears up the "constant" issue, since it would be `"{$_SERVER['HTTP_HOST']}"`, just like outside the string. So, using `{}` will make it clear _and_ readable, but is still "putting a variable in a string". – M. Eriksson Jul 09 '18 at 13:49
  • @MagnusEriksson I been talking about putting variables straight into strings, where "straight" means without `{}` obv. – Daniel W. Jul 09 '18 at 14:03
  • 1
    @DanFromGermany - Fair enough, but it wasn't 100% clear from your comment. In my opinion, using `{}` should be good. However, using `"$foo"` is usually OK as well, depending on the context. Like most things in programming, adapt to the context. – M. Eriksson Jul 09 '18 at 21:14
  • 1
    "$_SERVER[HTTP_HOST]" The reason this is bad practice is because variables tend to get copy+pasted throughout the lifetime of a code base. If it gets pasted outside of double quotes then it's introducing a bug. I would most likely decline a PR that contained this. – Mark Roach Jul 23 '18 at 23:53
  • @Mark Roach I would argue that you a) should only copy+paste code you fully understand, b) have a unit test that fails if your (new) code is wrong, and c) educate people about bugs in their PRs. – ax. Jul 25 '18 at 12:39
  • 2
    Hey, editor. If using HTTP_HOST has security implications then which is the safe way? You don't say. –  Oct 05 '18 at 12:53
  • shouldn't use double quotes in PHP too often; never on variables coming from a request. injection vulnerability – That Realty Programmer Guy Apr 23 '19 at 16:07
  • 1
    `$_SERVER['SERVER_NAME']` is better to use than HTTP_HOST. – SirSpeciam Jun 05 '20 at 19:21
  • If the answer has security implications, just remove it or changed it. – Pedro Lobito Jan 27 '21 at 12:18
  • check $_SERVER['REQUEST_SCHEME'] for https/http – Mohsen TOA Aug 08 '21 at 14:13
  • @MohsenNewtoa As already mentioned above: $_SERVER['REQUEST_SCHEME'] is not reliable - see https://stackoverflow.com/questions/18008135/is-serverrequest-scheme-reliable – ax. Aug 08 '21 at 19:00
  • If `$_SERVER['REQUEST_URI']` is not available, try `getenv("REQUEST_URI")`, works with Apache 2. – legolas108 Sep 19 '21 at 13:32
  • I have written a helper function around @ax. approach https://gist.github.com/ahmu83/f33db179eaf7dce273471053017a285a – AhmadKarim Apr 03 '22 at 18:23
  • @DanielW. *its bad practice, 1. dont put variables straight into strings 2. dont treat array keys like constants* you're welcome to write your own, verbose answer to the question. Personally, I can't imagine why sifting through fewer characters and operators would be any more complicated or confusing (or bad practice for that matter) than sifting through more. – Kröw Apr 17 '23 at 03:08
  • @MarkRoach Copy-pasting code without understanding how it works is one of the most dreadful things I could imagine a developer would do in a codebase. Do people not *think* about what they write these days? :( Anyway, I would argue that accounting for people doing something that drastic is futile, and that the person copy-pasting random code snippets should be stopped immediately, as they are the *actual* problem in such a scenario. Avoiding problems rather than fixing them will not get rid of them. It is like duct taping a flesh wound. – Kröw Apr 17 '23 at 03:15
485

Short version to output link on a webpage

$url =  "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";

$escaped_url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );
echo '<a href="' . $escaped_url . '">' . $escaped_url . '</a>';

Here are some more details about the issues and edge cases of the //example.com/path/ format

Full version

function url_origin( $s, $use_forwarded_host = false )
{
    $ssl      = ( ! empty( $s['HTTPS'] ) && $s['HTTPS'] == 'on' );
    $sp       = strtolower( $s['SERVER_PROTOCOL'] );
    $protocol = substr( $sp, 0, strpos( $sp, '/' ) ) . ( ( $ssl ) ? 's' : '' );
    $port     = $s['SERVER_PORT'];
    $port     = ( ( ! $ssl && $port=='80' ) || ( $ssl && $port=='443' ) ) ? '' : ':'.$port;
    $host     = ( $use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] ) ) ? $s['HTTP_X_FORWARDED_HOST'] : ( isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null );
    $host     = isset( $host ) ? $host : $s['SERVER_NAME'] . $port;
    return $protocol . '://' . $host;
}

function full_url( $s, $use_forwarded_host = false )
{
    return url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI'];
}

$absolute_url = full_url( $_SERVER );
echo $absolute_url;

This is a heavily modified version of http://snipplr.com/view.php?codeview&id=2734 (Which no longer exists)

URL structure:

scheme://username:password@domain:port/path?query_string#fragment_id

The parts in bold will not be included by the function

Notes:

  • This function does not include username:password from a full URL or the fragment (hash).
  • It will not show the default port 80 for HTTP and port 443 for HTTPS.
  • Only tested with http and https schemes.
  • The #fragment_id is not sent to the server by the client (browser) and will not be added to the full URL.
  • $_GET will only contain foo=bar2 for an URL like /example?foo=bar1&foo=bar2.
  • Some CMS's and environments will rewrite $_SERVER['REQUEST_URI'] and return /example?foo=bar2 for an URL like /example?foo=bar1&foo=bar2, use $_SERVER['QUERY_STRING'] in this case.
  • Keep in mind that an URI = URL + URN, but due to popular use, URL now means both URI and URL.
  • You should remove HTTP_X_FORWARDED_HOST if you do not plan to use proxies or balancers.
  • The spec says that the Host header must contain the port number unless it is the default number.

Client (Browser) controlled variables:

  • $_SERVER['REQUEST_URI']. Any unsupported characters are encoded by the browser before they are sent.
  • $_SERVER['HTTP_HOST'] and is not always available according to comments in the PHP manual: http://php.net/manual/en/reserved.variables.php
  • $_SERVER['HTTP_X_FORWARDED_HOST'] gets set by balancers and is not mentioned in the list of $_SERVER variables in the PHP manual.

Server controlled variables:

  • $_SERVER['HTTPS']. The client chooses to use this, but the server returns the actual value of either empty or "on".
  • $_SERVER['SERVER_PORT']. The server only accepts allowed numbers as ports.
  • $_SERVER['SERVER_PROTOCOL']. The server only accepts certain protocols.
  • $_SERVER['SERVER_NAME'] . It is set manually in the server configuration and is not available for IPv6 according to kralyk.

Related:

What is the difference between HTTP_HOST and SERVER_NAME in PHP?
Is Port Number Required in HTTP "Host" Header Parameter?
https://stackoverflow.com/a/28049503/175071

Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143
  • 16
    This code will fail if the server is given by IPv6 IP address. To fix that, replace SERVER_NAME with HTTP_HOST. – kralyk Nov 22 '12 at 17:05
  • 1
    note: `$_SERVER['REQUEST_URI']` will show `/example?foo=bar2` for url like `/example?foo=bar1&foo=bar2` – Timo Huovinen May 09 '13 at 13:36
  • 3
    This would not contain anything defined after a #, those aren't passed through to the server – William King Jun 05 '13 at 18:57
  • `SERVER_NAME` doesn't work well with balancers. Should try `HTTP_X_FORWARDED_HOST`, `HTTP_HOST`, and then fall back to `SERVER_NAME`. – mpen Oct 17 '13 at 19:53
  • @Mark shouldn't it be `$_SERVER['HTTP_X_FORWARDED_SERVER']` instead of `$_SERVER['SERVER_NAME']`? Why is `$_SERVER['HTTP_X_FORWARDED_HOST']` better? – Timo Huovinen Oct 18 '13 at 06:54
  • @TimoHuovinen: I think that will give you the name of the balancer rather than the domain name, which is what you're really after. Further, the port will cause it to show :443 on HTTPS, which you probably don't want either. – mpen Oct 18 '13 at 07:01
  • Note: according to my tests `$_SERVER['REQUEST_URI']` now correctly returns `/example?foo=bar1&foo=bar2` or url `/example?foo=bar1&foo=bar2` on php 5.4.7, I am now unsure on when exactly it replaced the duplicate key query param. Adding details into the answer. – Timo Huovinen Oct 19 '13 at 11:31
  • 1
    I'm unsure if that is no security risk. In your example you can send the Host header to reach the correct page but might let the page think it is called via another host using the HTTP_X_FORWARDED_HOST header. When the application uses this information (for whatever) it can be indeed a security problem as it allows you to promise something what isn't the case. – hek2mgl Dec 06 '13 at 11:08
  • @hek2mgl isn't that only insecure for a client that is connecting through an insecure proxy? Still trying to wrap my head around what exactly is insecure about it and how to work with balancers and still keep it secure (if at all possible). – Timo Huovinen Dec 06 '13 at 11:17
  • It doesn't count if you are using HTTP or HTTPS. The - untrusted - user can set this header like he wants. However, using HTTPS would prevent man in the middle attackers from injecting the header – hek2mgl Dec 06 '13 at 11:23
  • You normaly accept forwarded-for headers only if the request originates from the ip of the load-balancer/proxy. – Tom Regner Jan 16 '14 at 19:00
  • It returns http://localhost:8888:8888 because the port is already set in $s['HTTP_HOST']. – Matt3o12 Apr 25 '14 at 17:05
  • 1
    @Matt3o12 The value of the port is taken directly from the `Host` header, haven't seen it set like that, thanks for mentioning it, will add it as a tweak – Timo Huovinen Apr 25 '14 at 20:19
  • Why does it attempt to use `HTTP_HOST`? Isn't it safer and effectively equivalent to use always `$s['SERVER_NAME'] . $port`? – André Chalella Oct 23 '15 at 14:49
  • @AndréNeves because the function gets the _requested_ URL, while `SERVER_NAME` is simply a setting on the server. Basically the entire thing is user input of sorts. – Timo Huovinen Oct 24 '15 at 09:17
  • Thanks, Timo. I assume then the server could hardly be exploited in this manner, since the exploitable header (`HTTP_HOST`) will be used merely to construct strings to be sent back to the client, is that right? – André Chalella Oct 24 '15 at 09:29
  • 1
    @AndréNeves it could be used for more than that, for example to figure out routing, requested environments, etc. One difference could be when two domains point to the same server, then the server will see which one was requested, but it can only be these two hosts, unsupported hosts simply don't connect to the server. – Timo Huovinen Oct 24 '15 at 10:44
  • For me it worked like `$url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];` – Pathros Aug 05 '16 at 20:01
  • @TimoHuovinen I found your answer while Googling for *"`$_SERVER['REQUEST_URI']` php does not work with microsoft edge"* where I noticed the word "edge" being added in this revision http://stackoverflow.com/revisions/8891890/27 where I was under the impression it was "Microsoft Edge-related" and unsure if it has anything to do with a serverside `$_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']` coming back as "false" but fine on other browsers, wondering if that has anything to do with it. A more intense Google search did not render any results; am thinking of posting a question about this. – Funk Forty Niner Jan 23 '17 at 18:24
  • @Fred-ii- the REQUEST_URI variable is sent by the browser, if microsoft edge does not send it then it won't be available, the question is how do you determine what page you are looking at if you don't get it? The SERVER_NAME variable is set in the server settings by the admin and is usually the name (domain) of the website. I also read that UTF-8 in the settings or the url may affect this. – Timo Huovinen Jan 24 '17 at 07:10
  • 1
    @TimoHuovinen Thanks for the response. What you said makes sense, however it's hard to know why Edge failed on that. My friend who informed me of this yesterday as to what I wrote failed on him (on Edge) using `$_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']`, had him try another version by replacing `$_SERVER['SERVER_NAME']` with `www.example.com` worked. I.e.: `$host = "www.example.com" . $_SERVER['REQUEST_URI']; if( ($host == "www.example.com" . '/folder/file.php?q=123') || ($host == "www.example.com" . '/folder/file.php?q=12345'))`, baffling huh? Would you suggest I post a question? – Funk Forty Niner Jan 24 '17 at 14:39
  • 1
    @TimoHuovinen Addendum to the above. In using the original `$_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']` for an older version with an ` – Funk Forty Niner Jan 24 '17 at 14:41
  • This code will fail if URL contains `#` character – joseantgv Dec 18 '20 at 12:55
  • @joseantgv What do you mean? Anything past and including the `#` character is not sent to the server by the browser. – Timo Huovinen Dec 18 '20 at 18:24
  • @TimoHuovinen @WilliamKing In fact the value of the # part is actually sent to the server, and certainly can be accessed by PHP. Try echo this: `parse_url($url)['fragment']` – MMJ Dec 22 '22 at 14:06
  • @MMJ whether it's sent or not depends on the client used. Per http spec it should not be sent as far as I know, it would be very kind of you if you found the link to the specification, here's the wiki article which also says that it's normally not sent: https://en.wikipedia.org/wiki/URI_fragment – Timo Huovinen Dec 23 '22 at 12:15
  • Ouch... sorry dude, you are correct. In fact (as [http spec][1] rules) the fragment is not sent to the client. I just ran 1 test, informing a string directly in the parse_url() function, like this: `print_r(parse_url('http://localhost:8020/api/endpoint/?abc=123&def=true#hashtag'))` and in this forced and incorrect example, the fragment will exist on the server side. [1]: https://www.rfc-editor.org/rfc/rfc2396#section-4.1 – MMJ Dec 27 '22 at 15:37
277

Examples for: https://www.site.xyz/fold/my.php?var=bla#555

Notice 1:

  • the hashtag # part was added manually in below php example snippet only for theoretical & illustrational purposes, however Server-Side languages (including PHP) are unable to detect them, because hashtags parts are only recognized in Client-Side browser/javascript...*

Notice 2:

  • DIRECTORY_SEPARATOR returns \ for Windows-OS, while UNIX returns /.
========== PATHINFO (use for filepathes, not urls) ==========

$x = PATHINFO ($url);
$x['dirname']               https://www.site.xyz/fold
$x['basename']                                        my.php?var=bla#555 // unsafe!
$x['extension']                                          php?var=bla#555 // unsafe!
$x['filename']                                        my

========== PARSE_URL (use for urls, not filepathes) ==========

$x = PARSE_URL ($url);
$x['scheme']                https
$x['host']                          www.site.xyz
$x['path']                                      /fold/my.php
$x['query']                                                  var=bla
$x['fragment']                                                       555

Global variable $_SERVER

$_SERVER["DOCUMENT_ROOT"]   /home/user/public_html
$_SERVER["SERVER_ADDR"]     143.34.112.23
$_SERVER["SERVER_PORT"]     80 (or 443, etc..)
$_SERVER["REQUEST_SCHEME"]  https                           
$_SERVER["SERVER_PROTOCOL"] <same>
$_SERVER['HTTP_HOST']              www.site.xyz
$_SERVER["SERVER_NAME"]               <same>
$_SERVER["REQUEST_URI"]                        /fold/my.php?var=bla
$_SERVER["QUERY_STRING"]                                    var=bla

__FILE__                    /home/user/public_html/fold/my.php
$_SERVER["SCRIPT_FILENAME"] <same>                              // Note! it will show entry file's path, if `my.php` is not called directly.
__DIR__                     /home/user/public_html/fold
dirname(__FILE__)           <same>
$_SERVER["REQUEST_URI"]                           /fold/my.php?var=bla  // Note! it will show entry file's path, if `my.php` is not called directly.
parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH)  /fold/my.php
$_SERVER["PHP_SELF"]                              /fold/my.php  // Note! it will show entry file's path, if `my.php` is not called directly.
// detect https
$is_HTTPS = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS']!=='off') || $_SERVER['SERVER_PORT']==443);            //in some cases, you need to add this condition too: if ('https'==$_SERVER['HTTP_X_FORWARDED_PROTO']) 

PHP Functions

dirname($url)               https://www.site.xyz/fold/
basename($url)                                        my.php
debug_backtrace()           SHOWS FULL TRACE OF ALL INCLUDED FILES




< For WordPress >

// (Let's say, if WordPress is installed in subdirectory:  http://site.xyz/sub/)
home_url()                       http://site.xyz/sub/        // If is_ssl() is true, then it will be "https"
get_stylesheet_directory_uri()   http://site.xyz/sub/wp-content/themes/THEME_NAME  [same: get_bloginfo('template_url') ]
get_stylesheet_directory()       /home/user/public_html/sub/wp-content/themes/THEME_NAME
plugin_dir_url(__FILE__)         http://site.xyz/sub/wp-content/themes/PLUGIN_NAME
plugin_dir_path(__FILE__)        /home/user/public_html/sub/wp-content/plugins/PLUGIN_NAME/
T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • Where is the # part, Is there no way we can access part after # on the server side? – Rohit Khatri Aug 08 '16 at 07:01
  • @RohitKhatri that part is only accessible in the browser and is not sent to server – beppe9000 Dec 24 '19 at 13:53
  • What is the wordpress function to get the url with query string too ? – beppe9000 Dec 24 '19 at 13:54
  • WARN: `pathinfo()` does not behave with more complex `URL`'s as you would expect - although `/` character is not strictly forbidden in parameters (see https://stackoverflow.com/questions/1455578/characters-allowed-in-get-parameter), parsing such URL will not give you script basename/filename. Try `print_r(pathinfo("https://example.com/subFolder/myfile.php?var=path/to/another/file.png"));` – Jiří Aug 17 '21 at 10:17
  • For me, I had to do `basename ($_SERVER["PHP_https://stackoverflow.com/questions/6768793/get-the-full-url-in-phpSELF"] )` to get the main script name without query string (I need it for the main script in the sidebar links list) – Salem Jun 14 '22 at 11:13
70

Here's a solution using a ternary statement, keeping the code minimal:

$url = "http" . (($_SERVER['SERVER_PORT'] == 443) ? "s" : "") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

This is the smallest and easiest way to do this, assuming one's web server is using the standard port 443 for HTTPS.

Blackbam
  • 17,496
  • 26
  • 97
  • 150
honyovk
  • 2,717
  • 18
  • 26
49

My favorite cross platform method for finding the current URL is:

$url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
Yukulélé
  • 15,644
  • 10
  • 70
  • 94
  • 10
    Close, but I needed to change it to this: $url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; – Erik Allen Feb 12 '16 at 16:46
38

Simply use:

$uri = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
HappyCoder
  • 5,985
  • 6
  • 42
  • 73
25
function full_path()
{
    $s = &$_SERVER;
    $ssl = (!empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true:false;
    $sp = strtolower($s['SERVER_PROTOCOL']);
    $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
    $port = $s['SERVER_PORT'];
    $port = ((!$ssl && $port=='80') || ($ssl && $port=='443')) ? '' : ':'.$port;
    $host = isset($s['HTTP_X_FORWARDED_HOST']) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);
    $host = isset($host) ? $host : $s['SERVER_NAME'] . $port;
    $uri = $protocol . '://' . $host . $s['REQUEST_URI'];
    $segments = explode('?', $uri, 2);
    $url = $segments[0];
    return $url;
}

Note: I just made an update to Timo Huovinen's code, so you won't get any GET parameters in the URL. This URL is plain and removes things like ?hi=i&am=a&get.

Example:

http://www.example.com/index?get=information

will be shown as:

http://www.example.com/index

This is fine unless you use GET paramaters to define some specific content, in which case you should use his code! :-)

TRiG
  • 10,148
  • 7
  • 57
  • 107
  • hey thats, pretty cool :) you could also remove anything after a hash "#" (url fragment) in case it somehow slips in – Timo Huovinen Nov 22 '12 at 18:37
  • 1
    Not really, because if you set in " explode('#',$segment[0]) ", it will count as error, because " # " the symbol breaks the URL, and can only be read by Javascript. But what you can do, to be sure, is that you can remake the " return $url; " with " return trim($url,'#'); ", because then you will remove it, in case it will be there. But it will not remove the following content. You can read up on "Parse_url" if you want to. :-) – Alex Ahlgreen Westergaard Nov 28 '12 at 17:27
20

Same technique as the accepted answer, but with HTTPS support, and more readable:

$current_url = sprintf(
    '%s://%s/%s',
    isset($_SERVER['HTTPS']) ? 'https' : 'http',
    $_SERVER['HTTP_HOST'],
    $_SERVER['REQUEST_URI']
);

The above gives unwanted slashes. On my setup Request_URI has leading and trailing slashes. This works better for me.

$Current_Url = sprintf(
   '%s://%s/%s',
   isset($_SERVER['HTTPS']) ? 'https' : 'http',
   $_SERVER['HTTP_HOST'],
   trim($_SERVER['REQUEST_URI'],'/\\')
);
Rohit Gupta
  • 4,022
  • 20
  • 31
  • 41
Jonathon Hill
  • 3,445
  • 1
  • 33
  • 31
20

Clear code, working in all webservers (Apache, nginx, IIS, ...):

$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
Andreas
  • 2,821
  • 25
  • 30
16

HTTP_HOST and REQUEST_URI must be in quotes, otherwise it throws an error in PHP 7.2

Use:

$actual_link = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

If you want to support both HTTP and HTTPS:

$actual_link = (isset($_SERVER['HTTPS']) ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

⚠️ Using this code has security implications because the client can set HTTP_HOST and REQUEST_URI to arbitrary values. It is absolutely necessary to sanitize both values and do input validation.

Having said this, it is best to determine the link server side without relying on the URL of the browser.

Avatar
  • 14,622
  • 9
  • 119
  • 198
13

Here is my solution - code is inspired by Tracy Debugger. It was changed for supporting different server ports. You can get full current URL including $_SERVER['REQUEST_URI'] or just the basic server URL. Check my function:

function getCurrentUrl($full = true) {
    if (isset($_SERVER['REQUEST_URI'])) {
        $parse = parse_url(
            (isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') .
            (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '')) . (($full) ? $_SERVER['REQUEST_URI'] : null)
        );
        $parse['port'] = $_SERVER["SERVER_PORT"]; // Setup protocol for sure (80 is default)
        return http_build_url('', $parse);
    }
}

Here is test code:

// Follow $_SERVER variables was set only for test
$_SERVER['HTTPS'] = 'off'; // on
$_SERVER['SERVER_PORT'] = '9999'; // Setup
$_SERVER['HTTP_HOST'] = 'some.crazy.server.5.name:8088'; // Port is optional there
$_SERVER['REQUEST_URI'] = '/150/tail/single/normal?get=param';

echo getCurrentUrl();
// http://some.crazy.server.5.name:9999/150/tail/single/normal?get=param

echo getCurrentUrl(false);
// http://some.crazy.server.5.name:9999/
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
OzzyCzech
  • 9,713
  • 3
  • 50
  • 34
9

I've made this function to handle the URL:

 <?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;
     }
 ?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
8

This is quite easy to do with your Apache environment variables. This only works with Apache 2, which I assume you are using.

Simply use the following PHP code:

<?php
    $request_url = apache_getenv("HTTP_HOST") . apache_getenv("REQUEST_URI");
    echo $request_url;
?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Amarjit
  • 311
  • 2
  • 10
  • I tried this $actual_link = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; – Rohit Kaushik Jun 10 '20 at 06:53
7

This is the solution for your problem:

//Fetch page URL by this

$url = $_SERVER['REQUEST_URI'];
echo "$url<br />";

//It will print
//fetch host by this

$host=$_SERVER['HTTP_HOST'];
echo "$host<br />";

//You can fetch the full URL by this

$fullurl = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo $fullurl;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vaibhav Jain
  • 493
  • 2
  • 7
  • 13
7

Try this:

print_r($_SERVER);

$_SERVER is an array containing information such as headers, paths, and script locations. The entries in this array are created by the web server. There is no guarantee that every web server will provide any of these; servers may omit some, or provide others not listed here. That said, a large number of these variables are accounted for in the » CGI/1.1 specification, so you should be able to expect those.

$HTTP_SERVER_VARS contains the same initial information, but is not a superglobal. (Note that $HTTP_SERVER_VARS and $_SERVER are different variables and that PHP handles them as such)

Ram Sharma
  • 8,676
  • 7
  • 43
  • 56
php developer
  • 89
  • 2
  • 6
7

You can use http_build_url with no arguments to get the full URL of the current page:

$url = http_build_url();
Pang
  • 9,564
  • 146
  • 81
  • 122
Luke Mlsna
  • 468
  • 4
  • 16
7

Use this one-liner to find the parent folder URL (if you have no access to http_build_url() that comes along with pecl_http):

$url = (isset($_SERVER['HTTPS']) ? 'https://' : 'http://').$_SERVER['SERVER_NAME'].str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname(dirname(__FILE__)));
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
4

Here is the basis of a more secure version of the accepted answer, using PHP's filter_input function, which also makes up for the potential lack of $_SERVER['REQUEST_URI']:

$protocol_https = filter_input(INPUT_SERVER, 'HTTPS', FILTER_SANITIZE_STRING);
$host = filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_URL);
$request_uri = filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
if(strlen($request_uri) == 0)
{
    $request_uri = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);
    $query_string = filter_input(INPUT_SERVER, 'QUERY_STRING', FILTER_SANITIZE_URL);
    if($query_string)
    {
        $request_uri .= '?' . $query_string;
    }
}
$full_url = ($protocol_https ? 'https' : 'http') . '://' . $host . $request_uri;

You could use some different filters to tweak it to your liking.

Coder
  • 2,833
  • 2
  • 22
  • 24
4
    public static function getCurrentUrl($withQuery = true)
    {
        $protocol = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
        or (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
        or (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
        or (isset($_SERVER['SERVER_PORT']) && intval($_SERVER['SERVER_PORT']) === 443) ? 'https' : 'http';

        $uri = $protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

        return $withQuery ? $uri : str_replace('?' . $_SERVER['QUERY_STRING'], '', $uri);
    }
smarteist
  • 1,331
  • 12
  • 15
3

I used this statement.

$base = "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]$my_web_base_path";
$url = $base . "/" . dirname(dirname(__FILE__));
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PhonPanom
  • 385
  • 5
  • 8
3

I have used the below code, and it is working fine for me, for both cases, HTTP and HTTPS.

function curPageURL() {
  if(isset($_SERVER["HTTPS"]) && !empty($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] != 'on' )) {
        $url = 'https://'.$_SERVER["SERVER_NAME"];//https url
  }  else {
    $url =  'http://'.$_SERVER["SERVER_NAME"];//http url
  }
  if(( $_SERVER["SERVER_PORT"] != 80 )) {
     $url .= $_SERVER["SERVER_PORT"];
  }
  $url .= $_SERVER["REQUEST_URI"];
  return $url;
}

echo curPageURL();

Demo

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
thecodedeveloper.com
  • 3,220
  • 5
  • 36
  • 67
2

Use:

$base_dir = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite
$doc_root = preg_replace("!{$_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www
$base_url = preg_replace("!^{$doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'
$base_url = str_replace('\\', '/', $base_url);//On Windows
$base_url = str_replace($doc_root, '', $base_url);//On Windows
$protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
$port = $_SERVER['SERVER_PORT'];
$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
$domain = $_SERVER['SERVER_NAME'];
$full_url = "$protocol://{$domain}{$disp_port}{$base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc. 

Source: PHP Document Root, Path and URL detection

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hpaknia
  • 2,769
  • 4
  • 34
  • 63
2

Very simple use:

function current_url() {
    $current_url  = ( $_SERVER["HTTPS"] != 'on' ) ? 'http://'.$_SERVER["SERVER_NAME"] :  'https://'.$_SERVER["SERVER_NAME"];
    $current_url .= ( $_SERVER["SERVER_PORT"] != 80 ) ? ":".$_SERVER["SERVER_PORT"] : "";
    $current_url .= $_SERVER["REQUEST_URI"];

    return $current_url;
}
Abbas Arif
  • 372
  • 4
  • 16
1

This works for both HTTP and HTTPS.

echo 'http' . (($_SERVER['HTTPS'] == 'on') ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Output something like this.

https://example.com/user.php?token=3f0d9sickc0flmg8hnsngk5u07&access_level=application

Madan Sapkota
  • 25,047
  • 11
  • 113
  • 117
1

You can make use of HTTP_ORIGIN as illustrated in the snippet below:

if ( ! array_key_exists( 'HTTP_ORIGIN', $_SERVER ) ) {
    $this->referer = $_SERVER['SERVER_NAME'];
} else {
    $this->referer = $_SERVER['HTTP_ORIGIN'];
}
nyedidikeke
  • 6,899
  • 7
  • 44
  • 59
ninja
  • 463
  • 1
  • 7
  • 14
0

I think this method is good..try it

if($_SERVER['HTTP_HOST'] == "localhost"){
    define('SITEURL', 'http://' . $_SERVER['HTTP_HOST']);
    define('SITEPATH', $_SERVER['DOCUMENT_ROOT']);
    define('CSS', $_SERVER['DOCUMENT_ROOT'] . '/css/');
    define('IMAGES', $_SERVER['DOCUMENT_ROOT'] . '/images/');
}
else{
    define('SITEURL', 'http://' . $_SERVER['HTTP_HOST']);
    define('SITEPATH', $_SERVER['DOCUMENT_ROOT']);
    define('TEMPLATE', $_SERVER['DOCUMENT_ROOT'] . '/incs/template/');
    define('CSS', $_SERVER['DOCUMENT_ROOT'] . '/css/');
    define('IMAGES', $_SERVER['DOCUMENT_ROOT'] . '/images/');
}
UWU_SANDUN
  • 1,123
  • 13
  • 19
-1
$page_url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

For more: How to get the full URL of a page using PHP

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Akshit Ahuja
  • 337
  • 2
  • 15