I am using a .htaccess file to rewrite all URI addresses to take the user to index.php where some code determines which file to include based on the URL.
If the URL however is in a subfolder from that of the header the include function is not fetching the file.
eg.
index.php includes a file located at examplefolder/content/page.php. That file then includes a header on the content page but include('../header.php'); is not working. The URL is example.com/news/latest.
How can I get this to work?
You can use the chdir() function to change the current working directory on the webserver to get your relative paths to work correctly.
To see what the current working directory is, just echo getcwd(); Once you do that, you may realize that you don't need your relative paths and you can just structure the include based off of whatever your current working directory is (if you're rewriting to index.php, then all of your pages will start from the same base path, namely the web root).
If you rewrite all URLs to /index.php, all requests will be working from the / directory (i.e. document root).
So if you are including examplefolder/content/page.php and from there you want to include the file examplefolder/header.php, then that is exactly what you would write, because including a file does not change the working directory in the current thread of execution.
E.g.
include('examplefolder/header.php');
Related
I have a PHP page on my site in a sub folder called Articles.
The page is article.php.
The article.php page requires a common php page called _head.php. This provides the header for the pages.
_head.php is located in the root directory.
The /Articles directory is a subdirectory within the root.
I've included this _head.php page in article.php this way:
<?php include("../_head.php"); ?>
And this works fine.
The problem, however, is that the image elements within _head.php are located in the 'images' subdirectory (also off the root) and are referenced relative to the _head.php being in the root, like this...
<img src="images/services.gif">
So if I use _head.php for files on the root, it works great and shows all the images correctly. But when I include _head.php into a php file that is not in the root, but instead in a subdirectory like /Articles (/Articles/articles.php), the images do not show up.
Do I need to change the _head.php file in how it references the images or is there some code I'm supposed to include in articles.php when including _head.php that tells it how to use _head.php?
I'm concerned about using all absolute paths because if I have to move this site to another server this is going to cause me issues.
Mentioning what I follow not going to the hierarchical complexity,
For any PHP file that is being imported into another PHP file in root simple include/require_once (<path>).
For any file below root accessing other file anywhere within the root I use include/require_once (../<path>).
For accessing files which are outside the root, I use the absolute path of that file.
Working on few php files what I have seen using absolute path is the best thing in two ways, a) you are free from remembering the paths of different files and b) if you are using CDN or if your files are on different servers then this is very helpful. Anyways opinions may vary, this is my personal view/choice.
I'm trying to create a constant which defines my web root dir, which I can use for constructing paths for requires, header redirects, images, etc.
I need the constant to work when used in files in the root folder and sub folders. I know I could easily hard code the paths with ../ etc, but the main reason I'm trying to get this to work (apart from clean code) is so I can re-use the code on various sites on different servers, where the path may vary.
my dir structure
/
index.php
/library
libSetPathRoot.php
Document Root
echo $_SERVER["DOCUMENT_ROOT"];
Returns: /home/james/web/sites/
The "sites" dir contains various document roots defined in /etc/apache2/sites-available (so I can work on different scripts).
File contents
/index.php
require_once('library/libSetPathRoot.php'); //works fine.. of course
/library/libSetPathRoot.php
define("PATHROOT", realpath(__DIR__ .'/..').'/');
The above returns my root correctly:
echo PATHROOT;// /home/james/web/sites/site3/
I've tried the following and various other code to define a root path.
These, and others, didn't work for redirect(), include(), nothing at all:
define ('PATHROOT', getenv("DOCUMENT_ROOT"));
define ('PATHROOT', basename(dirname((__DIR__))));
echo PATHROOT;
Everything else seemed to return "site3" only.
The working define works for include() and require() regardless of where in the dir structure it is placed. ie if in file in sub dir to root calling root or other sub dir to root, in a file in root, included file etc.
But I just cannot get this working for header() redirect. Again, regardless of where I use it - root scripts, sub folder scripts, included scripts. Maybe I need another approach, but have read numerous options and tried them extensively (half a day spent).
Why is my define working for includes but not header redirect, and how can I make it work on all? Or do I have to use two methods, one for include and one for redirects?
Edit
Example header redirect I tried:
header('Location: '.PATHROOT.'page-not-found.php');
Returns a 404 for: /home/james/web/sites/site3/page-not-found.php
(the file does exist)
You can't do such file redirection with header(). It sends HTTP headers to the browser which should be in browser accepted format. But you are sending some local(server) file path. Which is obviously not working. you have to send a url for redirection eg. header("Location: http://example.com/page-not-found.php")
See the php documentation http://php.net/manual/en/function.header.php
You can use the header() function to send a new HTTP header, but this must be sent to the browser before any HTML or text (so before the declaration, for example).
header('Location: http://www.example.com/');
The URL must be an absolute. See RFC 2616. But in most cases a relative URL will be accepted too.
However header function and include function expect completely different parameters!
The header function expect URL and include function expect file-system file object.
Eventually you can tune the header function using relative FS path definitions like "../../newHeader.php"
I'm having a spot of bother with php includes. I have the following file structure
htdocs
index.php
login.php
php_includes
db_conx.php
check_user_status.php
within the db_conx.php file i've creates a variable $number = 10; for testing.
The db_conx file is included in the check_user_status.php file with the following code:
include_once("db_conx.php");
and that is working fine - i.e. i can echo $number and get 10.
However, I'm including the check_user_status.php file at the top of login.php with this code:
include_once("php_includes/db_conx.php");
and on this page I'm unable to echo out $number on this page (check_user_status.php).
I'm going to need this script included in many pages (since it checks whether the user is logged in or not). Am I doing something strange with the paths?
For relative paths you need to do this.
include_once("../php_includes/db_conx.php");
To break this down.
Your Current working directory is initially going to be htdocs/ if your hit that file in your browser.
the .. back you up one directory level (so the directory that contains both htdocs and php_includes)
then you want to follow down php_includes to get to db_conx.php.
This will become a problem when you do a file in a subdirectory. Assuming you and a page2.php to a htdocs/subpages/
Now if we follow those same steps we are not going to arrive at the same location.
A better approach is to get the path relative to an absolute location. I like using the document root (htdocs in your case), so:
include($_SERVER["DOCUMENT_ROOT"]."/../php_includes/db_conx.php");
will refer to the same place on the file system regardless of where it is used.
I think you can use __DIR__ magic constant
The directory of the file. If used inside an include, the directory of the included file is returned. This is equivalent to dirname(FILE). This directory name does not have a trailing slash unless it is the root directory. (Added in PHP 5.3.0.)
This will help you with nested included files, infact the file path will be always set automatically and you don't have to deal with absolute paths.
If your file structure is correct, assuming that php_includes is NOT a directory within htdocs, you would need to do:
include_once("../php_includes/db_conx.php");
I've taken over a site that caters for client access. They all access there own folder, and in the folder the files have an include with a relative path as below.
/core - contains all the actual files
/client/file.php -
<? include "../core/file.php"; ?>
but with the growing number of clients I want to go a level deeper and separate them better...
/uk/client/file.php -
<? include "../../core/file.php"; ?>
This is fine but when the files are included, they too have there own relative includes and this is where it breaks.
There are so many files I can't easily go through them to change all the include paths so I would like to maybe do a rewrite to fake the path?
I've tried this...
RewriteRule ^uk/$ /
But that doesn't work.
Any help would be greatly appreciated
This sound like a work for __DIR__, you can check documentation here
The directory of the file. If used inside an include, the directory of the included file is returned. This is equivalent to dirname(FILE). This directory name does not have a trailing slash unless it is the root directory. (Added in PHP 5.3.0.)
Otherwise you can still switch all your relative paths to absolute path and avoid any problem if some file are included in others.
As side note i would reccomend to not use php short tag <?...?>, I'd rather use long tags <?php....?>
I created initialize.php to define my project's root directory.
defined('DS') ? null : define('DS', DIRECTORY_SEPARATOR);
defined('SITE_ROOT') ? null : define('SITE_ROOT', DS.'works'.DS.'myproject');
I include it with something like this from any directory.
require_once("../includes/initialize.php");
and I include other files easier. I am going to upload the files to server, then I should only change the initialize.php file.
It works. But, when I use user friendly URL's, and call ajax files from it, I don't know my directory hierarchy to include initialize.php.
I don't want to do this:
require_once("/works/myproject/includes/initialize.php");
for every file. Because it is going to change when I upload everytime.
I don't want to use session or cookie for everyuser.
There should be a trick for this but I couldn't find. Is there a way for getting project root from anywhere while using user friendly URL's and ajax calls?
I fixed it.
when I call it with ajax it's ok. But I included it as php too for some conditions.
Because of current and the ajax files are in different folders, it crashed.
So, when I change it to only require initialize.php when called with ajax, problem solved.
If you're using Apache, you could try adding your includes directory to your include_path directive.
Find the current value by doing a phpinfo() and look for include_path and then try re-declaring it in your top-level web directory and add the absolute path to your includes directory.
So if the default value is:
include_path = ".:/usr/bin/php:/some/other/directory"
just copy-paste the same thing in your .htaccess file but add your include directory on the end, separating it with a colon.
include_path = ".:/usr/bin/php:/some/other/directory:/works/myproject/includes"
and that way you shouldn't have to reference the absolute path every time.
This all depends on the permissions your web host gives you. There are other (easier) ways to do this, but I find that most of them are usually restricted by hosting providers, and manually setting it via .htaccess is usually the most dependable way to get this done.
Here's a page listing a few different ways: Five ways to create include path for PHP
Simply doing this:
require_once("../includes/initialize.php");
is enough because PHP doesn't look at your friendly URLs. It includes whatever you give him to include relative to your script.
Also there is $_SERVER['DOCUMENT_ROOT'] that will give you an absolute path from your root directory.
It is a good approach to define all your directories in a common file as you added initialize.php. You will have to include this common file in every file on the project. User friendly url's have no effect on the file inclusion.