Best practices with multiple directories in HTML - php

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.)

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.
Home

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)

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"/>
</form>

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"]).'/">';
?>

Related

can I use magic constant __DIR__ in links?

So, I have a question regarding paths in links. Here's the problem: In my assignment all my links are broken (not all but half of them don't work).
html_start.php includes nav.php and start_html is included in /admin/index.php and so on.
public_html
html_start
nav
styles.css
admin
index.php
user
index.php
index.php
First I've tried using absolute path eg. a href = "/user/index.php" but the assistent warned me that it leads to homepage of my university not my index.php.
If I use relative links, half of them work do to the includes.
Sadly all of these work in my environment but not when it's uploaded to my school so I don't know how it will behave until I upload the assignment and I have only one attempt to correct it.
Now, i use include in almost every page - eg. include( __DIR__.'/app.cfg.php') and that apparently works.
So my question is can I do the same with links? I've read somewhere that it doesn't do the same thing.
Looks like you're working in "root" (localhost?), where absolute links are fine, but when the site gets set up at your school's server, then absolute links point to the school's domain instead of the subdirectory where your project is.
What you need is using <base> tag in combination with relative links. Note that it may mess up your css/js/images, so you'd need to update all paths to be relative (not starting with /). Here's an example:
<html>
<head>
<base href="http://example.com/"/>
[...]
link
The link above would point to http://example.com/dir/page.html. Basically, setting an URL in base tag sets what is the "root" of your website, and all relative links will respect it. You can store the value of base in your site's config and echo it in the template, so when your site is set up on another server you'd update the config file and all links/images/css/etc would work.

php script includes html in different directory

I have a form handler which is written in PHP and resides in a different directory than the html files. When the handler runs, it needs to include one of the html files. The html files have relative hrefs in them, which break because the page was served from the PHP directory, not the html directory.
For example, index.html contains
<link rel="stylesheet" type="text/css" href="css/site_global.css?4013920463"/>
These links are produced by Adobe Muse and expect that "css" is a subdirectory under the location of the html files and that the page was served from the html directory. Again, since I'm serving the page from the PHP directory, the relative links break.
Short of putting in absolute paths for the hrefs, is there any other technique I should consider? I really don't want to put in absolute paths because they will break for other reasons.
Ideally, I'd like to use some sort of method that allows me to set the "working path" in the browser - so that I can tell it to fetch hrefs from the right place.
Relative paths in a browser are computed based on the current page path (see here). If you are looking at http://foo.bar/one/page.html , the site_global.css path will be http://foo.bar/one/css/site_global.css .
If I understood your question, you can use the element to set a base URL for all the relative links in the page.
See here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
try $_SERVER['DOCUMENT_ROOT'], gives the path to your base directory with current working dir
or
try echo realpath(dirname(FILE));

Best way to deal with relative paths/base tag

OK, so I've run into an issue with nested php includes, and I want to know what is a good compromise of best practices and ease-of-use.
Here's my website structure:
root
- index.php
-/include
- header.php
- footer.php
-/articles
-article-1.php
-/css
-style.css
So here's the issue: Inside index.php I have an include "include/header.php". Inside header.php I have many relative paths such as <link href="css/style.css>. And inside article-1.php I also have include "include/header.php".
So the index file works. But the article-1 file can't see the css file because the relative link is now looking for /articles/css/style.css. I found out about the <base> tag, and have set that in header.php, and it's fixed all my problems except for anchor links (which I can work around with javascript if I HAVE to), but I'm still concerned about what best practice is. How should I go about doing this correctly without having to prepend every single relative link with a huge php line and also without having to use a javascript hack to make anchor links work?
Thanks!
I ended up using a <base> tag in the header, and then wherever I needed anchor links I used php like so: <a href="http://<?php echo $_SERVER[HTTP_HOST] . $_SERVER[REQUEST_URI];?>#">
This makes the link go to the current page with a # added to the end, so it's the same as using <a href="#">
Let me know if you think I could have done this a better way! Thanks!
I think you can go up a directory with "../", current directory is "./"
So from root/articles/article-1.php, you would get to your stylesheet with ../css/style.css
<link href="../css/style.css">
In my opinion the best practice for this sitution is to go back to the root directory, provided that your project is in the root of your server/webspace.
Use a "/" in the beginning of the links, which is an absolute path.
Example: /css/style.css IS ACTUALLY root->css folder->style.css file

.htaccess redirect subdirectory as query string in php

This is hard to explain, so hopefully I'm understood in my question.
(1) I want to create "SEO friendly" links that remove the query string from a web site. There is only one variable, let's call it "page". Here is the following code for my .htaccess file.
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^(.*)$ index.php?page=$1
This works in providing the proper redirect. So /applications/ will send to index.php?page=applications.
(2) My index.php will include a view page based on the value of $_GET['page']. Here is some sample code below:
switch ($_REQUEST['page']) {
default:
include ("home.php");
break;
case "apps":
include ("apps.php");
break;
}
There seems to be no problems so far.
(3) Let's make apps.php an exact copy of home.php. home.php loads just fine, but apps.php will not load linked CSS and JScript pages. When apps.php is loaded, it thinks it is in the /apps/ directory. To load the linked pages, I would need to insert a "../" in front of the file name. Then it displays correctly.
So my question is -- How can I properly write the .htaccess file so the home.php and apps.php page can be identical files and produce identical results, instead of the apps.php file being treated as if it were in the /apps/ directory?
First, I should apologize as I don't have a solution which involves making changes in the htaccess. My solutions are of a different nature.
I think the problem can be solved if you have a config variable,preferably in a config file, which will hold the root folder for images, js etc. Most of the time its public_html, the document root, where the url of your website points to. so your config variable could look like:
$base_url = 'http://www.mywebsite.com/';
The config file should be included in index.php unconditionally.
So, when you include any js or images, you do it like this:
<script type="text/javascript" src="<?php echo $base_url;?>js/global.js" />
<img src="<?php echo $base_url;?>images/gradient_green.jpg" />
If you include the config file in index.php, all the files you include based on switch-case conditions, will be able to use the $base_url variable.
Another possible solution is to use the base tag. Look it up here:
http://www.w3schools.com/TAGS/tag_base.asp
I hope this helps.
use absolute urls for js, css and images on your pages (starting with a slash).
/js/main.js instead of js/main.js
You can't do that with .htaccess unless you do an external redirect (by adding the [R] flag to your RewriteRule). But then you expose the query string, which is what you wanted to avoid in the first place.
The reason it can't be done: It is not apps.php which "thinks it is in the /apps/ directory" - it's the browser which "thinks" that. In the page source generated by apps.php, you send relative URLs back to the browser, and now the browser will request these resources relative to the location of the page it asked for. For the browser, the page it got is in /apps/, no matter what rewriting you applied internally on the server side.
So the options you have are:
Do an external redirect with your .htaccess (and defeat your original purpose ;-)
Change the URLs dynamically with PHP while processing apps.php etc, as you said (prefixing ../ to the URLs)
Use absolute URLs, just as #nobody has suggested in his answer.
The last one is the only real option IMHO.

mod_rewrite changes the current dir

I have a php file that loads an article from a db based on the given variables. There is also an .htacces file in the root of the site. I used this in the htaccess to redirect
RewriteRule
^articles/([a-zA-Z0-9-_\s]+).html$
template/index.php?action=viewarticle&alias=$1
after redirecting, the page shows fine but the html in the page goes wrong, for example:
media/2011/02/21/logos.jpg turns in to articles/media/2011/02/21/logos.jpg
This happens because the htacces is redirecting. Is there anyway to do this redirect while keeping the root dir unchanged?
This happens coz the htacces is redirecting.
No, this happens because the browser thinks that
example.com/articles/my_article.html
is a resource in the /articles sub-directory, and treats all relative URLs as relative to /articles.
There is no way to change that behaviour.
You will need to start using absolute image references, or relative image references that consider the additional directory:
<img src="/media/2011/02/21/logos.jpg"> <------ recommended
<img src="../media/2011/02/21/logos.jpg">
you could also use <base> as suggested by #Boris but absolute paths (or full URLs) are a vastly cleaner solution to the problem in my opinion.
First, what do you mean by "html in the pages goes wrong":
Is it the link showed in the status bar?
Is it the actual href? If it is, you probably use some view helper which construct your "base url"
Maybe you "link" your resource without specifing an absolute path (using /), then your resource are "relatively" linked to current page (/articles/)
.htaccess don't change anything in your code.
There is an html element which allow you to define base url used everywhere in your page.
<base href="/root" />
if you have for example Article 12 then when clicking on the link, you will redirect to /root/articles/12
Also, mixing Pekka's answer with Boris', you should define somewhere in your application which is the root path of your application and output all paths as absolute, prepending the base dir you defined earlier.
for example: in config.inc.php
define("ROOT_URI", "http://myserver.com/myapp");
everywhere:
<img src="<?php echo ROOT_URI;?>/media/2011/02/21/logos.jpg
This is like using the base element as Boris suggested, without using it (I also dislike base), and makes your application able to work in whatever folder under the webserver it is stored.

Categories