当使用 PHP 作为 Apache 模块时,也可以用 Apache 的配置文件(例如 httpd.conf)和 .htaccess 文件中的指令来修改 PHP 的配置设定。需要有“AllowOverride Options”或“AllowOverride All”权限才可以。
有几个 Apache 指令可以使用户在 Apache
配置文件内部修改 PHP 的配置。哪些指令属于
PHP_INI_ALL
,PHP_INI_PERDIR
或 PHP_INI_SYSTEM
中的哪一个,请参考附录中的
php.ini 配置选项列表。
php_value
name
value
设定指定的值。只能用于
PHP_INI_ALL
或 PHP_INI_PERDIR
类型的指令。要清除先前设定的值,把 value 设为 none。
Note: 不要用
php_value
设定布尔值。应该用php_flag
(见下面)。
php_flag
name
on|off
用来设定布尔值的配置指令。仅能用于
PHP_INI_ALL
和
PHP_INI_PERDIR
类型的指令。
php_admin_value
name
value
设定指定的指令的值。不能用于 .htaccess
文件。任何用 php_admin_value
设定的指令都不能被 .htaccess 或 virtualhost
中的指令覆盖。要清除先前设定的值,把 value 设为 none。
php_admin_flag
name
on|off
用来设定布尔值的配置指令。不能用于 .htaccess
文件。任何用 php_admin_flag
设定的指令都不能被 .htaccess 或 virtualhost
中的指令覆盖。
Example #1 Apache 配置例子
<IfModule mod_php5.c> php_value include_path ".:/usr/local/lib/php" php_admin_flag engine on </IfModule> <IfModule mod_php4.c> php_value include_path ".:/usr/local/lib/php" php_admin_flag engine on </IfModule>
PHP 常量不存在于 PHP 之外。例如在
httpd.conf 中不能使用 PHP 常量如
E_ALL
或 E_NOTICE
来设定
error_reporting
指令,因为其无意义,实际等于
0。应该用相应的掩码值来替代。这些常量可以在
php.ini 中使用。
在 Windows 下运行 PHP 时,可以用 Windows
注册表以目录为单位来修改配置。配置值存放于注册表项
HKLM\SOFTWARE\PHP\Per Directory Values
下面,子项对应于路径名。例如对于目录
c:\inetpub\wwwroot 的配置值会存放于
HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot
项下面。其中的设定对于任何位于此目录及其任何子目录的脚本都有效。项中的值的名称是
PHP 配置指令的名字,值的数据是字符串格式的指令值。值中的 PHP
常量不被解析。不过只有可修改范围是 PHP_INI_USER
的配置值可以用此方法设定,PHP_INI_PERDIR
的值就不行。
无论怎样运行 PHP,都可以在脚本中通过 ini_set() 而在运行时修改某个值。更多信息见手册中 ini_set() 的页面。
如果对自己系统中的配置设定及其当前值的完整列表感兴趣,可以运行 phpinfo() 函数并查看其结果的页面。也可以在运行时用 ini_get() 或 get_cfg_var() 取得个别配置指令的值。
nick at vistaworks dot net (2012-08-01 15:42:50)
On Windows, as the documentation above states, you cannot set max_upload_filesize and post_max_size in the registry, because they are PHP_INI_PERDIR.
Confusingly, however, is the fact that phpinfo() will show your changes if you do add those to the regsitry, as if they were taking effect. However, the upload size is *not* changed, regardless of what phpinfo() reports.
I believe the reading of registry values and override happen 'too late' in the request processing, ie, after the file has already been uploaded and rejected.
In a perfect world, phpinfo() would recognize this and not report the overridden values, which is very confusing.
Anonymous (2012-01-03 20:15:07)
For Mac users (Leopard/Tiger/Lion) it's worth knowing exactly where your httpd.conf and php.ini ares picked up, but, out of the box, these are defined only in the compiler settings as defaults.
The httpd binary was compiled with default settings of
SERVER_CONFIG_FILE="/private/etc/apache2/httpd.conf"
meaning starting apache using apachectl picks up this httpd.conf without it being specified on the command line via the org.apache.httpd.plist file is /System/Library/LaunchDaemons.
Again, the default httpd.conf does not contain a PHPIniDir, and locates php.ini via libphp5.so in /etc - you would need to create one here (using one of the php.ini.default templates if you want).
It's worth changing the PHPIniDir setting in httpd.conf setting to eg.:
Configuration File /usr/local/php5/lib/php.ini
so you know exactly which php.ini is being used at all times.
phpinfo() will then advise you that it's using this file.
user at NOSPAM dot example dot com (2011-09-13 11:16:41)
PHP Constants will work with php_value; for example:
php_value error_reporting 30711 #bitmask is the same as
php_value error_reporting "E_ALL & ~E_STRICT & ~E_NOTICE" #string of constants
rohitkumar at cftechno dot com (2011-06-29 00:23:32)
Open php.ini from c:/php in your text editor
If you installed Apache in the default location, the path should
be "C:\Program Files\Apache Software Foundation\Apache2.2\htdocs". If you installed
it elsewhere, find the htdocs folder and type its path:
doc_root = "C:\Program Files\Apache Software Foundation\Apache2.2\htdocs"
Just a little further down in the file, look for the line that begins with remove the semicolon from the start of the extension_
dir, and set it so that it points to the ext subfolder of your PHP folder:
extension_dir = "C:\PHP\ext"
These are optional extensions to PHP, disabled by default. We
want to enable the MySQL extension so that PHP can communicate with MySQL.
To do this, remove the semicolon from the start of the php_mysqli.dll line:
extension=php_mysqli.dll
note - php_mysqli, not php_mysql
Keep scrolling even further down in the file, and look for a line that starts with
;session.save_path. Once again, remove the semicolon to enable this line,
and set it to your Windows Temp folder:
session.save_path = "C:\Windows\Temp"
Browse to the conf subfolder in your Apache
installation folder (by default, C:\Program Files\Apache Software
Foundation\Apache2.2\conf), and select the httpd.conf file located there. In order
to make this file visible for selection, you’ll need to select All Files (*.*) from the
file type drop-down menu at the bottom of the Open window.
Look for the existing line in this file that begins with DirectoryIndex, shown
here:
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
This line tells Apache which filenames to use when it looks for the default page
for a given directory. Add index.php to the end of this line:
<IfModule dir_module>
DirectoryIndex index.html index.php
</IfModule>
All of the remaining options in this long and intimidating configuration file
should have been set up correctly by the Apache install program. All you need
to do is add the following lines to the very end of the file:
LoadModule php5_module "C:/PHP/php5apache2_2.dll"
AddType application/x-httpd-php .php
PHPIniDir "C:/PHP"
Make sure the LoadModule and PHPIniDir lines point to your PHP installation
directory, and note the use of forward slashes (/) instead of backslashes (\) in
the paths.
Save your changes and Restart Apache using the Apache Service Monitor system tray icon. If all is
well, Apache will start up again without complaint.
fay at prospekt-omsk dot ru (2011-01-31 00:52:11)
x64 based Windows registry path is
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\PHP\Per Directory Values
self at pabloviquez dot com (2009-06-14 18:07:24)
Note that, changing the PHP configuration via the windows registry will set the new values using php_admin_value. This makes that you cannot override them on runtime.
So for example, if you set the include_path on the windows registry and then you call the set_include_path function in your application, it will return false and won't change the include_path.
cawoodm at gmail dot com (2009-05-04 07:41:02)
With IIS it can become confusing that changes to php.ini are ineffective. It seems it is necessary to restart the application pool for the changes to be seen. It would be great if this was not necessary - I am sure I have worked with systems where php.ini changes were immediately effectvie.
ravi at syntric dot net (2009-03-08 22:52:06)
Just a quick note regarding per-directory php settings. A number of flags can be set custom to a particular app's requirement based on one of two methods describe her http://www.cognitivecombine.com/?p=207
I particularly stumbled upon this to turn off register_globals. Drupal, for e.g., required this to be off but I knew of numerous php apps that had code which relied on these globals. The .htaccess method described in the above URL worked for my case.
hyponiq at gmail dot com (2009-02-09 09:11:58)
Running PHP under Apache poses a major problem when it comes to per-directory configuration settings for PHP. In Apache virtual hosting, only a master PHP configuration file (i.e. php.ini) is parsed at run-time per PHP script. Under IIS 6.0 or greater, you can include per-directory PHP configuration files to override or overwrite the master configuration settings. The issue here, however, is having Apache virtual hosts override/overwrite master settings; not what IIS can do.
So, there are two possible solutions. The first solution is described in this section and uses the Apache configuration settings php_value, php_flag, php_admin_value, and php_admin_flag. In that, each virtual host which you'd like to have certain configuration settings changed must have these directives set (and that is for each PHP configuration setting). This, to me, is the more viable solution, although it is time-consuming and mentally taxing.
The other possible solution is to set the PHPRC environment variable. To my knowledge, all implementations of Apache HTTPD allow for the SetEnv directive to set the PHPRC variable per-virtual-host. What that does is tell PHP to look in the specified location for that virtual host's configuration settings file (i.e. "C:/path/to/custom/php.ini"). The only downside to this tactic is that EVERY virtual host's custom php.ini file must contain all set parameters. In other words, every single PHP configuration directive you have set in the master php.ini file must ALSO be set in per-virtual-host configuration settings. Doesn't that suck? It seems rather redundant to me (and completely defeats the purpose) that you have to include all configuration settings OVER AND OVER AGAIN.
The great thing about per-directory configuration settings (when they're implemented correctly) is that PHP already has the master settings pre-loaded and the per-directory settings (which may only ammount to one directive in difference) can be loaded per request and, thus, there is less over-head.
There really is more to this topic than that, which is why I blogged a rather lengthy and detailed article here: http://hyponiq.blogspot.com/2009/02/apache-php-multiple-phpini.html This information is meant to help users and administrators. I highly suggest it be read if anyone has any questions on Apache and PHP configurations. I have included some examples that illustrate the two possible solutions, as well. I did my best to research everything before I wrote the article.
I hope this helps!
==== 10-FEB-09: ====
I must add a little more information:
I've done some thorough testing on my PC as to the PHPRC environment variable set by the Apache directive SetEnv. It seems to me that this variable is completely disregarded using that directive. I tried everything and can only come to the conclusion that either A) I did something very wrong, or B) that it simply doesn't work as expected.
The former solution, however, does work magically! So, to expand on my previous post, the only real and viable solution to this problem is to use the php_value, php_flag, php_admin_value and php_admin_flag directives in your virtual hosts configurations.
Once again, it can be very boring! But it does work.
ludek dot stepan at gmail dot com (2008-09-25 04:37:09)
Hello,
I've found this directive useful for setting per-file php.ini options. For example, when I want to have my .css styles processed as php scripts, I put this code into .htaccess to setup correct mimetype.
AddHandler php5-script .css
<FilesMatch "\.css$">
php_value default_mimetype "text/css"
</FilesMatch>
Yours Ludek
contrees.du.reve at gmail dot com (2008-02-02 05:25:38)
Being able to put php directives in httpd.conf and have them work on a per-directory or per-vitual host basis is just great. Now there's another aspect which might be worth being aware of:
A php.ini directive put into your apache conf file applies to php when it runs as an apache module (i.e. in a web page), but NOT when it runs as CLI (command-line interface).
Such feature that might be unwanted by an unhappy few, but I guess most will find it useful. As far as I'm concerned, I'm really happy that I can use open_basedir in my httpd.conf file, and it restricts the access of web users and sub-admins of my domain, but it does NOT restrict my own command-line php scripts...
webmaster at htaccesselite dot com (2007-07-11 20:18:14)
To change the configuration for php running as cgi those handy module commands won't work.. The work-around is being able to tell php to start with a custom php.ini file.. configured the way you want.
With multiple custom php.ini files
-------------------------------------------
/site/ini/1/php.ini
/site/ini/2/php.ini
/site/ini/3/php.ini
--
The trick is creating a wrapper script to set the location of the php.ini file that php will use. Then it exec's the php cgi.
shell script /cgi-bin/phpini.cgi
-------------------------------------------
#!/bin/sh
export PHPRC=/site/ini/1
exec /cgi-bin/php5.cgi
--
Now all you have to do is setup Apache to run php files through the wrapper script instead of just executing the php cgi.
In your .htaccess or httpd.conf file
-------------------------------------------
AddHandler php-cgi .php
Action php-cgi /cgi-bin/phpini.cgi
--
So to change the configuration of php you just need to change the PHPRC variable to point to a different directory containing your customized php.ini.. You could also create multiple shell wrapper scripts and create multiple Handler's+Actions in .htaccess..
in your .htaccess
-------------------------------------------
AddHandler php-cgi1 .php1
Action php-cgi1 /cgi-bin/phpini-1.cgi
AddHandler php-cgi2 .php2
Action php-cgi2 /cgi-bin/phpini-2.cgi
AddHandler php-cgi3 .php3
Action php-cgi3 /cgi-bin/phpini-3.cgi
--
The only caveat here is that it seems like you would have to rename the file extensions, but there are ways around that too ->
http://www.askapache.com/php/custom-phpini-tips-and-tricks.html
Woody/mC (2007-07-09 06:09:14)
@ pgl: As the documentation says:
"To clear a previously set value use none as the value."
Works fine for me.
pgl at yoyo dot org (2007-06-27 03:59:14)
It is not possible to unset a config option using php_value. This caused me problems with auto_prepend_file settings where I wanted to have a global file auto included, with an exception for only one site. The solution used to be to use auto_prepend_file /dev/null, but this now causes errors, so I just create and include blank.inc now instead.