PHP
Run PHP two ways. A PHP site keeps its files like a classic host, with .htaccess. A PHP app from GitHub is built fresh on every deploy, Symfony included.
Updated 27 Oct 20264 min read
PHP runs on Tanzahost in two ways. Pick the one that fits how your code changes:
| What | A PHP site | A PHP app |
|---|---|---|
| Add it with | Add a service, then App or website, with a ZIP without Composer | Add a service, then App or website |
| Its files | Kept, and changed in place: by the site itself, the file manager or a ZIP | Set up fresh with each version: from GitHub, a ZIP or a change in the file manager |
| Good for | Classic PHP sites, sites moved from cPanel | Symfony, Laravel and any PHP with Composer |
.htaccess | Works as you expect | Works too |
Both choose from the same PHP versions, extensions and settings.
PHP versions
| Version | Notes |
|---|---|
| PHP 8.5 | Supported |
| PHP 8.4 | What new sites and apps get when they don't ask |
| PHP 8.3 | Supported |
| PHP 8.2 | Supported |
| PHP 8.1 | No more security fixes from its makers: a warning, and builds move to a supported version after 2027-12-31 |
| PHP 8.0 | The same as 8.1 |
PHP 7.4 isn't offered for new sites or apps.
A PHP site
Open your project, choose Add a service, then App or website.
Under Where's your code?, choose Upload a ZIP and drop your site's ZIP. A ZIP of PHP files without
composer.json, or with a cPanelpublic_htmlfolder, runs As a website by itself; you can still choose As an app.Give it a name and choose its PHP version. You can change it later on the site's page: the site restarts on the new version with no downtime, and its files stay.
Choose Deploy.
From a cPanel backup, the ZIP's top public_html folder becomes the site, and the rest of the ZIP is kept aside in a from-zip folder for you to look at. Later, Replace the files with a ZIP on the site's page does the same again; the files it replaces stay in the trash for 7 days.
Edit any file in the file manager, and run scripts on a timetable with scheduled tasks, like cPanel's cron jobs:
php scripts/report.phpA PHP app from code
We see PHP when the code has composer.json, index.php or public/index.php. With composer.json, we run:
composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-progressWe recognise Laravel, Symfony and WordPress. The app is served by the same web server as our sites, from public/ when your code has one, from web/ when it has web/index.php, and otherwise from the top folder, several requests at a time, with .htaccess working. If package.json has a build script, we install Node.js and build your assets too. For Laravel, follow Deploy a Laravel app. Symfony apps run their Doctrine migrations (when they use them) and cache:warmup before each version goes live.
The version comes from every constraint your code states: require.php in composer.json, config.platform.php, and the php of every package in composer.lock. We use our default, PHP 8.4, when all of them allow it, otherwise the newest version they all allow. So "php": ">=8.2" with a lock that stops at 8.4 builds with 8.4, never a version your packages refuse. To pin one, choose it in Set up and run, or in tanzahost.json; if your packages don't accept it, we say so before the build.
Extensions
Every PHP already has the common extensions, like ctype, curl, dom, fileinfo, mbstring, openssl, pdo, pdo_sqlite, session, sodium and xml. From PHP 8.5, opcache is built in too. You can add these:
apcu, bcmath, bz2, calendar, exif, gd, gmp, imagick, imap (where your PHP version still has it), intl, ldap, memcached, mongodb, mysqli, opcache, pcntl, pcov, pdo_mysql, pdo_pgsql, pgsql, redis, soap, sockets, tidy, xsl, zip.
A PHP app gets what its code needs by itself, each with the reason on its plan:
the extensions
composer.jsonandcomposer.lockrequire ("ext-gd": "*"), from any package, unless a polyfill provides them;the ones well-known packages use without saying: gd for
spatie/laravel-medialibrary,intervention/imageandbarryvdh/laravel-dompdf; gd and zip formaatwebsite/excel; pcntl for Horizon and Octane; redis when your queue, cache or sessions use Redis through phpredis; mongodb formongodb/laravel-mongodb;the database's own:
pdo_mysqlorpdo_pgsql.
The most common ones are ready on every server, so most builds start straight away. Tick others under PHP extensions in Set up and run, or on a site's PHP settings. If your code needs one that isn't on the list, the plan says so before the build, with Ask us to add it.
PHP settings
Like cPanel's INI editor, from an allowed list:
| Setting | Allowed |
|---|---|
upload_max_filesize, post_max_size | Up to 2G |
memory_limit | Up to the app's memory limit |
max_execution_time, max_input_time | Up to 600 seconds |
max_input_vars | Up to 100,000 |
display_errors, opcache.enable | On or Off |
date.timezone | A time zone, like Europe/London or UTC |
session.gc_maxlifetime | Up to 30 days, in seconds |
Others are refused, so nothing can switch off what keeps your app safe. On a site, saving restarts it with no downtime and your files stay as they are. On an app, they're added when it next builds.
Example: Asha's old order form
Before duka moved to Laravel, Asha had a small order form in plain PHP on her old cPanel host. She downloads its backup, adds a PHP site named orders with PHP 8.4, and chooses A ZIP file. Its public_html becomes the site, and her .htaccess rewrites work as before. In PHP settings she raises the largest upload to 20M for her product photos.