In my php script I created a constant variable that defines the base url to be put in my hyperlinks, but do I really need this?
Here is an example of what I mean.
I have this:
// base url is only defined once and reused throughout
define("__BASE_URL","http://localhost/test1/");
print '<a href="'.__BASE_URL.'index.php?var1=open/>Open</a>';
(I have a lot of these spread throughout my script.)
I tried this and it works:
print '<a href="index.php?var1=open/>Open</a>';
So which way is the proper way on doing this? I noticed the second way even works on loading images, css, and javascript files.
It really comes down to how you're structuring your site. Relative URLs are great (by doing href="index.php" you're reallying saying href="./index.php"), but they can start to become messy when you begin spreading pages over multiple directories.
Personally I like to base all of my relative URLs off of the root directory, meaning that all of my URLs start with a slash ('/'). That way it doesn't matter if my script is in / or /admin, as I will always have a constant reference point - the document root - as opposed to some relative directory in the structure.
Your first example, storing document paths in variables, really starts to come in handy when you begin developing larger systems where you want the paths to be configurable. For example, maybe you want your system admins to be able to define where images are pulled from, or where the cached downloads are.
So really consider your use cases and size of your system.
Also keep in mind that if you ever move the script to another server that your URLs and directory structures may change, which could cause havoc (ex., you might have your script moved to a different subdomain, into the document root, etc.). A lot of people will drop in Apache's mod_rewrite in this case.
It depends. Without the __BASE_URL, your link will be relative to the current document. In your case, that means index.php must be in the same directory as the file that has the index.php link on it.
If you have the __BASE_URL, then the link will work no matter where its containing file is located (i.e. doesn't have to be in same directory as index.php).
Another option is to use a starting slash only. Then your link will be relative to your domain root:
print '<a href="/index.php?var1=open/>Open</a>';
In other words, the above link would point to http://localhost/index.php.
It sounds like your question is regarding absolute vs relative URLs. Are you going for portability? It's generally best to use relative URLs, especially if you plan to work in a test environment and then later transfer files to production.
Related
Recently I'm reading some webpages and I found there are a lot of usages like:
href="/./foo/bar.php"
Isn't this the same as href="/foo/bar.php"? Or is this there something I don't know about the differences between the two ways?
The relative URL /./foo/bar.php is not the same as the relative URL /foo/bar.php. The former has /. at the beginning.
They have the same effect, though. When URLs are processed, relative URLs are resolved to absolute URLs, and in this process, if a relative URL starts with /./, it is replaced by /. Reference: STD 66, clause Remove Dot Segments. (Such a reference is turn resolved as relative to the server root, basically something like http://www.example.com/foo/bar.php.)
So these two relative URLs always resolve to the same absolute URL. There is in general no reason to use the longer URL, which looks more complicated and confusing.
Note that this has absolutely nothing to do with folders or files. It is simply string manipulation, based on the URL standard. Whether URLs get mapped to folders and files is at the discretion of a server and in principle invisible to the world outside it.
I don't get it.
When trying to include files from different directories, i'm sure i must be missing something real simple.
Site structure is like this.
if i include("includes/header.php); from inside the /reports/top_sellers_report.php file, the call to the css file doesn't work.
To make it work i must put ../styles/styles.css
But then, if i open "product_dtails.php from the root, it too includes the header, and then the css file won't load and i need to remove the ../ to make it work.
I can't win...
Am i missing something? 4 hours of searching online suggests i am!
Your problem is not really PHP-related. Just look at the URLs:
http://www.example.com/
http://www.example.com/reports/
http://www.example.com/styles/styles.css
Depending on where you are on your site, the relative path to styles.css might change, thus when you access http://www.example.com/reports/ you have to use ../styles/styles.css, wheras in http://www.example.com/ you have to us styles/styles.css.
Probably the easiest way to fix your problem is either by using the absolute URL like http://www.example.com/styles/styles.css or the base-path /styles/styles.css instead of ../styles/styles.css. I recommend the latter.
I think you should look into using an MVC approach as this would probably help you organise your code better:
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
The include statements are evaluated on the server, so wherever you are including the file from, you need to specify it relatively from there. The CSS 'include' is being evaluated in the browser, so you need to make the file path relative from that directory.
I suggested looking to the MVC approach as it helps you to manage your code and separate the different parts of your website into distinct parts which should help you avoid this issue.
I suppose you can refer to you stylesheet absolutely though (ie http://www.mywebsite.com/dir/dir2/stylesheet.css) on each page and that would also work.
as far as I know, include is relative to your index so you have root/index.php
within index.php you should use include("styles/style.css")
within includes/header.php you'll need to add the ../styles to redirect you to root and then to your styles folder and so on
if you open directly product_dtails.php it will act like the index.php, so you need to just use styles/style.php
I have a common header.php to include in virtually every page of the website. I have relative links to different resources in the header.php file. As soon as I include it in other pages which are located in different sub-folders under the root folder, some of the links would break. I can make all the links in the header.php absolute. Now another problem pops up: If you move the application to another domain and put it somewhere under the wwwroot, the absolute links will not work. I couldn't find a way in PHP to extract the part of the URL which is the root for this application. I ended up define a variable for the application root and prefix every link inside header.php with this variable. This way, I only need to change one variable when this application is moved from one place to another.
I am wondering if there are other better ways to handle this kind of situation.
Your feed back would be much appreciated.
Edit: hoping to receive more feed back.
You write it's a common header.php file, like with the central variable, you can do make use of the <base> HTML element - but this is limited to HTML.
You can create yourself a mapping function that is able to resolved absolut URLS to the request URI, or that is able to resolved relative URLS to the context they come out of so that they can be mapped absolutely relatively to the request URI again.
Then you can implement a output filter that is handling URIs on it's own and you can do some special prefixes for special treatments.
I have several files in my web folder, including these two:
/mydocroot/include/somesubdir/include.inc.php
/mydocroot/include/settings.inc.php
where somesubdir is a symbolic link to another directory on my disk, to a path named, eh, let's say /anywhere/else.
Inside include.inc.php, something like this is written:
<?php
require_once "../settings.inc.php";
?>
In my opinion, that should include /mydocroot/include/settings.php... But guess what happens: PHP tries to include /anywhere/settings.inc.php, instead of /mydocroot/include/settings.inc.php.
It seems like PHP automatically resolves symbolic links.
How can I avoid this and include my settings.inc.php file?
I just had a similar issue. You can do it by using $_SERVER['SCRIPT_FILENAME'] variable, that displays the requested file, so in your case it will be /mydocroot/include/somesubdir/include.inc.php, even if somesubdir is a symbolic link. To include a file that is one level lower instead of doing
require_once "../settings.inc.php";
do this:
require_once dirname(dirname($_SERVER['SCRIPT_FILENAME'])).DIRECTORY_SEPARATOR."settings.inc.php"
Documentation about $_SERVER variables
The most straight forward solution is to always use absolute paths. There are multiple ways you can do this, from hard coding the path every time you need it, to hard coding the path once in the top of your script and referencing that, to dynamically figuring it out and setting it once at the top of your script.
The third option is what most off the shelf CMSs use to be able to run without complete knowledge of your file structure.
Why is it that you're using a symbolically linked directory in this manner?
The solution is to create a basepath variable. The best way to do this is to include the following at the top of your script and then reference it
$basepath = dirname(dirname($_SERVER['SCRIPT_FILENAME'])).DIRECTORY_SEPARATOR;
You can then reference the basepath in your includes, requires, etc. Therefore,
include "../myscript.php";
Would become,
include $basepath."myscript.php";
If you are back ticking further, you will have this:
include "../../myscript.php";
Would become,
include $basepath."../myscript.php";
You must nest the dir_name functions twice, plus one more time for each additional folder you need to backtick through. You MUST get all the way back to the folder where the symbolic link exists.
I consider this issue a major design flaw with PHP. I can't think of a single instance where accessing backticked files relative to the actual file would be desirable. In all situations, including virtual hosting, it ONLY makes sense to regress back along the linked path, never the target path.
You can use is_link to check if a file is a symbolic link. If it is, use readlink to get the absolute target.
But, in ten years of php development I've never had cause to use symbolic links. As Jason suggests, I've always defined or deduced an absolute path once, then used that throughout my app to make all file paths absolute.
Is the html <base> tag safe to use in terms of browser support? Or should I generate a root path with PHP which i then add like this somepage which makes up a absolute url.
using the base tag like this <base href="<?=BASE?>" /> I am then able to use links like this
somepage
now I am fully aware that it would be much easier to just do this without using the base tag:
somepage
but how do I test locally then with a base url of http://localhost/testsite/ ???
edit:
thanks guys, your the people who make the stackoverflow community so great :)
My advice would be to use absolute URLs beginning with a slash, and just set up a virtual host that uses /localhost/testsite/ as its document root. Then you could leave the absolute URLs and just access your site at something like http://testsite/ locally.
You've definitely given this some thought but I would like to throw one more consideration into the mix. If you are writing a web application, you should construct it in such a way that you can install it into any sub-directory in the future and it will continue to work with little change.
This means that href's, src's, action's and even HTTP Location headers will need to be aware of such a change. That's why I recommend prepending your uri's with <?php echo SITE_BASE ?> or whatever you want to call it.
Debate can rage on as to whether SITE_BASE should contain a trailing slash.
I like the first option, outputting a base directory in PHP tags
somepage
the very best. This makes your site independent from which directory it is installed in (you may not be able to change virtual host settings on shared hosting packages). It is also easy to outsource image files to a different server/subdomain if ever need be.
<base> is safe to use in terms of browser support, but I personally recommend strongly against using it for reasons of code maintainability. <base> changes the rules for how URLs are processed; you need to keep the base in mind for all relative URLs; and is very easy to overlook. From a programming perspective, it feels like a dirty fix.
Comming back to this question 2 years later, I now realise that the best way to handle absolute URLs is to put the URL into a wrapper function, for example like this:
somepage
the wrapper function then gives you full control over the URL handling
function url($url){
if(strpos($url,'/')===0){
return 'http://localhost/testsite'.$url;
}else{
return $url;
}
}