Configuration methods in PHP to enable large uploads on a per-site basis
June 07, 2010
As dry as the subject of PHP configuration is, I thought a blog entry was necessary as I’ve just spent a fair bit of time digging around to find a way to configure PHP directives on a per-site basis. The mechanisms available vary based on the runtime environment and the method PHP runs.
My problem was to set PHP directives on a per site basis in order to enable large file uploads on a single web application running on the web server. I also wanted to modify the temporary upload folder PHP uses for file uploads, and enable file upload progress monitoring through the APC extension (preferrably only on the file uploader web app). The directives corresponding to these are in a number of different “modes”, so I was looking for a way that provided complete freedom over specifying the directives.
Depending on your PHP install and operating system there are several ways to customise your site’s PHP configuration. PHP itself can run in CGI mode, or as an Apache module. I’ll leave it to http://docs.joomla.org/Should_PHP_run_as_a_CGI_script_or_as_an_Apache_module%3F#What_is_the_difference_between_CGI_and_apache_Module_Mode.3F as it does a great job at explaining security and performance differences between PHP running in CGI or Apache module mode.
Determining your PHP runtime environment.
To determine the best way for configuring PHP on a per-site basis you’ll need to determine your PHP runtime environment (i.e. your operating system and whether PHP runs as a CGI or an Apache module). So, create a script that outputs your PHP runtime environment information:
<?phpphpinfo();?>
You should then look at the “Server API” field, which will say something like “CGI/FastCGI” for PHP running as a CGI:
or “Apache Handler” for PHP running as an Apache module:
Now we’ve identified the mode of operation, I’ll explain some general methods for customising PHP directives on a per-site basis:
General per-site configuration methods
This should work on PHP running in any environment (Linux/Windows/Mac/etc) as either an Apache module or CGI.
Use ini_set() (limited number of options available)
You can customise a limited number of PHP directives on a per-script basis, by adding ini_set()
to the top of your scripts. You can adjust PHP_INI_USER
directives within scripts. See http://uk.php.net/ini_set for more information on this.
Allow user defined INI files (greater number of options available)
Edit your php.ini
to permit user defined .ini files, by looking for a field user_ini.filename
(which might be currently commented out). Uncomment it and state the filename you want to use for the user defined .ini files (which by default is .user.ini
).
Then, within your web application (e.g. C:\phpwebs\helloworld
), create a new file called .user.ini
and add in the directives to suit:
upload_max_filesize = 1024M post_max_size = 1500M
You can adjust PHP_INI_PERDIR
and PHP_INI_USER
directives in user defined INI files, which may or may not be enough. In my case, it was not, as I wanted to also update upload_tmp_dir
, a PHP_INI_SYSTEM
directive.
Define folder and directives in php.ini (most, if not all options available)
In this approach, you edit php.ini
wherever it is located (see output from phpinfo()
above), and at the end add your site-specific configuration, by specifying the folder that the web application resides in. Lets say our web app is located in C:\phpwebs\helloworld\
. To configure the PHP runtime on this web app, add
\[PATH=C:/phpwebs/helloworld/\]upload\_max\_filesize = 1024Mpost\_max\_size = 1500M
At the end of php.ini
.
Note virtually any directive can be customised on a per-site basis using this method, and this was the approach I went for when hosting a PHP web app on IIS to in order to adjust upload_tmp_dir
for the uploader app. What I didn’t seem to be able to do was to enable some extension based directives on a per site basis. The progress meter failed when apc.rfc1867=on
was specified under the per-site declaration, so I made this part of the global php.ini.
Per-site configuration options with PHP as a CGI in Windows IIS
Any of the general per-site configuration options mentioned above should work. You can also edit the registry to manage a subset of PHP directives, illustrated at http://www.php.net/manual/en/configuration.changes.php, in the section entitled ‘Changing PHP configuration via the Windows registry’. The process is as follows:
- Open up regedit
- Navigate to HKLM\SOFTWARE\PHP\Per Directory Values
- Create keys corresponding to the directory hierarchy of your web app and at the child node specify the customised directives via
New > String Value
. Using ourC:\phpwebs\helloworld\
example see the screenshot below for how you modify PHP directives:
Note that you can customise only PHP_INI_USER
directives in this manner.
Per-site configuration options with PHP as an Apache module
All-in-one *AMP stacks (such as XAMPP) mostly have PHP running as an Apache module. Any of the general per-site configuration options mentioned above should also work for PHP configured as an Apache module.
If your PHP install in running this way, you can also edit httpd.conf
file to specify PHP directives for virtual hosts and additionally directories and subdirectories exposed by the virtual host.
To do this:
1. Ensure AllowOverride All
in httpd.conf
. This should reside in the conf
folder in the Apache folder.
2. In XAMPP, virtual host declarations are containerised and are specified in <apache_dir>/conf/extra/http-vhosts.conf
. In this file you would type the following:
DocumentRoot "C:/phpwebs/helloworld"ServerName www.helloworld.comphp\_admin\_value upload\_tmp\_dir "C:\\tmp"php\_value post\_max\_size 1500Mphp\_value upload\_max\_filesize 1024Mphp\_admin\_value apc.rfc1867 on
With this method you have complete freedom over which PHP directives you want to set. Valid apache directive syntax can be found at http://www.php.net/manual/en/configuration.changes.php.