views:

71

answers:

4

I haven't found a clear answer to this question (but have determined the HTML tag is more trouble than it's worth.)

When you're working with multiple directories on a website, how do you make sure relative links to the rest of your site work as you change your current directory? I don't want my link to "/index.php" to actually link to "/support/index.php" when I go to the support directory.

We're using PHP, so I could use output buffering to change links, but I want to see if others have any good ideas. Could also implement it through Smarty in one way or another. I haven't built a website from scratch that has used multiple directories simply because I don't know of an easy way to deal with this, but the problem shouldn't be too difficult.

(Running on IIS, but obviously it would be better to let it work on any server.)

+4  A: 

you could declare a base_url variable, or declare a constant containing your base url

e.g.

DEFINE('BASE_URL', 'http://example.com/');

when using links

e.g.

<a href="<?php echo BASE_URL; ?>index.php">Home</a>
Flakron Bytyqi
This is a good solution, setting up the URL's like this is called using the 'absolute path'.
evolve
That's what I originally considered doing, but I figured it wouldn't hurt to search for a method that doesn't require me to put a variable in front of every link, every image, etc. That's why I considered using a find/replace on the buffered output.The other issue is allowing both www.example.com and example.com to work.... I already got burned for that because someone had only allowed www.example.com through their content filtering and not example.com
Guttsy
Switching between http:// and https:// makes this a bit tricky too.
Guttsy
This is the way I prefer. +1
Unicron
@Guttsy it's easily possible to switch by finding out what protocol you're on at the moment, and defining `BASE_URL` accordingly.
Unicron
Works for me (although I'll still apply the BASE_URL with output buffering because I can.)
Guttsy
adding domain name is overkill. no smart developer will use it. excluding SO theorists of course
Col. Shrapnel
@Guttsy how come you're using all this machinery - constants, domains, variables, PHP code in the every url, when you need none? Because simple `/` doing exactly the same
Col. Shrapnel
+1  A: 

You already have everything you need

how do you make sure relative links to the rest of your site work as you change your current directory?

we're using absolute links for that

I don't want my link to "/index.php" to actually link to "/support/index.php" when I go to the support directory.

Lucky you, it will never happen

/index.php is absolute path and will never point anywhere beside /index.php.

/ is not just for decoration. It the meaning of slash at the beginning of the path is "root directory". So, /index.php means index.php placed in the root directory.
/support/index.php means index.php placed in the support directory which is placed in the root
easy-peasy. just always use absolute path (not URL which is senseless)

Col. Shrapnel
Will not work for portable web applications that may be used in a sub-directory. If that's never going to happen, it will be ok.
Unicron
@Unicron are you talking of silly HTML files being edited on the local windows system with no web-server installed? oh yeah that can be a problem
Col. Shrapnel
Yes, if I keep everything absolute in that fashion, that's fine. There is a high likelihood that everything will stay at the root of the website anyway. (However, I did mess up in writing that question... I didn't exactly intend "/" to mean root. Maybe "./" or no slash would have been better.)
Guttsy
@Col no, I'm talking about a web application that might be installed on any kind of server in any kind of subdirectory (e.g. `example.com/blog` for a blog app).
Unicron
I am amazed by the fact that I have to explain such a darn basic things. Everyone in the world just using absolute path but local crazy inventors cant stand such an easy solution. they need at least a framework to solve path problem
Col. Shrapnel
@Unicron do not solve a problem before it arises. Yu will need a variable to address these files through a filesystem as well. So, it will be another story.
Col. Shrapnel
@Guttsy no matter what did you intend. you have to use a `/` slash anyway. dot-slash `./` is just a substitution for the relative path as though you havent typed anything. `./index.php` is the same as `index.php` with no slash. So, you have to learn absolute paths which is really basic thing for the programming.
Col. Shrapnel
@Col you have no idea what you are talking about. Building a web app so it is insensitive to being hosted in a sub-directory is simply good practice. Every good web app out there is constructed that way. I'm not saying everybody must do this for every little project. But your notion that everybody who works this way is an idiot is plain arrogant and short-sighted.
Unicron
@Unicron are you saying that every link in the HTML code in this every good web app should be relative? Thank you for sparing this piece of wisdom.
Col. Shrapnel
@Col no, I'm saying that specifying a root directory stored in a configuration file on server side, and prefixed for every resource is the only way to go when portability is necessary.
Unicron
@Unicron I am talking nothing against that. That is another matter, not being asked. The OP's question is merely about **HTML** code, where links should be absolute, no matter how it set - with some variable or manually.
Col. Shrapnel
@Col the OP's tags say `php` `template` `base`. Anyway, you may be right. Hard to tell from the question.
Unicron
A: 

Add <base href="http://www.domain.com/"> to your <head> tag. This will make all relative links start from the directory given as href. Then use relative links like support/index.php not beginning with/ (i.e. not /support/index.php)

Note: Make the <base> tag the first tag in your <head> section, as all links after that will be interpreted from that base dir. (e.g. <link href="relative/path"> will already use the base dir if it is defined above.

Advantage: you can move your whole page to a subdirectory like http://www.domain.com/page and only have to change the <base> tag. If you use links like /support/index.php they will always start from the root directory (i.e. http://www.domain.com/)

Dynamic base dir for url rewrites:

<?php
    if  (preg_match("/https/i",$_SERVER["SERVER_PROTOCOL"]))
        $protocol = "https";
    else
        $protocol = "http";
    echo '<base href="'.$protocol.'://'.$_SERVER["HTTP_HOST"].dirname($_SERVER["SCRIPT_NAME"]).'/">';
?>
opatut
dirty patch and overkill
Col. Shrapnel
that's going even worse
Col. Shrapnel
Look @Guttsy, how it happens - a dirty and long way to emulate *relative* directories :)
Col. Shrapnel
@Col. Shrapnel: explain "dirty patch" please
opatut
you're doing an improvement to the thing, which don't need any improvements. Ever used such a monstrous construct you've posted here in the real life?
Col. Shrapnel
you guys tend to complicate things. dunno why. why not to use simple solution? why to add unnecessary code? Look at the SO source for example. Do they use that ridiculous tag? No. Ever wondered why? That's just useless! Noone needs it just to address a resource, when absolute path is o.k.
Col. Shrapnel
Think about the total page being moved to a subdir. Absolute links from the root dir will be wrong then.
opatut
Nothing bad will happen with such a moving. you can move /support.php anywhere while your images will remain in place, thanks to absolute path /img/bullet.php
Col. Shrapnel
"while your images will remain in place" is maybe not what I want - lets stop this discussion
opatut
just answer me one little question. did you ever use the code you posted here?
Col. Shrapnel
yes why not ???
opatut
well, it will call index.php from the /support directory when you switch to it. that's what the OP feared
Col. Shrapnel
as for the base href tag, what if I would add a link to the image in the other directory? which real path is /avatars/face.png? How to avoid your base href patch? You guys just copy and paste answers from each other, not even trying to think
Col. Shrapnel
See that: "Dynamic base dir for url rewrites" - This is not for the OP, its for the community where maybe someone will have the same problem I had when i wrote the code. I redirect everything to my index.php, but relative paths will start from the url the browser requested (www.domain.com/category) but that dir does not even exist so I use <base> to let all relative paths start from www.domain.comOnly the first paragraph is the solution for the OP, the rest is additional information.
opatut
"You guys just copy and paste answers from each other, not even trying to think" - I flagged this as offensive... You don't know what I did or not, this code is not copied from anyone except me.
opatut
A: 

I store a “base” URI in two locations: (i) on the PHP/Zend Framework server, my configuration.xml file holds conventional values such as URIs; (ii) on the client side a more shallow, hidden <form/> holds other (less security compromising) values such as a base URI.

The form, by the way, looks something like this:

<form id="AppSettings" action="#">
    <input type="hidden" id="MyBaseUri" value="http://superuser.com"/&gt;
</form>
rasx