Different PHP version for each folder on my server

I have little knowledge of how to configure Apache and the server. Currently, my server is running a version of PHP 5.X I would like to upgrade to PHP 7 but there would be a lot of projects that would need to be upgraded.

So here's my question : Can I specify a version of PHP for a specific folder on my server? For example, I have 20 projects in /var/www/html

  • Project 01/
  • Project 02/
  • ...
  • Project 20/

All are working on PHP 5. For my new project, could I force the directory "project 21" to use PHP7 (while the others still use PHP5)?

Thanks.


Solution 1:

It's a bit old question, but here is how to do it, you need to use php-fpm version and fast CGI to do it.

You can do it for example with virtual host config. This example is fitting if you have a root and inside the root multiple websites (from a browser you reach it like this: www.domain.com/site1) this is from my dev environment, so the settings are not fully fit for production:

<VirtualHost *:8080>
    #ServerName www.example.com
    
    <Directory /home/my_user/environment>
        Options Indexes FollowSymLinks
        RewriteEngine on
        RewriteBase /
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
        AllowOverride All
        Require all granted
        
        <FilesMatch ".+\.ph(ar|p|tml)$">
            SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://localhost"
        </FilesMatch>
    </Directory>
    
    <Directory /home/my_user/environment/site1>
        <FilesMatch ".+\.ph(ar|p|tml)$">
            SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://localhost"
        </FilesMatch>
    </Directory>
    <Directory /home/my_user/environment/site2>
        <FilesMatch ".+\.ph(ar|p|tml)$">
            SetHandler "proxy:unix:/run/php/php7.2-fpm.sock|fcgi://localhost"
        </FilesMatch>
    </Directory>

    ServerAdmin webmaster@localhost
    DocumentRoot /home/my_user/environment

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    AccessFileName .htaccess
</VirtualHost>

Or if every site has its own domain you can use multiple vhosts:

<VirtualHost *:8080>
    #ServerName www.example.com
    
    <Directory /home/my_user/environment>
        Options Indexes FollowSymLinks
        RewriteEngine on
        RewriteBase /
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
        AllowOverride All
        Require all granted
        
        <FilesMatch ".+\.ph(ar|p|tml)$">
            SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://localhost"
        </FilesMatch>
    </Directory>

    ServerAdmin webmaster@localhost
    DocumentRoot /home/my_user/environment

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    AccessFileName .htaccess
</VirtualHost>
<VirtualHost *:8080>
    ServerName site1.localhost
    DocumentRoot "/home/my_user/environment/site1"
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>
<VirtualHost *:8080>
    ServerName site2.localhost
    DocumentRoot "/home/my_user/environment/site2"
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

In both examples, the default PHP is 7.3, while site1 runs from 5.6 and site2 from 7.2.

The difference between the two is that you have a domain that only points to that website or it points to multiple and just the route determinate which website should be displayed.

Side note, if you have multiple virtual hosts files, apache will choose the most specific one, that's what we using out in the second example.

This config represents ubuntu/debian systems, i.e. centos the sockets placed in a different location.

All used PHP version config needs to be enabled via a2enconfig command before you can use it.* EDIT: *Actually not. I have all disabled and just the vhost determinate which PHP needs to run on which directory/site. I had to do this because I have a simple script that changes the default PHP version.

But it also possible without a virtual host, in this case, you need something like this between the config files:

<Directory /home/my_user/environment>
    Options Indexes FollowSymLinks
    RewriteEngine on
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
    AllowOverride All
    Require all granted

    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://localhost"
    </FilesMatch>
</Directory>

<Directory /home/my_user/environment/site1>
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://localhost"
    </FilesMatch>
</Directory>
<Directory /home/my_user/environment/site2>
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
</Directory>

Some other notes that my apache root is in my user's home directory/environment. So I can easily access my web server files. For this I running apache as my user and group to prevent file permission issues.
You may also need to change the port where the apache runs (in my example 8080).

Solution 2:

I had a very similar question: "How do I test a newer version of PHP without disrupting my existing code running an older version of PHP?"

I tried the different solutions provided through some of the other links above, including trying to use the .htaccess file to try to force a specific PHP version for just one directory, but they didn't work. I'm using a shared hosting service, so I don't have the ability to reconfigure Apache or anything like that either.

Here is a solution that does work, although not necessarily exactly in the way you requested:

I used a subdomain. I created a subdomain called "test" (could have been called "Project20" as in the question above) which I could then access using test.mydomain.com. Using my shared hosting service (Lunarpages) I was able to set up a separate directory called "test" (could have been "Project20") and put my PHP 7 files in it for testing. Then I chose for only this subdomain to use PHP 7.2 instead of PHP 5.6. Voila!

Here how, step by step (this was done on a shared hosting service using the web-based cPanel for site administration and ftp to put the files on the server:

  1. In cPanel choose "Subdomains" and create a new subdomain, such as "test", then set the document root to "/public_html/test".

  2. Create the "/public_html/test" directory and fill it with your project test files.

  3. In cPanel use MultiPHPManager to choose PHP 7.2 for the subdomain "test.mydomain.com" ONLY. (Note that this MultiPHPManager tool seems to be new, there may be other ways.)

Now accessing test.mydomain.com with your web browser runs any php file using the new PHP version, and the rest of your main site is unaffected.

Here is a good way to test whether this worked:

  1. Create a file called phpinfo.php with the following code in it:

    <? phpinfo(); ?>

  2. Then before switching to the new version of PHP (before step 3 above) visit the web page "test.mydomain.com/phpinfo.php" and you should see your old PHP version displayed.

  3. Then complete step 3 above and refresh the page and you should see the new PHP version displayed. Voila!

Sorry for not having a nice command-line version of these directions for you, but I don't have shell access to my hosting provider...