What order does PHP read configuration from? - php

PHP configuration can be made in a number of different places:
php.ini
httpd.conf
.htaccess
within a php script via ini_set()
any more?
Some configuration settings can only be set in certain places and there's certain Apache and PHP settings that would prevent you from doing any PHP config changes in .htaccess or with your PHP script. But assuming that a given PHP setting can be set in all of the above places, in what order is this configuration read? In other words what overrides what? (I'm assuming that ini_set() overrides any of the previous settings).

There's compile-time settings before php.ini. The rest of the stages aren't really "configuration". They're more of a way to override settings established in a previous stage. PHP will quite happily run without any other config directives in php.ini/http.conf/.htaccess. php.ini does list (almost?) all the configuration settings available, but that's just a courtesy so you don't have to dig around in the docs to find the one setting you do want to override.

You named them in the correct order.
I don't recommend setting configuration in any other place than a php.ini though.
There are also per-directory php.ini configurations and I don't know which comes first, .htaccess or the directory php.ini but I would guess the .htaccess first and php.ini after.

Apache loads PHP, so Apache's config is read first. .htaccess is also handled by the webserver, so I'm guessing that will be second. Thirdly PHP is loaded. It checks for PHP.ini's in several locations. Also see here. Finally the ini_set is checked runtime.

First, You can use a user.ini file.
I think PHP will read it from the bigger to the smaller, I mean from httpd.conf -> php.ini (and then user.ini if set) -> .htacess -> ini_set()

Related

locate source of local php settings

When I pull up phpinfo() from my webroot it details local and master php config settings. I'm familiar with the principal -- master settings are handled in the main php.ini file and can be overridden in site directories with php.ini files, ini_set() calls, or .htaccess files (depending on how the server is configured).
For a few settings I'm seeing local values that differ from the master settings, and for the life of me, can't locate where they are coming from. The loaded/parsed php.ini section of phpinfo() doesn't shed any light, and I've grep'd the heck out of the server trying to find where specific settings are found in files, without success.
Is there any way to locate the source of a setting?
If you've already checked "loaded ini files" section, there are a few more places where the settings can be defined:
if you're running Apache module, check for php_value in its config files
check for php_value in .htaccess
if you're using fastcgi (with nginx, apache or anything else), extra parameters can be specified in the command line (although who would do this?)
there are also default PHP setting
ini_set directive in the code above or in auto-prepended file defined in auto_prepend_file directive
this page http://php.net/manual/en/configuration.changes.modes.php also mentions something about Windows registry and .user.ini (oh gosh, never thought about this!)

What is PHP_INI_PERDIR and PHP_INI_USER in .user.ini file?

I am beginner to php and learning about ini files. I have read about these two modes PHP_INI_PERDIR and PHP_INI_USER that are recognized in .user.ini file as i read in php.net at php.net but don't understand what these two modes are and why and where these are used.
Can anyone tell ?
The setting PHP_INI_USER allows the developer to set INI settings programatically using ini_set() within PHP code. The setting PHP_INI_PERDIR only allows you to place setting in a configuration file php.ini, .htaccess, httpd.conf the later two are web server configuration files.
The reason why you might put a setting in .htaccess is so that system administrators can expose web server configuration and allow PHP configuration in the same file per web site. The httpd.conf allows for the opposite-- allowing only system administrators (or those who can manage a web server) to make settings in a more secure web server configuration file.
The Mode PHP_INI_USER allow entry to be set in user scripts (like with ini_set()) or in Windows Registry
The Mode PHP_INI_PERDIR allow to entry to set in php.ini, .htaccess, httpd.conf or .user.ini(since PHP 5.3).
We can read detail where a configuration setting may be set in PHP Manual
Hope this will help everyone and make it clear enough between the MODES.

Overriding PHP.ini in a shared development environment

My development environment is shared with other developers of my startup and is setup on Rackspace. The php.ini file is located in /etc/ folder, and I believe this is a centralized location from where every other developer's dev environment setting is being configured from. I want to customize this php.ini file specifically for myself rather than having to do it in the /etc/ location.
Specifically I am setting up XDEBUG in my environment, some other developers don't want it, so I don't want to bug em :)
To do so, I scanned the Internet on how to override the php.ini file specifically for a directory, and found this page on stackoverflow
And following that, I simply copy pasted the php.ini file within my htdocs folder and then simply echoed out phpinfo() (I echoed this in one of my Controllers, (using Zend)). The index.php file is within the htdocs folder.
When I look # "Loaded Configuration File", it still reads
/etc/ instead of ../htdocs/
Anybody know what's up?
In general, it isn't possible to load php.ini on a per directory basis, but in some special cases (CGI/FastCGI), it is: see documentation for Per-user configuration
Since PHP 5.3.0, PHP includes support for .htaccess-style INI files on a per-directory basis. These files are processed only by the CGI/FastCGI SAPI. This functionality obsoletes the PECL htscanner extension. If you are using Apache, use .htaccess files for the same effect.
In addition to the main php.ini file, PHP scans for INI files in each directory, starting with the directory of the requested PHP file, and working its way up to the current document root (as set in $_SERVER['DOCUMENT_ROOT']). In case the PHP file is outside the document root, only its directory is scanned.
If you are hosting several independent sites on one server, you should consider FastCGI anyway, to keep them separated. With php5-fpm it's very easy to setup many pools of workers.
Note that only set a limited subset of the ini-options in the user-ini-file.
As you said you don't have control on the server, the possible work-arounds would be to:
Use ini_set() to override the changes inside your script. Not all of the configuration directives can be changed using ini_set() though.
Use an .htaccess file in your directory to override the configurations in php.ini file.
(certain parts adapted from #1438393)
Hope this helps!
I'm not sure you understood the post. The post means if you run the server and want a per domain php.ini you can run the module as a per domain so each user controls there domain php.ini however it looks like your server does not offer this so you will need to us htaccess file to overwrite the php.ini settings.
By over write this doesn't mean you can change the directory this means maybe add a module or add error reporting ect...
You can do it by using this post: How can I use xdebug to debug only one virtual host?

Changing PHP.ini using htaccess on a Server

I am trying to use PHP's built-in function get_browser(). I followed the instructions in this useful post, but I'm still getting the error
browscap ini directive not set.
I downloaded the php_browscap.ini file and moved it into the same directory as my .htaccess file, so that its location is home/hostname/subdomain/php_browscap.ini Since I do not have access to my php.ini file, I am trying to edit the browscap property using .htaccess. This is what I entered:
php_value browscap home/hostname/subdomain/php_browscap.ini
I don't know if it matters, but below that there's some Rewrite Engine code.
As forementioned, I am still getting the error above. What did I do wrong?
Thanks.
The browscap PHP value has a changeable mode of PHP_INI_SYSTEM meaning it can only be set in php.ini or httpd.conf (not .htaccess).
Do a phpinfo() to understand your PHP runtime config. If your system is configure as "CGI/FastCGI" then it is probably running suPHP as the PHP initiator. In this case you can specify your own php.ini file. By default suPHP looks in the script directory but you can override this by the following directive in your .htaccess file:
suPHP_ConfigPath (expects a path name)
This option tells mod_suphp which path to pass on to the PHP-interpreter (by setting the PHPRC environment variable). Do NOT refer to a file but to the directory the file resists in.
E.g.: If you want to use "/path/to/server/config/php.ini", use "suPHP_Config/path/to/server/config".
If you don't use this option, PHP will use its compiled in default path.
Also you must use a properly formed path in your browsercap directive e.g.
browscap="/home/hostname/subdomain/php_browscap.ini"
(Note the leading /)
Addendum
I've just check and the Dreamhost shared hosting plan uses suEXEC. With suEXEC you can normally override the php.ini patch by copying the system php.ini (phpinfo() tells you where to find this) into a private directory, say _private as well as the browsercap.ini then adding
SetEnv PHPRC /home/hostname/_private
to your .htaccess file. If this doesn't work then the issue is specific to Dreamhost's suEXEC config and you need to ask this Q on http://discussion.dreamhost.com/
There are two potential problems here.
Perhaps your host does not allow you to override ini settings in the .htaccess file.
Maybe browscap does not like the path you have provided. Try:
php_value browscap /home/hostname/subdomain/php_browscap.ini
And ensure that permissions on that file allow the web user to read it.
If you are on a shared hosting and do not have access to the system php.ini then you can use the following standalone replacement of php's native "get_browser()" implementation.
https://github.com/garetjax/phpbrowscap

Can php.ini settings be overridden in by a website using PHP + IIS6?

We have PHP 5.2.6 deployed to c:\php and in that folder there is the php.ini file. On Windows, can a website override these settings similar to the way that apache has .htaccess? e.g.
DirectoryIndex index.php index.html
<IfModule mod_php5.c>
php_flag magic_quotes_gpc off
php_flag register_globals off
</IfModule>
<IfModule mod_php4.c>
php_flag magic_quotes_gpc off
php_flag register_globals off
</IfModule>
Update:
I was aware of ini_set() but wondered if there was a declarative way to do this in a configuration file in the website rather than in script.
I would recommend doing all you can to avoid changing register_globals to on as it's a major security hole.
But you can try using init_set() to change the settings within your PHP code, although some settings cannot be changed once PHP has started running. (These are somewhat server dependent I believe.)
You can override the directives in the php.ini file several ways, but not all directives can be changed by each method. See the php.ini directives page in the manual for a list of the directives and the methods that will work on each one.
The last column in the table lists the methods that will work on that particular method. In increasing level of access:
PHP_INI_USER - Can be set in user
scripts with ini_set() (or any higher method)
PHP_INI_PERDIR - Can be set using
the .htacess file with php_value
for string values or php_flag for
binary values (or any higher method)
PHP_INI_SYSTEM - Can
be set using php.ini or httpd.conf
only (both require access to the server's configuration files)
PHP_INI_ALL - Can be set using
any of the above methods
ini_set should do what you're after -
$option = 'magic_quotes_gpc';
echo "Value of $option => ", ini_get($option);
ini_set($option,0);
echo "New value of $option => ", ini_get($option);
A caveat here is that just because you can set the value at run-time doesn't mean it will work as expected, e.g. setting register_globals at runtime will be of little use as that setting has already done it's job by the time your script starts.
From http://us.php.net/configuration.changes:
Changing PHP configuration via the Windows registry
When running PHP on Windows, the configuration values can be modified on a per-directory basis using the Windows registry. The configuration values are stored in the registry key HKLM\SOFTWARE\PHP\Per Directory Values, in the sub-keys corresponding to the path names. For example, configuration values for the directory c:\inetpub\wwwroot would be stored in the key HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot. The settings for the directory would be active for any script running from this directory or any subdirectory of it. The values under the key should have the name of the PHP configuration directive and the string value. PHP constants in the values are not parsed. However, only configuration values changeable in PHP_INI_USER can be set this way, PHP_INI_PERDIR values can not.
...Haven't actually tried this yet, so your mileage may vary.
I just found a new way of doing this.
First of all, I used phpinfo() to find the PHP.ini being used by my Hosting provider.
Thereafter, I uploaded a file containing the following code to my Hosting space:
$fsrc = fopen($pathToIni,'r');
$fdest = fopen($myHostingDir,'w+');
$len = stream_copy_to_stream($fsrc,$fdest);
fclose($fsrc);
fclose($fdest);
echo $len;
This effectively copied the php.ini to my Hosting space. Thereafter, I downloaded that php.ini, changed the register_globals to off (for which I did all this), and uploaded it to the root of my Hosting space. Bingo, there you go.
I have relied on the fact that IIS uses the complete php.ini if available in a directory. You cannot override only specific settings like that using .htaccess on Apache.
For cgi environments, there is a module called htscanner. It basically fakes .htaccess behavior and allows per directory configurations. Unfortunately I have no experience with this on Windows, let alone with IIS6.

Categories