5

I've typically used the following linking practice, of relative URLs with an absolute URL path:

<a href="/relative/path/to/document.html">

But I will implement absolute URLs:

<a href="http://example.com/relative/path/to/document.html">

It's not a problem for me to change them (automated find & replace in HTML documents).

But what is the best practice to make sure that it will work on both my localhost (which supports PHP), as well as on the web? And why?


For example, here's how I do PHP includes:

<?php include($_SERVER['DOCUMENT_ROOT']."/relative/path/to/document.html"); ?>

Adopt the same approach for href URLs? Is a different PHP technique better? Curious to hear why.

Community
  • 1
  • 1
Baumr
  • 6,124
  • 14
  • 37
  • 63

5 Answers5

6

Keep the same directory structure locally and on the web host, and use relative URIs and paths whenever possible. If you must use an absolute URI, define it once somewhere and use the constant whenever you need to output a URI to avoid having to make the changes using find and replace.

<?php
    define('ROOT_URI', 'http://example.com/subdirectory');
?>

<a href='<?php echo ROOT_URI; ?>/relative/path/to/document.html'> document </a>

It's easier if you have a configuration file or some other included file where you only define it once.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
  • 1
    A good place for this define is in a configuration file. Each deployment can customize the environment. – Xeoncross Jan 17 '13 at 03:15
  • Is ROOT_URI and then echo preferred over include and DOCUMENT_ROOT? Why? Thanks – Baumr Jan 17 '13 at 14:37
  • 1
    `DOCUMENT_ROOT` is a physical file path, which is fine for your `include` statement, but not for generating an actual URI. See http://stackoverflow.com/questions/7868652/serverdocument-root. Also I just named the constant `ROOT_URI` in my example, you can name it whatever you want (for instance in another answer the constant was named `HOST`). – rink.attendant.6 Jan 17 '13 at 20:56
6

You could just include a predefined constant or variable in the HTML hrefs.

e.g.

<?php
define("LOCAL", "http://localhost");
define("WEB", "http://foo.bar");
$environment = LOCAL; //change to WEB if you're live
?>
<a href="<?php echo $environment; ?>/relative/path/to/document.html">
hammus
  • 2,602
  • 2
  • 19
  • 37
3

That all depends on how you plan on hosting the content. PHP is not a bad choice as there are oodles of hosting companies that support PHP. Without a scripting language like PHP, your best bet would be javascript, but depending why you are trying to make the URL's absolute, that might defeat your purpose.

One thing I would suggest is making a configuration file as you may or may not be able to depend on $_SERVER['DOCUMENT_ROOT'].

Say: config.php

<?php
define("HOST", "http://example.com");
// Whatever else you might need on all files.

Then every file that needs it, put this at the top

<?php
include_once(dirname(__FILE__)."/config.php");

// Keep in mind this path is relative to current file, so if you are 3 sub-folder keep
// include_once(dirname(__FILE__)."/../../../config.php")
?>

...

<a href=<?php echo HOST;?>/relative/path/to/document.html">...
ymmyk
  • 101
  • 9
0

Instead of doing this, you can add below line to your head tag. Now you can give all urls relative to your root. Now, when you upload to server or work on localhost. Just change url here.

<base href="http://mydomin.com/" />
  • Thanks, but that's not in the scope of the question as URLs won't be absolute. Also, there's [a number of complications with the `base` element](http://www.pitstopmedia.com/sem/base-tag-seo), while it also doesn't work in IE8 – Baumr Apr 14 '14 at 10:28
0

Here is a solution that works both on remote and local servers and doesn't require to change the domain name:

$protocol = isset($_SERVER["HTTPS"]) ? 'https://' : 'http://';
$url_base = $protocol . $_SERVER['HTTP_HOST'];

With these 2 lines you won't need to change the code if you change your domain name and also you won't need to change it if you switch between HTTP and HTTPS. Feel free to change variable names as you prefer.

So then your code for links would look something like this:

<a href="<?php echo $url_base; ?>/relative/path/to/document.html">link</a>

IMPORTANT UPDATE REGARDING SECURITY:

There is however a security risk with this solution. Here's an article on it.

The $_SERVER['HTTP_HOST'] and $_SERVER['SERVER_NAME'] variables can be changed by sending a different Host header when accessing the site:

curl -H "Host: notyourdomain.com" http://yoursite.com/

Doing that, any URLs that used $_SERVER['HTTP_HOST'] or $_SERVER['SERVER_NAME'] would use notyourdomain.com.

Taking this further, imagine an attacker fills out a password reset form with your email and changes the Host header. The password reset email would then direct you to their site. If you’re paying attention to the domain, you’re fine, but normal users don’t and that’s why phishing attacks work.

So use it with caution or better avoid using it.

Here's a way to deal with multiple environments from the linked article:

When dealing with multiple environments, you can use $_SERVER['HTTP_HOST'] and $_SERVER['SERVER_NAME'], but only to check which domain you’re on and then manually set the correct URL. You could keep it simple with an array of valid domains:

$domains = array('domain.com', 'dev.domain.com', 'staging.domain.com', 'localhost');
if (in_array($_SERVER['HTTP_HOST'], $domains)) {
    $domain = $_SERVER['HTTP_HOST'];
}else {
    $domain = 'localhost';
}

You can also make it a bit shorter:

$domains = array('domain.com', 'dev.domain.com', 'staging.domain.com', 'localhost');
$domain = in_array($_SERVER['HTTP_HOST'], $domains) ? $_SERVER['HTTP_HOST'] : 'localhost';
Dmitry Gamolin
  • 934
  • 1
  • 12
  • 29