Equivalent of running $_SERVER['DOCUMENT_ROOT'] when running php in terminal - php

I was wondering if there is some variable that will return what $_SERVER['DOCUMENT_ROOT'] returns when I call PHP like this: ./somescript
If not, how do people get around this case? I'm looking to be able to call the same script (a template compiler) in both the web browser and the terminal.
Thanks!
Matt Mueller

I don't recommend the getcwd() command for this because you cannot be sure of where cwd is pointing unless you've made a chdir before (which mean you already know which directory you're in). Working directory can be define in php config and vary between apache and CLI, and some php frameworks changes it on startup.
Use dirname(__FILE__) it always works wether you're in a apache or cli context (plus it works on windows and unix), and if you need to move inside your project files you can just use relative paths.

I think you should use getcwd function to obtain current directory (or just dirname(__FILE__) if your script is the top one). Then you only need to be sure to run the script from your DOCUMENT_ROOT. Something like this:
cd /var/www/
php ./scripts/top.php

hardcode document root in it.
hardcode is always a solution

Related

crontab cannot read dir '../' in php script

Why can't crontab read the '../' dir in the script, but if I access the script through a browser it can and there are no problems.
example: file.php
<?php
include('../config.php');
?>
If I run the script through the terminal config.php it can't be read '/usr/bin/php /home/example.com/public_html/cron/file.php',
whereas if I open it through a browser it runs smoothly
https://example.com/cron/file.php
I use php7.4 and os centos7
This is a perfect use case for why you should avoid using relative paths and instead stick to using absolute paths when including other scripts/files. PHP resolves relative paths according to the CWD (Current Working Directory) which will be different between your web server and your terminal. For the web server it depends on which script invoked the interpreter (in your case this is /home/example.com/public_html/cron/file.php). In the terminal it depends on from which directory the interpreter is loaded in the shell. In the case of a crontab it is the $PWD variable set in the home directory of the user that owns the crontab (so most likely /home/{username}). Of course that those two resolve to completely different paths.
So instead of all this guess work and instead of trying to change the CWD adhoc (which involves further guess work), you could simply use an absolute path at all times.
<?php
include __DIR__ . '/../config.php';
What this allows you to do is set the absolute path to the magic __DIR__ constant, which is a compile-time constant set to the path of the script in which it is used (in your case this is /home/example.com/public_html/cron). Then you can relatively go down one directory from that absolute path in order to get to /home/example.com/public_html from which you can now safely access config.php regardless of how you invoke the script and the given CWD.
.. references the parent directory of wherever the script is executing. It's presumably different in the two scenarios. Try cd /home/example.com/public_html/cron && /usr/bin/php file.php in your crontab, so that you're executing that in the same directory as your web page is.

PHP: How to set current working directory to be same as directory executing the script

I'm in the process of transferring my website from one server to another. I have some php scripts that use the is_readable function which uses the current working directory.
On the old server, when I call getcwd(), it outputs the folder in which the script is being executed. On the new server it outputs the root directory '/'.
I would like to know how I can configure PHP to use the current folder instead of '/'. I don't want to have to change any PHP code that already works on the old server. I can configure the new server, but don't know what settings to change. I'm using apache2, if that helps.
EDIT: It seems as though my working directory is not root like I thought. When I create a testFile.php and echo getcwd() it shows the directory the php file is in. But in my problem file, in the same directory, getcwd() shows up as '/'
chdir(__DIR__);
or
chdir(dirname(__FILE__));
(see chdir and magic constants).
But that should be by default.
This is normal in CLI mode:
It does not change the working directory to that of the script. (-C and --no-chdir switches kept for compatibility)
a quick workaround would be
chdir(dirname(__FILE__));
You can get the current directory a script is in with dirname(__FILE__) or __DIR__ if >= PHP 5.3.

equivalent to $_SERVER['DOCUMENT_ROOT'] that will work when script is called by cron?

I'm using $_SERVER['DOCUMENT_ROOT'] for my include paths so files will figure out where they are running from (i.e. whether they're on live or staging) and it works fine, except for scripts that are run by cron in which I have to hardcode the path.
Is there another variable I could use that could work from both cron and the browser?
When running your PHP script through cron, I assume it is executed in the context of the CLI instead of the web server. In the case of executing PHP from the CLI, the $_SERVER['DOCUMENT_ROOT'] is not populated correctly. You can use the following code to work around this:
if ($_SERVER['DOCUMENT_ROOT'] == "")
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__);
The following will give you the directory that your script is located in:
realpath(dirname(__FILE__));
This works for both web requests and cron scripts.
The best thing to do is to define your own constant that you can reference from anywhere else in your app. For example, you can put something like this in MyAppDirectory/public_html/index.php:
define('APPLICATION_PATH', realpath(dirname(__FILE__).'/..'));
This will give you a consistent reference back to MyAppDirectory/ regardless of where index.php is called or included from. Defining your own constant not only allows you to call your application from cron or through the browser like you want, but will also allow you to change your storage structure in much larger ways with minimum changes to track down. Zend Framework uses this heavily with its Zend_Application bootstrap process, and googling for "php APPLICATION_PATH" will provide you with a variety of further references.
You can use chdir() function, if your script is running via cron:
chdir(dirname(__FILE__)); //avoid conflict with "cron path" and app base path (if script runs via 'Cron')
I work on Windows, so use "nnCron", but it have to work on Linux too.

$_SERVER['DOCUMENT_ROOT'] does not work in the php script running through cron

I use $_SERVER['DOCUMENT_ROOT']."/lib/sft_required.php"; to include the 'sft_required' file in a PHP script. When I run this file using browser, it works fine but when I run this as a cron job job, it does not work. It seems that the file is not included when we run the script through cron.
you could populate the $_SERVER['DOCUMENT_ROOT'] on your own
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__);
if the cron file is in document root
$_SERVER['DOCUMENT_ROOT'] = dirname(dirname(__FILE__));
if the cron file is one directory above the document root
Assuming you are running the script directly through cron (as opposed to from a web server accessed by an HTTP request triggered by a cronjob (e.g. by cron running wget)), then of course it doesn't work.
There is no server, so $_SERVER is not set.
$_SERVER cannot be expected to contain any of the normal values when a PHP script is run using the CLI interpreter. Either put the path in an environment variable, or pass it to the script as a command line argument.
I answered a similar question here. As people have mentioned, the superglobal $_SERVER isn't defined in CLI situations. In the link is a (so far) foolproof method for obtaining the DOCUMENT_ROOT location. Hope it proves useful.
define('DOCROOT', substr(str_replace(pathinfo(__FILE__, PATHINFO_BASENAME), '', __FILE__), 0, -1));
This will get you the same data as $_SERVER['DOCUMENT_ROOT'] for cronjobs.
Example 1:
/var/www/site.com/ - DOCUMENT_ROOT;
/var/www/site.com/cron/script.php - CRON PHP script;
<?php
/** DOCUMENT_ROOT -> /var/www/site.com/ */
$_SERVER['DOCUMENT_ROOT'] = realpath(dirname(__FILE__).'/../');
?>
Example 2:
/var/www/site.com/ - DOCUMENT_ROOT;
/var/www/site.com/sub_dir/cron/script.php - CRON PHP script;
<?php
/** DOCUMENT_ROOT -> /var/www/site.com/ */
$_SERVER['DOCUMENT_ROOT'] = realpath(dirname(__FILE__).'/../../');
?>
Here is my solution for a similar problem that I dealt with.
$site_root_directory = substr( __DIR__, 0, strpos( __DIR__, "wp-content" ) );
In my case, I am running a cron that executes a file inside of my theme. (I don't load WordPress for the corn, so I do not have access to things like ABSPATH).
This way I get my 'root directory' by using the first child folder inside of the root leading to my script, instead of working my way back from the script directory.
/var/more_directories/public_html/wp-content/themes/theme-name/includes/cron-jobs
/var/more_directories/public_html/
This means that I don't have to be worried about moving my script around, since it will always be somewhere under that first child folder.
I had same problem..
And solutions what i found on internet not worked with my webserver cron, so i needed find another way to change that path easly..
And its mostly not big problem, when yu have 1-2 cron files(can easly edit file path if needed), but i had 20 cron files and when i need change server or path changed or smt, then i must change all those files, change file path on them...
So i found atleast FOR ME exellent solutions:
i maded one file path.php in cron folder and bc its same folder with cron files, then you can include it without errors.
And in path.php i have $path = '/server/root/path';
And then i include that path.php to my cron files(i have 20 cron files or so)
And now i use that $path on my cron files as below:
include 'path.php';
include $path.'/includes/db.php';
Now if i need change path, then i just open path.php file , change it and all working.
Hope i helped someone, bc that solutions changed my life much much easyer!
Its still not perfect, bc perfect would be when all worked automatically, but for me that is much much easyer than previous system, so i tought i will share my experience, mabe i can help someone :)!
In my case, this issue was caused by the $_SERVER['DOCUMENT_ROOT'] path having a trailing slash during normal site operations and no trailing slash during cron jobs.
I'm not sure what was causing that to happen, but as a workaround, I switched my code to use ABSPATH instead, since it appeared to be returning a consistent value.
So, in other words, I changed this:
$private_folder = realpath($_SERVER['DOCUMENT_ROOT'] . "../private_html");
to this:
$private_folder = realpath(ABSPATH . "../private_html");
There are several other solutions to that problem as well, such as using str_replace or rtrim.
This solution worked for me:
$site_root_directory = substr( __DIR__, 0, strpos( __DIR__, "public_html" ) ).'public_html';

In PHP, Best way to ensure current working directory is same as script , when using CLI

When calling php via cli, the current directory is NOT changed to the one of the script. All the scripts i have running in crontab run via the CLI, so this is an issue.
I'm currently fixing the problem by doing a chdir() with the absolute path where the script is, but i REALLY dont like hardcoding paths into stuff like that.
I'm looking for the most portable/reliable method for ensuring that the current working directory is the one where the script it is at.
chdir(dirname(__FILE__));
You can use __FILE__ to get the full absolute path to the executing file itself:
<?php
echo "I'm here: ".__FILE__."\n";
?>
See the documentation for more info.

Categories