PHP broken relative links in nested directories - php

I'm sure I'm missing some simple explanation, but I want to confirm - so assume I know very little.
I have a directory structure like so (for the time being) of:
My main site (localhost/project/ on my testing server, and C:/xampp/htdocs/project on my HDD) with these files and folders:
Root
graphics
variousgraphics.png
support
stylesheet.css
templates
header.php
footer.php
initialize.php
you
default.php
index.php
anotherfile.php
Up until I created the folder 'you' everything was fine, i.e. I included the initialize file for index.php as <?php include(templates/initialize.php) ?>
But when I decide to include initialize.php using the above method for the default.php file (inside 'you'), it errored out with Warning: include(templates/initialize.php) [function.include]: failed to open stream: No such file or directory in C:\xampp\htdocs\photoquilt\you\default.php
So naturally I appended ../ to create <?php include(../templates/initialize.php) ?> but then of course that didn't work because the files referenced inside initialize.php weren't appended in the same way, and so I get to here.
It's worth noting for me, an echo of $_SERVER['document_root'] leads to C:/xampp/htdocs
So in summary:
Is there any way to make sure all the link/paths work correctly irrespective of where the originating path was from?

In default.php you can define a constant like
define('ROOT_PATH', dirname(__DIR__));
or for php versions prior to 5.3.0
define('ROOT_PATH', dirname(dirname(__FILE__)));
and then use ROOT_PATH in all scripts to build the the file paths.
see
- http://docs.php.net/language.constants.predefined
- http://docs.php.net/dirname

There are a couple problems here as far as I can tell: the server-sided and the client-sided.
As for the PHP goes, you are doing it fine. Referencing the file by its relative path (../templates/initialize.php) is the way to go. There's another way of achieving the same, though I wouldn't recommend it: editing the include_path to add the root directory of your project. You can do it in an .htaccess located in the root directory, ie:
php_value include_path ".:/path/to/your/project:/usr/local/lib/php"
For the HTML part (images not loading, stylesheets not found), you can set a base href:
<base href="http://path.to.your/in-server/" />
The base href should point the root of your directory. All the images, stylesheets, etc in HTML must then be fixed to use relative URIs from the root of the project (graphics/variousgraphics.png).

Related

include_once in header breaks when an absolute path is used

I have my website on my local server (localhost - XAMPP). My website is broken up into three parts: 1)Header 2)Body and 3)Footer/Jscripts.
The header.php calls other basic files for the header section of the webpage. It works fine when I used relative paths, for example: include_once('./_css/main.css'); to call my CSS files or include_once('./_inc/metadata.php); to call my metadata for my pages.
The problem arises when I use an absolute path:
include_once('http://localhost/mywebsite.com/_css/main.css'); the same for the other files.
Why is that? This all started because I want to create subfolders because I had a general page, but now that I'm breaking it down to subpages I need a folder to contain the subpages
I was trying to include the css files and all the other resource files to the subpages, but they break using the relative paths method (./_css/main.css) being pulled from the header file located in the root directory. On the subpages, I'm using include_once('../_inc/header.php') to include the initial header.php file.
I want to avoid having to duplicate all the resource files from the root directory and adding them in the subfolder with their respective relative paths. That's why I was trying to use the absolute path method.
Any insight or clue would be appreciate as to:
Fix the 'Warning: include_once(): http:// wrapper is disabled in the server configuration by allow_url_include=0' error when using the absolute path.
2)Sharing css files in subfolders.
Using an absolute path may be a bad idea, what if you move from localhost to a real server? You'd need to make massive changes. Changing the project structure so that you could avoid all of this might be better, or if you really want to keep things as they are, use a variable.
<?php
$include_path = "whatever/path"
include('../header.php');
?>
and in header.php
<?php
include($include_path.'/my_css.css');
?>

Linking CSS file with PHP throgh all folders

INTRO
I am new to php. I love that it allows me to change one header.php file and it updates all over the site.
IF all - index.php, header.php, style.css, article.php, homework.php files are in the ROOT folder, everything works like magic, I like it. I use:
<?php include_once "header.php"; ?>
at the top of index.php, article.php and homework.php and the header appears.
to load css a regular =
<link href="style.css" rel="stylesheet" type="text/css">
is enough to have in my header.php file, because all the files are in the same directory.
MY PROBLEM
When the amount of articles becomes too large and I decide I want to put those articles in different folders, that is when stuff gets confusing and I would like to know a proper way to solve it.
New website folder structure
C:\xampp\htdocs\articles\homework.php
C:\xampp\htdocs\views\header.php and style.css
C:\xampp\htdocs\index.php
C:\xampp\htdocs\articles.php
Now please help me how to make homework.php file to load the css from the header.php? I manage to load the header itself with
<?php include_once "..\views\header.php";?>
BUT the css file doesn't load for some reason.
I read something about "basenames", "site roots", but don't know how to properly set them up.
The perfect scenario
The perfect scenario would be if I could have a basename variable that I can change, so when I make my server live I can just change the basename to the appropriate new server directory and because all the header.php and other blog files were linked to that basename, everything would change automatically. I have done too many manual directory rewriting to do it once again, please tell me a way to automate it :)
Thank you a lot!
p.s!!!!!! Before I even post this question I realized that the header.php is trying to load views/style.css, which doesn't make sense, because the style.css file is in the same folder as header.php now.. Somehow basenames, site roots are a must here I believe...
You can specify relative paths such as ../css - means up one folder then look in css folder or ../../ - means up 2 levels then look in css folder.
../../main/css/style.css - would mean up 2 levels then look in main/css for the file style.css.
The problem with using / or ../ etc is that if you decide to change the location of the resource you still have to change all your paths. Using a var you can simply change it to reflect the new location.
with PHP you can also getcwd() and dirname() and realpath() to get a string representing a location, you can then set a base variable for your files and 'path' down from it.
This way you can use the same variable to locate a file rather than different relative paths depending on the level of the file calling it.
DIRECTORY_SEPARATOR is also useful for avoiding errors between / and \ with linux and windows OS. However I believe Windows and Linux will both resolve /
Personally I like to set path locations to commonly used files such as /includes in config.php then I can use that setting from anywhere
In summary you are just either discovering a path using PHP or setting a path as a variable
$path = 'c:/htdocs/mysite/includes/';
then using the variable as part of the path name when you access the file
$_SERVER['DOCUMENT_ROOT']
can also be useful to identify your site home folder

Pulling in files from different folder

I am working on a webpage that is located in a different folder than the root folder. I'm trying to pull in the newsletter.css file, the header.php file, and the services.jpg file. The working page is located at Root/newsletters/newsletter-2020-01.php. The header.php file is located in the Root folder, the newsletter.css is located at Root/styles/newsletter.css and lastly, the services.jpg is located at Root/images/services.jpg. The working file (Root/newsletters/newsletter-2020-01.php) isn't pulling in any of the other files. I've looked for the answer on Stackoverflow and everything is saying to use ../file.ext but this isn't working. Any advice?
<link rel="stylesheet" type="text/css" href="../styles/newsletter.css">
</head>
<?php include("../header.php");?>
<div class="background_image" style="background-image:url(../images/services.jpg)"></div>
For server level files (pulling in PHP files etc. that are done on the server, not the browser).
Use: $_SERVER['DOCUMENT_ROOT'], it's a sure thing.
https://www.php.net/manual/en/reserved.variables.server.php
$_SERVER['DOCUMENT_ROOT'] it gives you the full path of your server to the root where your HTML etc. files are stored. From there you use the path to the exact file you want.
To see it in action: <?php echo $_SERVER['DOCUMENT_ROOT'] ?>
It will make more sense.
Ex. $_SERVER['DOCUMENT_ROOT'] . '/directory/myfile.php'
As for browser level files (files accessed by the browser, .css, .js)
Use an absolute path from the root, again, a sure thing.
Ex. <script language="javascript" src="/directory/scripts/myjavascript.js"></script>
Why?
Relative paths can be broken if the file moves around. It may be relative to FileA, but FileB may be in a different location, or FileA may move, or be included in another file.
Absolute paths are a sure thing!
Consider a physical directory structure ( on Windows ) such as:
C:\wwwroot\htdocs\example
|_css
|_scripts
|_images
|_galleries
|_icons
|_banners
|_gallery
In the above typically example would be set as the document root and a call to echo $_SERVER['DOCUMENT_ROOT'] would yield c:/wwwroot/htdocs/example etc
An Absolute or Root Relative path for css, images, scripts etc would begin with a leading slash. So, to access css files you might do:
<link rel='stylesheet' href='/css/theme.css' />
or for an images
<img src='/images/banners/logo.png' />
If you start the path with ../ you are instructing the browser to fetch the resource beginning 1 folder higher ( than the current directory ) and then follow the given path. Similarly if you use ../../ that means "go up 2 levels" and begin searching from that point. There is a place for this syntax but it can be confusing and very easy to get wrong.
If you begin the path for a resource with no leading slash ( such as images/example.png ) you are instructing the browser to fetch the resource from the same level OR a sub-folder. In the given example here images/example.png suggests the image is within a sub-folder of the given path so if you are accessing the page at https://localhost/gallery/beach/index.php it would mean that there needs to be a folder structure C:\wwwroot\htdocs\example\gallery\beach\images for that to work ( unless using advanced trickery with the server config )
When it comes to including additional PHP scripts you can do so a little differently. It is not essential and in most cases it can be preferable to have the files you wish to include outside of the document root. Using the same base structure from above and having a directory for commonly included files outside of document root would mean that using a browser you could not directly open files in the includes directory - so for example: https://localhost/includes/secrets.php would fail but that file could easily be included from within PHP.
To include other PHP files you can tweak the includes_path variable using set_include_path() and thus allow PHP to include files from outwith the site root.
c:\wwwroot\htdocs\includes
You could ensure that all PHP scripts ( such as db connections and other class files ) are easily included by setting the includes_path:
set_include_path( 'c:\wwwroot\htdocs\includes' );
and then, to include a file from that directory:
require 'db.php';
You can set this to use the full path instead or you can use the ../../ style syntax also.

include() and require_once() Issue

I have this situation:
/
index.php
/init (folder)
init.php (of course inside this file i use require_once for db/function/and whatever you want to put inside)
/layout_parts (folder)
header.php (and others common parts are inside this folder)
/my_space (folder inside layout parts)
my_file.php
another_file.php
/your_space (folder inside layout parts)
your_file.php
another_file.php
/third_space (folder inside layout parts)
third_file.php
another_file.php
For the index i have no problem it all works fine, but if i include header.php in one of the subfolder files my require_once(init/init.php); that is on the top of header.php won't work.
(Warning message says no such file in the directory (OF COURSE THE FILE EXIST) and it write down the subfolder directory that is not the path i expected).
I tried echo $SERVER['DOCUMENT_ROOT]; to see the whole path, echo __DIR__; to see wich is the right path to the directory, no way out.
I know is such a dummy question but if some kind heart could help me it would be great. Thanks :)
The best way to handle this would be to use absolute paths instead of relative ones. When you use relative paths, you have to worry each time about how many levels deep you are and then have that many ../ etc. This is messy and difficult to manage, for eg, if you move a file to a different location, you have to update the includes again, based on where you are now. This is why absolute paths are helpful.
So create something like this:
$appRoot = "/path/to/root/folder/";
This is the path where the index.php file is located. It is the "application root", if you will.
Now, in ANY file where you want to include init.php add the following line:
include_once($appRoot."init/init.php");
Ideally the $appRoot should be created in a global config located in root. If you do not have a structure where a univeral config can be added, it can still be messy and you might need to add absolute paths into individual files (which is not a good idea)

Including a file in multiple directories - PHP

I am trying to get my include() functions in order but everytime I switch the syntax in one directory it messes up its subdirectory and vice versa.
I have a file called 'header.php' in my 'localhost/FTS/includes/header.php' folder.
The 'FTS' folder has my index.php file so it is technically my root folder while I am testing.
In the file 'localhost/FTS/admin.php' I use the line include 'includes/header.php'; and it works fine but then when I go into the file 'localhost/FTS/admin/members.php' the include file is not found. Also inside of my 'header.php' file I include a couple more files from my root directory.
I just want all of my includes to work from each directory. Any ideas?
The include statement includes files relative to the script executing include, which is why you're seeing this issue. You have a couple of options available to you:
You can preface your include path with something like $_SERVER['DOCUMENT_ROOT'], which if you're using Apache, will reference your document root directory. So something like include( $_SERVER['DOCUMENT_ROOT'] . "/includes/header.php" ); will appear to the script as an absolute path, so it will work if called from various places in your structure, but still be portable (note that it would require being called from a web server, this won't work if you're using your scripts through CLI).
You can create some sort of placeholder at the root of your directory structure, and work your way up until you find it, then consider this the root and make your include statements relative to this. This will be more portable and work in CLI mode, but it will be slightly more resource intensive.
You can use different include statements depending on where you're script including the include file is located, such as include( "includes/header.php" ); if the file you're including is in the includes directory of the directory you're currently in, or include( "../includes/header.php" ); if the includes directory is in the parent directory of the script being run.

Categories