What is the difference between these two in PHP?
require "./vendor/autoload.php";
vs
require "vendor/autoload.php";
For both statements the autoload.php script is found, but in certain environment the autoloader itself does not find classes. I'm not trying to solve the autoloader problem itself, but try to understand why these two make it behave differently.
The . refers to the folder that you are in, it's most a unix syntax for files them for the php. I think you should use __DIR__ to prefix the included files, so you can avoid some problems with relative paths
The . gives you the ability to set the path of the included files relatively to the path of the original file that run (the file that included them).
Lets take the following structure:
/index.php
/file2.php
/folder/
/file1.php
If index.php includes file1.php, and you want file1.php to include file2.php - you can do this using require './file2.php'; (inside file1.php, which is in the inner folder).
If you use require 'file2.php'; inside file1.php you are looking for file2.php inside the folder (which will give you an error, because the file is not there).
Related
I've been going over those two topics:
include, require and relative paths
PHP - with require_once/include/require, the path is relative to what?
and couldn't make my script to work, none of presented methods are working or maybe I'm doing something wrong.
Anyway this is where my problem occurred:
Root/ //this is root location for server
APP/ //this is root location for script
Root/APP/core/init.php //this is where I include classes and functions from
Root/APP/classes/some_class.php //this is where all classes are
Root/APP/functions/some_function.php //this is where all functions are
and so obviously I need to include init.php everywhere so I did in every file like this:
require_once 'core/init.php';
it was working until I have decided to create a location for admin files like this:
Root/APP/Admin/some_admin_file.php
and when I included init this way:
require_once '../core/init.php';
script failed to open functions, no such file in APP/Core/ folder
so I used DIR method presented in topic above and than even weirder thing happened, error:
no such file in APP/Core/classes/Admin/
What is that? :D I'm lost with this, could someone help a bit ;)
Include paths are relative to the current working directory, which can be inspected using getcwd(); this can be a source of many issues when your project becomes bigger.
To make include paths more stable, you should use the __DIR__ and __FILE__ magic constants; for instance, in your particular case:
require_once dirname(__DIR__) . '/core/init.php';
The dirname(__DIR__) expression is effectively the parent directory of the script that's currently being run.
Btw, __DIR__ could also be written as dirname(__FILE__).
I have the current tree.
/edu/index.php
/edu/Classes/Connection.php
/edu/Classes/User.php
/edu/Handlers/Post.php
When I need to use functions from Connection.php and User.php inside index.php, I require them using:
require_once './Classes/Connection.php';
require_once './Classes/User.php';
But some functions from User.php also needs functions from Connection.php to work, so since index.php is where the requests come from, I require Connection.php inside User.php using:
require_once './Classes/Connection.php';
But sometimes I need to use the same functions from Post.php, so
require_once './Classes/Connection.php'; inside User.php does not work if Post.php is the file sending requests.
Isn't there a unified path or solution so that I can be able to require the file from any place inside my project in the same way? I would really like to avoid a solution such as...
public function UserFunction($path){
require_once $path;
}
And change the parameter on each call depending on my position inside the project folder.
If the files you are trying to include are mostly classes, it would probably be best to implement the __autoload function. When you instantiate a class, if the class hasn't been defined, then the __autoload method is called with the class name so you can include the file. If you create a simple standard, like all classes reside in the $_SERVER['DOCUMENT_ROOT'].'/classes/' folder and the filename is the same as the class name like ClassName.php, you can dynamically load in any classes as they are needed.
Also, generally looked down upon but I figured I would mention it because I hadn't seen it offered yet. There is the set_include_path() function you can call that will allow you to set the path(s) that php looks when including a file. HOWEVER, this can cause some trouble. As an example, my work hosts several sites under sub-domains each with their own document root. Under the document root each site has its own "includes" folder. Well some genius about 8 years ago set the include path in the global apache config to /var/www/site1/includes;/var/www/site2/includes...etc. Problem is that when a file exists with the same name in site1 as site2 and you try to include it, you will always include the file from site1 because php will find the file there and stop looking. It has caused some small headaches from time to time.
Your best best is to include relative to __DIR__ to get a file relative to another file.
Other good points that you can include from are
$_SERVER["DOCUMENT_ROOT"]
or make your own using htaccess.
in .htaccess put
SetEnv MY_INCLUDE_PATH "/path/to/my/php/files";
then in php
include ($_SERVER["MY_INCLUDE_PATH"]."/Connection.php");
Okay so on my website I have a scripts folder which includes a php file which connects to mysql server so If I move a database then It will change it on all the files which are connect to the database.
I also have another folder called templates. In that folder there is a top for the header and the footer. In the header template I wrote:
require("../scripts/connect.php");
And I have another folder called, category. And that folder includes the header and the header includes connect. But then it displays and error that there is no such files.
Please help. Thank you
A good practice is to include a main config in all running php files, usually called config.php :)
in this config file create a constant called SITE_ROOT or something similar that point to the exact folder like this
define("SITE_ROOT", "/var/www/mysite");
Then on any include, include_once, require, require_once use it like this:
require(SITE_ROOT."/scripts/connect.php");
This should solve any relative path drama
You shouldn't use relative paths with the include/require, but use a constant defining the ROOT_PATH of your website.
Example:
In all the files calling needing includes:
define(ROOT_PATH, '../');
include ROOT_PATH . '/scripts/connect.php';
And in /scripts/connect.php (and all the other files that will be included somewhere), all the includes should use ROOT_PATH (without defining it).
I have a directory root:
index.php
includes/
template.php
testfile.php
phpFiles/
processInput.php
testfile.php
index.php:
require_once("includes/template.php");
template.php:
require_once("includes/phpFiles/processInput.php")
processInput.php:
require_once("testfile.php")
require_once("../testfile.php")
This code will work when you run index.php, of course it will not work when you run template.php.
As you can see, index.php includes template.php like normal. But in template.php, you have to include like if you are in the directory that index.php is in. But then, in processInput.php, you include as if you are in the directory that processInput.php is in.
Why is this happening, and how can I fix it so that the include path is always the directory of the file that the require is done in? The second included file have the same include path as the requested file, but the next one does not.
Thanks for your help!
EDIT: The strange thing is that I've included classes in a class folder. And it included other files as it is supposed to, even though the paths are relative. WHY does this happen, and how can I fix it?
VERY IMPORTANT EDIT: I just realized that all this is because in my example, the inclusion in includes/phpFiles/processInput.php includes a file in the same directory: require_once("file in same dir.php"); This is the reason. If you are including a file with out specifying anything more than the filename, the include_path is actually the dir where the file the require is written in is in. Can anyone confirm this?
Use an absolute path.
require_once($_SERVER['DOCUMENT_ROOT']."/includes/phpFiles/processInput.php");
Use a similar form for all your required files and they will work no matter where you are.
You can do this in a few ways, amongst others:
Use set_include_path to control the directories from where to perform require() calls.
Define a common absolute base path in a constant that you define in index.php and use that in every require() statement (e.g. require(BASEPATH . '/includes/template.php')).
Use relative paths everywhere and leverage dirname(__FILE__) or __DIR__ to turn them into absolute paths. For instance: require(__DIR__ . '/phpFiles/processInput.php');
By default, the current working directory is used in the include path; you can verify this by inspecting the output of get_include_path(). However, this is not relative to where the include() is made from; it's relative to the main executing script.
You're using relative paths. You need to use absolute paths: $_SERVER['DOCUMENT_ROOT'].
When you include/require, you are basically temporarily moving all code from one file, to another.
so if file1.php (which is located in root) contains:
require("folder/file.php");
and you include file1.php in file2.php (which is in a different location (say folder directory for example):
file2.php:
require("../file1.php");
Now all of file1.php code is in file2.php. So file2.php will look like this:
require("../file1.php");
require("folder/file.php");//but because file2.php is already in the `folder` directory, this path does not exist...
index.php:
require_once("includes/template.php");
template.php:
require_once("includes/phpFiles/processInput.php")
Your directory structure is off. The file inclusion is being seen from the file you're using it from. So, "template.php" is looking for an "includes/" folder in its current folder (/includes/).
As others are saying, use absolute paths, which will make sure you're always going at it from the file system root, or use:
require_once("phpFiles/processInput.php")
In your template.php file (which is far more likely to break if you ever move things around, which is why others all recommend using absolute paths from the file system root).
BTW, if you're using "index.php" as some kind of framework system, you can consider defining a variable that stores the address of common files such as:
define('APPLICATION_PATH', realpath(dirname(__FILE__));
define('PHPFILES_PATH', APPLICAITON_PATH . '/includes/phpFiles/');
I have seen this:
<?php
include( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my_file.php');
?>
Why would I ever need to do this? Why would I go to the trouble of getting the dirname and then concatenating that with a directory separator, and a new filename?
Is the code above not equivalent to this:
<?php
include( 'my_file.php' );
?>
??
The PHP doc says,
Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include() will finally check in the calling script's own directory and the current working directory before failing. The include() construct will emit a warning if it cannot find a file; this is different behavior from require(), which will emit a fatal error.
Let's say I have a (fake) directory structure like:
.../root/
/app
bootstrap.php
/scripts
something/
somescript.php
/public
index.php
Now assume that bootstrap.php has some code included for setting up database connections or some other kind of boostrapping stuff.
Assume you want to include a file in boostrap.php's folder called init.php. Now, to avoid scanning the entire include path with include 'init.php', you could use include './init.php'.
There's a problem though. That ./ will be relative to the script that included bootstrap.php, not bootstrap.php. (Technically speaking, it will be relative to the working directory.)
dirname(__FILE__) allows you to get an absolute path (and thus avoid an include path search) without relying on the working directory being the directory in which bootstrap.php resides.
(Note: since PHP 5.3, you can use __DIR__ in place of dirname(__FILE__).)
Now, why not just use include 'init.php';?
As odd as it is at first though, . is not guaranteed to be in the include path. Sometimes to avoid useless stat()'s people remove it from the include path when they are rarely include files in the same directory (why search the current directory when you know includes are never going to be there?).
Note: About half of this answer is address in a rather old post: What's better of require(dirname(__FILE__).'/'.'myParent.php') than just require('myParent.php')?
I might have even a simpler explanation to this question compared to the accepted answer so I'm going to give it a go: Assume this is the structure of the files and directories of a project:
Project root directory:
file1.php
file3.php
dir1/
file2.php
(dir1 is a directory and file2.php is inside it)
And this is the content of each of the three files above:
//file1.php:
<?php include "dir1/file2.php"
//file2.php:
<?php include "../file3.php"
//file3.php:
<?php echo "Hello, Test!";
Now run file1.php and try to guess what should happen. You might expect to see "Hello, Test!", however, it won't be shown! What you'll get instead will be an error indicating that the file you have requested(file3.php) does not exist!
The reason is that, inside file1.php when you include file2.php, the content of it is getting copied and then pasted back directly into file1.php which is inside the root directory, thus this part "../file3.php" runs from the root directory and thus goes one directory up the root! (and obviously it won't find the file3.php).
Now, what should we do ?!
Relative paths of course have the problem above, so we have to use absolute paths. However, absolute paths have also one problem. If you (for example) copy the root folder (containing your whole project) and paste it in anywhere else on your computer, the paths will be invalid from that point on! And that'll be a REAL MESS!
So we kind of need paths that are both absolute and dynamic(Each file dynamically finds the absolute path of itself wherever we place it)!
The way we do that is by getting help from PHP, and dirname() is the function to go for, which gives the absolute path to the directory in which a file exists in. And each file name could also be easily accessed using the __FILE__ constant. So dirname(__FILE__) would easily give you the absolute (while dynamic!) path to the file we're typing in the above code. Now move your whole project to a new place, or even a new system, and tada! it works!
So now if we turn the project above to this:
//file1.php:
<?php include(dirname(__FILE__)."/dir1/file2.php");
//file2.php:
<?php include(dirname(__FILE__)."/../file3.php");
//file3.php:
<?php echo "Hello, Test!";
if you run it, you'll see the almighty Hello, Test!! (hopefully, if you've not done anything else wrong).
It's also worth mentioning that from PHP5, a nicer way(with regards to readability and preventing eye boilage!) has been provided by PHP as well which is the constant __DIR__ which does exactly the same thing as dirname(__FILE__)!
Hope that helps.
I used this below if this is what you are thinking. It it worked well for me.
<?php
include $_SERVER['DOCUMENT_ROOT']."/head_lib.php";
?>
What I was trying to do was pulla file called /head_lib.php from the root folder. It would not pull anything to build the webpage. The header, footer and other key features in sub directories would never show up. Until I did above it worked like a champ.
If you want code is running on multiple servers with different environments,then we have need
to use dirname(FILE) in an include or include_once statement.
reason is follows.
1. Do not give absolute path to include files on your server.
2. Dynamically calculate the full path like absolute path.
Use a combination of dirname(FILE) and subsequent calls to itself until you reach to the home of your '/myfile.php'.
Then attach this variable that contains the path to your included files.