83
function url(){
    if(isset($_SERVER['HTTPS'])){
        $protocol = ($_SERVER['HTTPS'] && $_SERVER['HTTPS'] != "off") ? "https" : "http";
    }
    else{
        $protocol = 'http';
    }
    return $protocol . "://" . $_SERVER['HTTP_HOST'];
}

For example with the function above, it works fine if I work with the same directory, but if I make a sub directory, and work in it, it will give me the location of the sub directory also for example. I just want example.com but it gives me example.com/sub if I'm working in the folder sub. If I'm using the main directory,the function works fine. Is there an alternative to $_SERVER['HTTP_HOST']?

Or how could I fix my function/code to get the main url only? Thanks.

1

14 Answers 14

122

Use SERVER_NAME.

echo $_SERVER['SERVER_NAME']; //Outputs www.example.com
Sign up to request clarification or add additional context in comments.

5 Comments

@barbushin's answer below is better nowadays.
Here's the link to barbushin's answer: stackoverflow.com/a/43911112/457268 It presupposes knowledge of the domain though, and is not useful if one wants to dynamically determine the host name.
@barbushin's answer is not better. Its flat out wrong. Hardcoding the domain is not the correct answer.
it outputs for me: example.com not www.example.com
Although this can be spoofed if not configured properly, it's still better than gethostname() which does not work when on virtual host, I've posted the comparison and solution/config as a new answer: stackoverflow.com/a/77815115/1835470
59

You could use PHP's parse_url() function

function url($url) {
  $result = parse_url($url);
  return $result['scheme']."://".$result['host'];
}

3 Comments

$_SERVER['SERVER_NAME'] wasn't an option since we do interactive domain hosting with custom ports. (Why should we make things easy ?)
I believe parse_url return nothing, if no http. For example: $url = "example.com";
Please add some explanation to your answer by editing it, such that others can learn from it - where does $url come from?
43

Shortest solution:

$domain = parse_url('http://google.com', PHP_URL_HOST);

6 Comments

This should be accepted as answer, because its cross domain capability
This gives you the string "google.com". It's a flat out wrong answer.
@AyexeM You're supposed to change "google.com" to your website's domain.
@rahuldotech That makes no sense, copy paste your domain in there and it will return your domain? How is that helpful ? OP wants the domain of the server, not how to parse a domain from a string.
How I understand the question is how to get the domain segment without knowing what the domain is. That is, relative to the page you are loading. What if you are testing locally, then uploading to production? If you already know the domain, you don't need to retrieve it dynamically. I think the assumption is we don't know the domain the resource is loading from.
|
31
/**
 * Suppose, you are browsing in your localhost 
 * http://localhost/myproject/index.php?id=8
 */
function getBaseUrl() 
{
    // output: /myproject/index.php
    $currentPath = $_SERVER['PHP_SELF']; 

    // output: Array ( [dirname] => /myproject [basename] => index.php [extension] => php [filename] => index ) 
    $pathInfo = pathinfo($currentPath); 

    // output: localhost
    $hostName = $_SERVER['HTTP_HOST']; 

    // output: http://
    $protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'?'https':'http';

    // return: http://localhost/myproject/
    return $protocol.'://'.$hostName.$pathInfo['dirname']."/";
}

3 Comments

Umm... see php.net/manual/en/reserved.variables.server.php $_SERVER["SERVER_PROTOCOL"] returns a string like HTTP/1.0 or HTTP/1.1 and has nothing to do with https. You're probably looking for something like $_SERVER['HTTPS'] == 'on' or the undocumented REQUEST_SCHEME. See this related question and here's the answer I used: stackoverflow.com/a/14270161/466314
See, Previously I have wrote 5, It was correct but minor changes should be there like, $protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'?'https':'http';
No, strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'‌​ is always false because $_SERVER["SERVER_PROTOCOL"] doesn't work the way you think it does. It will never contain HTTPS anywhere in it. The example given in the apache documentation <If "%{SERVER_PROTOCOL} != 'HTTPS'"> is wrong as it's always true: httpd.apache.org/docs/2.4/rewrite/remapping.html#canonicalhost
11

Use parse_url() like this:

function url(){
    if(isset($_SERVER['HTTPS'])){
        $protocol = ($_SERVER['HTTPS'] && $_SERVER['HTTPS'] != "off") ? "https" : "http";
    }
    else{
        $protocol = 'http';
    }
    return $protocol . "://" . parse_url($_SERVER['REQUEST_URI'], PHP_URL_HOST);
}

Here is another shorter option:

function url(){
    $pu = parse_url($_SERVER['REQUEST_URI']);
    return $pu["scheme"] . "://" . $pu["host"];
}

1 Comment

parse_url returns nothing, if there is no http or https, i.e example.com
7

Step-1

First trim the trailing backslash (/) from the URL. For example, If the URL is http://www.google.com/ then the resultant URL will be http://www.google.com

$url= trim($url, '/');

Step-2

If scheme not included in the URL, then prepend it. So for example if the URL is www.google.com then the resultant URL will be http://www.google.com

if (!preg_match('#^http(s)?://#', $url)) {
    $url = 'http://' . $url;
}

Step-3

Get the parts of the URL.

$urlParts = parse_url($url);

Step-4

Now remove www. from the URL

$domain = preg_replace('/^www\./', '', $urlParts['host']);

Your final domain without http and www is now stored in $domain variable.

Examples:

http://www.google.com => google.com

https://www.google.com => google.com

www.google.com => google.com

http://google.com => google.com

1 Comment

what if other subdomain is used instead www?
3
/* Get sub domain or main domain url
 * $url is $_SERVER['SERVER_NAME']
 * $index int remove subdomain if acceess from sub domain my current url is https://support.abcd.com ("support" = 7 (char))
 * $subDomain string 
 * $issecure string https or http
 * return url
 * call like echo getUrl($_SERVER['SERVER_NAME'],7,"payment",true,false);
 * out put https://payment.abcd.com
 * second call echo getUrl($_SERVER['SERVER_NAME'],7,null,true,true);
*/
function getUrl($url,$index,$subDomain=null,$issecure=false,$www=true) {
  //$url=$_SERVER['SERVER_NAME']
  $protocol=($issecure==true) ?  "https://" : "http://";
  $url= substr($url,$index);
  $www =($www==true) ? "www": "";
  $url= empty($subDomain) ? $protocol.$url : 
  $protocol.$www.$subDomain.$url;
  return $url;
}

Comments

2

2 lines to solve it

$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$myDomain = preg_replace('/^www\./', '', parse_url($actual_link, PHP_URL_HOST));

1 Comment

This answer is missing its educational explanation.
2

This works fine if you want the http protocol also since it could be http or https. $domainURL = $_SERVER['REQUEST_SCHEME']."://".$_SERVER['SERVER_NAME'];

Comments

2

Use this code is whork :

if (!preg_match('#^http(s)?://#', $url)) {
         $url = 'http://' . $url;
}
$urlParts = parse_url($url);
$url = preg_replace('/^www\./', '', $urlParts['host']);

1 Comment

This answer is missing its educational explanation. Also, I would prepare the url with a single preg call instead of two. ...and please use correct spelling.
0

Please try this:

$uri = $_SERVER['REQUEST_URI']; // $uri == example.com/sub
$exploded_uri = explode('/', $uri); //$exploded_uri == array('example.com','sub')
$domain_name = $exploded_uri[1]; //$domain_name = 'example.com'

I hope this will help you.

1 Comment

In here $domain_name = 'sub' not 'example.com'. If need to get 'example.com' , then change the last code to $domain_name = $exploded_uri[0];
0

TL;DR

Specific http server (apache/nginx) config or whitelist of hosts & $_SERVER['SERVER_NAME'].


gethostname() ? only for non-virtual host...

https://www.php.net/manual/en/function.gethostname.php

gets the standard host name for the local machine.

... but if you're on a virtual host, this will still return the system host, not the virtual one :-( ...
(typically e.g. shared web hosting)

So what about $_SERVER['SERVER_NAME']?

https://www.php.net/manual/en/reserved.variables.server.php

Well, this on the other hand can be spoofed if not configured properly,
but it does return the virtual host if on virtual host.

Note: Under Apache 2, UseCanonicalName = On and ServerName must be set. Otherwise, this value reflects the hostname supplied by the client, which can be spoofed. It is not safe to rely on this value in security-dependent contexts.

Nginx => the same thing, docs just don't mention it.

Solution

Basically you have 2 options:

  1. If you can configure your http server, you can force it to be your value, not value from request, this differs per http server you use:

    • Apache: UseCanonicalName (to On) & ServerName directives have to be set - most likely in your <VirtualHost>
    • Nginx: you have to set the server_name directive in your server{} block.
  2. If you can't configure your server or can't rely on its setting, you can at least whitelist the allowed hostnames

<?php
    $allowedHosts = [
        'localhost',
        'example.com',
        'www.example.com',
    ];

    if (!\in_array($_SERVER['HTTP_HOST'], $allowedHosts)) {
        exit('You trynna spoof me?');
    }

Comments

-1

Tenary Operator helps keep it short and simple.

echo (isset($_SERVER['HTTPS']) ? 'http' : 'https' ). "://" . $_SERVER['SERVER_NAME']  ;

1 Comment

^ What they said. You probably also want to check the value of $_SERVER
-3

If you're using wordpress, use get_site_url:

get_site_url()

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.