PHPunit - CLI PHP file includes/requires - php

For example if I have a php script called "RunAllTests.php" in '/var/www/tests/RunAllTests.php' and I execute phpunit within the that directory, the includes in "RunAllTests.php" are found.
If I execute phpunit on that same file, from another directory, lets say '/var/www/', the included files in "RunAllTests.php" cannot be located. - "failed to open stream: No such file or directory in"
I kept this a little bit vague, let me know if you need some more specifics.

Your requires are wrong / not portable: they expect the directory of the file (or some other fixed directory) to be the working dir.
Your options are:
Just start the process from the correct dir.
chdir(__DIR__) in your script.
include / require relative to the __DIR__ constant in your files (which IMHO is most portable)
define a working dir in code beforehand, use that value (related to (3) but more fixed).

Related

PHP Include './' vs '../' [duplicate]

A. What does this do?
require ("./file.php");
B. in comparison to this?
require ("file.php");
(Its not up-one-directory.. which would be)
require ("../file.php");
./ is the current directory. It is largely the same as just file.php, but in many cases (this one included) it doesn't check any standard places PHP might look for a file, instead checking only the current directory.
From the PHP documentation (notice the last sentence):
Files for including are first looked for in each include_path entry relative to the current working directory, and then in the directory of current script. E.g. if your include_path is libraries, current working directory is /www/, you included include/a.php and there is include "b.php" in that file, b.php is first looked in /www/libraries/ and then in /www/include/. If filename begins with ./ or ../, it is looked only in the current working directory.
The first version forces the internal mechanism to include files relatively to the... directly executed file. So for example you have
index.php
// directly executed script (php -f index.php or from a browser)
include 'second.php';
second.php
// This is included relatively to index.php
// Actually, it is first searched relatively to include_path, then relatively
// to index.php
include './third.php';
third.php
// This is included relatively to second.php ONLY. It does not search
// include_path
return "foo";
The Short Answer
You're right, it's not up one directory. A . refers to the directory you're in, and .. refers to the parent directory.
Meaning, ./file.php and file.php are functionally equivalent in PHP. Here's the relavent page of documentation:
http://us.php.net/manual/en/wrappers.file.php
The Longer Answer
However, just because they work the same in this context doesn't mean they're always the same.
When you're operating in a *nix shell environment, and you type the name of an executable file, the shell will look in the PATH directories, but it won't look in the CWD, or the directory you're currently in.
So, if you're in a directory that has a file called: myprogram.php (this would be a PHP CLI file) and you just type:
myprogram.php
it doesn't matter if your program is executable or not. The shell will look in /bin/, /usr/bin/, etc. for your file, but it won't look in ./: the directory you're in.
To execute that program without adding your directory to the PATH, you need to type
./myprogram
So really, ./ is more explicit. It means, "the file you're looking for HAS to be right here" and lack of ./ means, "the file should be somewhere the program is looking for files".
The dot-slash forces the file to be found in the current directory only, rather than additionally searching the paths mentioned in the include_path setting.
Edit: I have completely rewritten the answer for the sake of clarity
When including a file, you can either use ./myfile.php or myfile.php.
They are not the same and you should always, preferably, use the first syntax, unless you know what you're doing.
The difference is best illustrated with an example: lets say you have the following files and folder structure:
index.php
inc/inner.php
From index.php, you can include your inner template without the ' ./' and it will work as expected:
# index.php
<?php
include "inc/inner.php";
Now let's say we add a new file, so the folder structure is now like this:
index.php
inc/inner.php
inc/inner-inner.php
To include inner-inner.php in inner.php, we would do this... right?
# src/inner.php
<?php
include "inner-inner.php";
Wrong. inner.php will just look for inner-inner.php in the root folder.
index.php
* inner-inner.php <- Doesn't exist, PHP ERROR.
inc/inner.php
inc/inner-inner.php
Instead, we should use the ./ syntax to include inner-inner. This will instruct that the file we are including must be included relative to the current file, not to the current "entry point" of the PHP script (index.php in the example).
# src/inner.php
<?php
include "./inner-inner.php";
In addition, and as mentioned in other comments, if you have configured a different "load path" for your PHP application, that load path will be looked up first without the ./ syntax. Instead, the ./ syntax is more efficient because it doesn't check the "include path" of php 1.
If you wanna make your includes even more explicit, use the __DIR__ constant. This tells php: "Use the directory of this file" 2.
# src/inner.php
<?php
include __DIR__ . "/inner-inner.php";
TLDR; Always use ./ or __DIR__ 2 because it's relative to the current (working) directory and doesn't depend on the PHP "include path" 1.
References:
[Include - https://www.php.net/manual/en/function.include.php]
Magic Constants - https://www.php.net/manual/en/language.constants.magic.php
Simply you are telling php to include the file in the current directory only or fail if the file is not present.
If you use the format "indexcommon3.php" and the file is not present php will search it into the include_path system variable.
For reference you can use http://www.php.net/manual/en/function.include.php
It's explicitly naming the current directory.

Warning: require_once(/HTML/Template/ITX.php): failed to open stream: No such file or directory in C:\wamp64\www\mysite\main\login.php on line 13 [duplicate]

I was writing an web app in PHP, when I encountered a strange situation. To illustrate my problem, consider a web app of this structure:
/
index.php
f1/
f1.php
f2/
f2.php
Contents of these files:
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("../f2/f2.php"); ?>
f2.php: blank
now when I try to open index.php in my browser I get this error:
Warning: require_once(../f2/f2.php) [function.require-once]:
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2
Fatal error: require_once() [function.require]:
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2
Is there something obvious I'm missing? how do include paths work in PHP?
Before I asked this question, I attempted to experiment and find out. I set up another test, like so:
/
index.php
f1/
f1.php
f2.php
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("f2.php"); ?>
f2.php: blank
To my surprise (and utter confusion), this worked out fine!
So, what is the secret behind the path resolution?
PS I saw this question, but it still does not answer the second case that I've stated here.
If you include another file, the working directory remains where the including file is.
Your examples are working as intended.
Edit: The second example works because . (actual directory) is in your include path (see your error message).
Edit2:
In your second example, the key point of your interest is this line:
<?php require_once("f2.php"); ?>
At first it will look in the current working dir (/var/www/req_path_test), but does not find f2.php.
As fallback, it will try to find f2.php in your include_path ('.:/usr/share/php:/usr/share/pear'), starting with '.' (which is relative to the actual file, not the including one).
So './f2.php' works and the require does not fail.
When you open index.php, working dir is set to the folder this file resides in. And inside insluded f1.php this working dir does not change.
You can include files by using their absolute paths, relative to the current included file like this:
require_once(dirname(__FILE__).'/../../test/file.php')
But better consider using an autoloader if these files contain classes.
Normaly in you old structure
<?php require_once("f2/f2.php"); ?>
instead of
<?php require_once("../f2/f2.php"); ?>
should work. As far as i know php takes the paths from the initial script
It sounds like your server has the open_basedir setting enabled in the PHP configuration. This makes it impossible to include (and open) files in folders above your in the directory structur (i.e., you can't use ../ to go up in the folder structure).
From the PHP Docs PHP include
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.
If the file path is not given then i.e require_once("f2.php");
1st. The include_path is checked
2nd. The calling scripts own directory is checked
3rd. Finally the current working directory is checked
If file not found then PHP throws warning on file include & fatal error on require
If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) — the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.
If you include/require your file beginning with . or .. or ./ then PHP's parser will look in the parent directory which is the current working directory i.e require_once("../f2/f2.php"), php will check at the root directory as the calling script index.php is in that directory.
Now You have not defined any include path in your PHP script thus it always falls back to the calling script and then into the current working directory.
// Check your default include path, most likely to be C:\xampp\php\PEAR
echo get_include_path();
// To set include path
set_include_path ( string $new_include_path ) : string
The Current Working Directory is derived from your main calling script index.php.
// The Current Working Directory can be checked
echo getcwd();
In the first Example where the required file "../f2/f2.php" is from f1.php
You code does not work because -
The specified path is ignored by PHP as your filename begins with ../
f1/ the calling script's own directory is ignored as well.
The parser directory looks into the parent directory to find the requested file. The current working directory is root directory, this is from where you have initiated the working script index.php. The file is not located at this directory, wrong path given.
Thus you get the Fatal Error
In the Second example you have changed the directory & from f1.php you require_once("f2.php").
Your code works because -
This time you require("f2.php") no leading ../ or ./ This time PHP checks the include_path but does find it there, as you haven't defined it and the file does not reside in the default preset include_path.
This time the calling script f1.php's directory is f1/. and you require file ("f2.php") is located at this directory. PHP This time checks the file in this directory and finds it.
PHP does not have to check the working directory as the file was found.
Thus Your Code Works Fine!

PHP include path sub-folder files not included

I have a site where the PHP include path is /usr/share/php
Within this path I have a sub-folder containing some utility files, e.g. /usr/share/php/utils. my_session.php is one of these utility files.
My application calls
require ("my_session.php");
and this works even though the file is actually within the utils folder.
I am trying to replicate this site in another installation and I am getting the error:
Failed opening required 'my_session.php' (include_path='.:/usr/share/php)
My question is:
Should the php include path also include files in sub-folders in the include path?
This appears to be the case on my original site and I don't know why the behaviour seems to be different on the second site.
According to PHP documentation when you try to include a file, only paths listed in the include_path directive are checked. PHP is not supposed to check their subfolders.
My guess would be that this fails because you are using a relative path for the require.
Your include_path is defined as .:/usr/share/php. That means only two folders will be checked when require('my_session.php') gets executed:
the current path
the folder /usr/share/php
I don't know your folder structure, so let's just imagine one:
my_project
- app
-- index.php
- lib
-- my_session.php
Now, if my_project/app/index.php tries to require('my_session.php') this will fail, because the current folder at the time executing the require is my_project/app/ and there is no file entry of my_session.php relative to my_project/app/ (it's relative to my_project/lib/ instead).
Long story short: Try to to use an absolute path instead of your relative one, e.g.
require('/var/www/html/my_project/lib/my_session.php');
Edit: removed and its subfolders, which was wrong. Too much __autoload in my brain^^
Two solutions:
Add /usr/share/php/utils to your include_path.
or
Include your file with require ("utils/my_session.php");

How does include path resolution work in require_once?

I was writing an web app in PHP, when I encountered a strange situation. To illustrate my problem, consider a web app of this structure:
/
index.php
f1/
f1.php
f2/
f2.php
Contents of these files:
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("../f2/f2.php"); ?>
f2.php: blank
now when I try to open index.php in my browser I get this error:
Warning: require_once(../f2/f2.php) [function.require-once]:
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2
Fatal error: require_once() [function.require]:
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2
Is there something obvious I'm missing? how do include paths work in PHP?
Before I asked this question, I attempted to experiment and find out. I set up another test, like so:
/
index.php
f1/
f1.php
f2.php
index.php:
<?php require_once("f1/f1.php"); ?>
f1.php:
<?php require_once("f2.php"); ?>
f2.php: blank
To my surprise (and utter confusion), this worked out fine!
So, what is the secret behind the path resolution?
PS I saw this question, but it still does not answer the second case that I've stated here.
If you include another file, the working directory remains where the including file is.
Your examples are working as intended.
Edit: The second example works because . (actual directory) is in your include path (see your error message).
Edit2:
In your second example, the key point of your interest is this line:
<?php require_once("f2.php"); ?>
At first it will look in the current working dir (/var/www/req_path_test), but does not find f2.php.
As fallback, it will try to find f2.php in your include_path ('.:/usr/share/php:/usr/share/pear'), starting with '.' (which is relative to the actual file, not the including one).
So './f2.php' works and the require does not fail.
When you open index.php, working dir is set to the folder this file resides in. And inside insluded f1.php this working dir does not change.
You can include files by using their absolute paths, relative to the current included file like this:
require_once(dirname(__FILE__).'/../../test/file.php')
But better consider using an autoloader if these files contain classes.
Normaly in you old structure
<?php require_once("f2/f2.php"); ?>
instead of
<?php require_once("../f2/f2.php"); ?>
should work. As far as i know php takes the paths from the initial script
It sounds like your server has the open_basedir setting enabled in the PHP configuration. This makes it impossible to include (and open) files in folders above your in the directory structur (i.e., you can't use ../ to go up in the folder structure).
From the PHP Docs PHP include
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.
If the file path is not given then i.e require_once("f2.php");
1st. The include_path is checked
2nd. The calling scripts own directory is checked
3rd. Finally the current working directory is checked
If file not found then PHP throws warning on file include & fatal error on require
If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) — the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.
If you include/require your file beginning with . or .. or ./ then PHP's parser will look in the parent directory which is the current working directory i.e require_once("../f2/f2.php"), php will check at the root directory as the calling script index.php is in that directory.
Now You have not defined any include path in your PHP script thus it always falls back to the calling script and then into the current working directory.
// Check your default include path, most likely to be C:\xampp\php\PEAR
echo get_include_path();
// To set include path
set_include_path ( string $new_include_path ) : string
The Current Working Directory is derived from your main calling script index.php.
// The Current Working Directory can be checked
echo getcwd();
In the first Example where the required file "../f2/f2.php" is from f1.php
You code does not work because -
The specified path is ignored by PHP as your filename begins with ../
f1/ the calling script's own directory is ignored as well.
The parser directory looks into the parent directory to find the requested file. The current working directory is root directory, this is from where you have initiated the working script index.php. The file is not located at this directory, wrong path given.
Thus you get the Fatal Error
In the Second example you have changed the directory & from f1.php you require_once("f2.php").
Your code works because -
This time you require("f2.php") no leading ../ or ./ This time PHP checks the include_path but does find it there, as you haven't defined it and the file does not reside in the default preset include_path.
This time the calling script f1.php's directory is f1/. and you require file ("f2.php") is located at this directory. PHP This time checks the file in this directory and finds it.
PHP does not have to check the working directory as the file was found.
Thus Your Code Works Fine!

What does the dot-slash do to PHP include calls?

A. What does this do?
require ("./file.php");
B. in comparison to this?
require ("file.php");
(Its not up-one-directory.. which would be)
require ("../file.php");
./ is the current directory. It is largely the same as just file.php, but in many cases (this one included) it doesn't check any standard places PHP might look for a file, instead checking only the current directory.
From the PHP documentation (notice the last sentence):
Files for including are first looked for in each include_path entry relative to the current working directory, and then in the directory of current script. E.g. if your include_path is libraries, current working directory is /www/, you included include/a.php and there is include "b.php" in that file, b.php is first looked in /www/libraries/ and then in /www/include/. If filename begins with ./ or ../, it is looked only in the current working directory.
The first version forces the internal mechanism to include files relatively to the... directly executed file. So for example you have
index.php
// directly executed script (php -f index.php or from a browser)
include 'second.php';
second.php
// This is included relatively to index.php
// Actually, it is first searched relatively to include_path, then relatively
// to index.php
include './third.php';
third.php
// This is included relatively to second.php ONLY. It does not search
// include_path
return "foo";
The Short Answer
You're right, it's not up one directory. A . refers to the directory you're in, and .. refers to the parent directory.
Meaning, ./file.php and file.php are functionally equivalent in PHP. Here's the relavent page of documentation:
http://us.php.net/manual/en/wrappers.file.php
The Longer Answer
However, just because they work the same in this context doesn't mean they're always the same.
When you're operating in a *nix shell environment, and you type the name of an executable file, the shell will look in the PATH directories, but it won't look in the CWD, or the directory you're currently in.
So, if you're in a directory that has a file called: myprogram.php (this would be a PHP CLI file) and you just type:
myprogram.php
it doesn't matter if your program is executable or not. The shell will look in /bin/, /usr/bin/, etc. for your file, but it won't look in ./: the directory you're in.
To execute that program without adding your directory to the PATH, you need to type
./myprogram
So really, ./ is more explicit. It means, "the file you're looking for HAS to be right here" and lack of ./ means, "the file should be somewhere the program is looking for files".
The dot-slash forces the file to be found in the current directory only, rather than additionally searching the paths mentioned in the include_path setting.
Edit: I have completely rewritten the answer for the sake of clarity
When including a file, you can either use ./myfile.php or myfile.php.
They are not the same and you should always, preferably, use the first syntax, unless you know what you're doing.
The difference is best illustrated with an example: lets say you have the following files and folder structure:
index.php
inc/inner.php
From index.php, you can include your inner template without the ' ./' and it will work as expected:
# index.php
<?php
include "inc/inner.php";
Now let's say we add a new file, so the folder structure is now like this:
index.php
inc/inner.php
inc/inner-inner.php
To include inner-inner.php in inner.php, we would do this... right?
# src/inner.php
<?php
include "inner-inner.php";
Wrong. inner.php will just look for inner-inner.php in the root folder.
index.php
* inner-inner.php <- Doesn't exist, PHP ERROR.
inc/inner.php
inc/inner-inner.php
Instead, we should use the ./ syntax to include inner-inner. This will instruct that the file we are including must be included relative to the current file, not to the current "entry point" of the PHP script (index.php in the example).
# src/inner.php
<?php
include "./inner-inner.php";
In addition, and as mentioned in other comments, if you have configured a different "load path" for your PHP application, that load path will be looked up first without the ./ syntax. Instead, the ./ syntax is more efficient because it doesn't check the "include path" of php 1.
If you wanna make your includes even more explicit, use the __DIR__ constant. This tells php: "Use the directory of this file" 2.
# src/inner.php
<?php
include __DIR__ . "/inner-inner.php";
TLDR; Always use ./ or __DIR__ 2 because it's relative to the current (working) directory and doesn't depend on the PHP "include path" 1.
References:
[Include - https://www.php.net/manual/en/function.include.php]
Magic Constants - https://www.php.net/manual/en/language.constants.magic.php
Simply you are telling php to include the file in the current directory only or fail if the file is not present.
If you use the format "indexcommon3.php" and the file is not present php will search it into the include_path system variable.
For reference you can use http://www.php.net/manual/en/function.include.php
It's explicitly naming the current directory.

Categories