# PHP

**Note**: 

You can now use the Upsun Fixed [composable image](https://fixed.docs.upsun.com/create-apps/app-reference/composable-image.md) to install runtimes and tools in your application container.
To find out more about this feature, see the [dedicated documentation page](https://fixed.docs.upsun.com/create-apps/app-reference/composable-image.md). 
Also, see how you can [modify your PHP runtime when using a composable image](#modify-your-php-runtime-when-using-a-composable-image).

## Supported versions

You can select the major and minor version.

Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.

| Grid | Dedicated Gen 2 |
| 

   - 8.5

   - 8.4

   - 8.3

   - 8.2

   - 8.5

   - 8.4

   - 8.3

   - 8.2

   - 8.1

   - 8.0

Note that from PHP versions 7.1 to 8.1, the images support the Zend Thread Safe (ZTS) version of PHP.

### Specify the language

To use PHP, specify `php` as your [app's `type`](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types):

```yaml  {location=".platform.app.yaml"}
type: 'php:<VERSION_NUMBER>'
```

For example:

```yaml  {location=".platform.app.yaml"}
type: 'php:8.5'
```

### Deprecated versions

The following versions are [deprecated](https://fixed.docs.upsun.com/glossary.md#deprecated-versions).
They're available, but they don't receive security updates from upstream and aren't guaranteed to work.
They'll be removed in the future – consider migrating to a [supported version](#supported-versions).

| Grid | Dedicated Gen 2 |
| 

   - 8.1

   - 8.0

   - 7.4

   - 7.3

   - 7.2

   - 7.1

   - 7.0

   - 5.6

   - 5.5

   - 5.4

   - 7.4

   - 7.3

   - 7.2

   - 7.1

   - 7.0

## Usage example

Configure your app to use PHP on Upsun Fixed.

### 1. Specify the version

Choose a [supported version](#supported-versions)
and add it to your [app configuration](https://fixed.docs.upsun.com/create-apps/_index.md):

```yaml  {location=".platform.app.yaml"}
type: 'php:8.5'
```
### 2. Serve your app

To serve your app, define what (and how) content should be served by setting the [`locations` parameter](https://fixed.docs.upsun.com/create-apps/image-properties/web.md#locations).

Usually, it contains the two following (optional) keys:

- `root` for the document root,
  the directory to which all requests for existing `.php` and static files (such as `.css`, `.jpg`) are sent.
- `passthru` to [define a front controller](https://fixed.docs.upsun.com/create-apps/web/php-basic.md#set-different-rules-for-specific-locations) to handle nonexistent files.
  The value is a file path relative to the [app root](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory).

  **Note**: 

For enhanced security, when setting ``passthru`` to ``true``, you might also want to add the following configuration:

 - Set ``scripts`` to ``false``.
This prevents PHP scripts from being executed from the specified location.

 - Set ``allow`` to ``false``.
By default, when PHP scripts aren’t executed, their source code is delivered.
Setting ``allow`` to ``false`` allows you to keep the source code of your PHP scripts confidential.

Adjust the `locations` block to fit your needs.

In the following example, all requests made to your site's root (`/`) are sent to the `public` directory
and nonexistent files are handled by `app.php`:

```yaml  {location=".platform.app.yaml"}
web:
  locations:
    '/':
      root: 'public'
      passthru: '/app.php'
```
See how to [create a basic PHP app with a front controller](https://fixed.docs.upsun.com/create-apps/web/php-basic.md).
To have more control, you can define rules to specify which files you want to allow [from which location](https://fixed.docs.upsun.com/create-apps/web/php-basic.md#set-different-rules-for-specific-locations).

### Complete example

A complete basic app configuration looks like the following:

```yaml  {location=".platform.app.yaml"}
name: 'myapp'

type: 'php:8.5'

disk: 2048

web:
  locations:
    '/':
      root: 'public'
      passthru: '/app.php'
```
## Dependencies

Up to PHP version 8.1, it's assumed that you're using [Composer](https://getcomposer.org/) 1.x to manage dependencies.
If you have a `composer.json` file in your code, the default [build flavor is run](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build):

```bash
composer --no-ansi --no-interaction install --no-progress --prefer-dist --optimize-autoloader
```

To use Composer 2.x on your project, either use PHP 8.2+ or, in your app configuration, add the following [dependency](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies):

```yaml  {location=".platform.app.yaml"}
dependencies:
  php:
    composer/composer: '^2'
```
Adding a dependency to the [dependencies block](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies) makes it available globally.
So you can then use included dependencies as commands within your app container.
You can add multiple global dependencies to the dependencies block, such as [Node.js](https://fixed.docs.upsun.com/languages/nodejs.md#2-specify-any-global-dependencies).

If you want to have more control over Composer or if you don't want to use Composer at all, adapt the [build flavor](#change-the-build-flavor).
You can also use a [private, authenticated third-party Composer repository](https://fixed.docs.upsun.com/languages/php/composer-auth.md).

### Change the build flavor

If you need more control over the dependency management,
you can either use your custom build flavor
or interact with Composer itself through [its environment variables](https://getcomposer.org/doc/03-cli.md#environment-variables).

You can remove the default build flavor and run your own commands for complete control over your build.
Set the build flavor to `none` and add the commands you need to your `build` hook, as in the following example:

```yaml  {location=".platform.app.yaml"}
build:
    flavor: none

hooks:
    build: |
        set -e
        composer install --no-interaction --no-dev
```
That installs production dependencies with Composer but not development dependencies.
The same can be achieved by using the default build flavor and [adding the `COMPOSER_NO_DEV` variable](https://fixed.docs.upsun.com/development/variables/set-variables.md).

See more on [build flavors](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build).

### Alternative repositories

In addition to the standard `dependencies` format,
you can specify alternative repositories for Composer to use as global dependencies.
So you can install a forked version of a global dependency from a custom repository.

To install from an alternative repository:

1. Set an explicit `require` block:

```yaml  {location=".platform.app.yaml"}
dependencies:
  php:
    require:
      "platformsh/client": "2.x-dev"
```
   This is equivalent to `composer require platformsh/client 2.x-dev`.

2. Add the repository to use:

```yaml  {location=".platform.app.yaml"}
repositories:
  - type: vcs
    url: "git@github.com:platformsh/platformsh-client-php.git"
```
That installs `platformsh/client` from the specified repository URL as a global dependency.

For example, to install Composer 2 and the `platformsh/client 2.x-dev` library from a custom repository,
use the following:

```yaml  {location=".platform.app.yaml"}
dependencies:
  php:
    require:
      composer/composer: '^2'
      "platformsh/client": "2.x-dev"
    repositories:
      - type: vcs
        url: "git@github.com:platformsh/platformsh-client-php.git"
```

### Configure security blocking {#configure-security-blocking}

When building a PHP app, Upsun runs `composer install`, which runs the latest available Composer version.

By default, PHP builds fail if a dependency in a project has a known vulnerability. A PHP build might also fail if a dependency is abandoned. 

**The best practice is to upgrade the dependencies** to reduce security risks and to catch issues sooner. However, you can configure the level of security blocking by defining the following keys in the `.dependencies.php.config` section of your `.platform.app.yaml` configuration file. 

| Key                     | Description                                                      |
| ------------------------| ---------------------------------------------------------------- |
| `audit.block-insecure`  | Default is `true`. **Important: Upsun recommends keeping this default setting and upgrading affected dependencies to reduce security risks.**                                  | 
| `audit.block-abandoned` | Default is `false`; set to `true` for even stricter security. Ignored if `audit.block-insecure` is `false`.                  |
| `audit.ignore`          | Array of specific advisories to ignore; see example below.        | 
| `audit.ignore-severity` | Ignore vulnerabilities based on their severity rating (`low`/`medium`/`high`). See the example below.<BR>For each rating, include an `apply` key with one of these values: - `all` to ignore everything for this rating -  `block` to ignore this severity level for blocking builds (but still flag findings in audit reports) - `audit` to ignore this severity level in audit reports (but still block builds) |

Examples: 
```yaml  {location=".platform.app.yaml"}
applications:
  # The app's name, which must be unique within the project.
  myapp:
    type: 'php:8.5'

    dependencies:
      php:
        config:
          audit:
            ignore:  # ignore these security advisories
              - "PKSA-yhcn-xrg3-68b1"
              - "PKSA-2wrf-1mxk-1pky"
```

```yaml  {location=".platform.app.yaml"}
applications:
  # The app's name, which must be unique within the project.
  myapp:
    type: 'php:8.5'

    dependencies:
      php:
        config:
          audit:
            ignore-severity:
              low:
                apply: all   # ignore all low severity findings
```

Related information: 
- [Troubleshooting PHP builds that now fail](https://fixed.docs.upsun.com/languages/php/troubleshoot.md#build-failure-security-blocking)

### Additional Composer schema properties
In addition to [alternate repositories](#alternative-repositories), other
[Composer schema properties](https://getcomposer.org/doc/04-schema.md) can be added to the global dependencies. For
example, one of your dependencies may be a plugin where you need to explicitly whitelist it as an
[allowed-plugin](https://getcomposer.org/doc/06-config.md#allow-plugins).

To add additional composer schema properties:

1. Set an explicit `require` block:

```yaml  {location=".platform.app.yaml"}
applications:
  # The app's name, which must be unique within the project.
  myapp:
    type: 'php:8.5'

    dependencies:
      php:
        require:
          "third-party/required-plugin"": "^3.0"
```

2. Add each additional property as a block at the same indentation as the `require` block:

```yaml  {location=".platform.app.yaml"}
applications:
  # The app's name, which must be unique within the project.
  myapp:
    type: 'php:8.5'

    dependencies:
      php:
        require:
          symfony/runtime: '*'
        config:
          "allow-plugins":
            symfony/runtime: true
```

## Connect to services

The following examples show how to use PHP to access various [services](https://fixed.docs.upsun.com/add-services.md).
The individual service pages have more information on configuring each service.

```php {}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Memcached service.
$credentials = $config->credentials('memcached');

try {
    // Connecting to Memcached server.
    $memcached = new Memcached();
    $memcached->addServer($credentials['host'], $credentials['port']);
    $memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);

    $key = "Deploy day";
    $value = "Friday";

    // Set a value.
    $memcached->set($key, $value);

    // Read it back.
    $test = $memcached->get($key);

    printf('Found value <strong>%s</strong> for key <strong>%s</strong>.', $test, $key);

} catch (Exception $e) {
    print $e->getMessage();
}

```
```php {}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;
use MongoDB\Client;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// The 'database' relationship is generally the name of primary database of an application.
// It could be anything, though, as in the case here here where it's called "mongodb".
$credentials = $config->credentials('mongodb');

try {

    $server = sprintf('%s://%s:%s@%s:%d/%s',
        $credentials['scheme'],
        $credentials['username'],
        $credentials['password'],
        $credentials['host'],
        $credentials['port'],
        $credentials['path']
    );

    $client = new Client($server);
    $collection = $client->main->starwars;

    $result = $collection->insertOne([
        'name' => 'Rey',
        'occupation' => 'Jedi',
    ]);

    $id = $result->getInsertedId();

    $document = $collection->findOne([
        '_id' => $id,
    ]);

    // Clean up after ourselves.
    $collection->drop();

    printf("Found %s (%s)<br />\n", $document->name, $document->occupation);

} catch (\Exception $e) {
    print $e->getMessage();
}

```
```php {}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// The 'database' relationship is generally the name of primary SQL database of an application.
// That's not required, but much of our default automation code assumes it.
$credentials = $config->credentials('database');

try {
    // Connect to the database using PDO.  If using some other abstraction layer you would
    // inject the values from $database into whatever your abstraction layer asks for.
    $dsn = sprintf('mysql:host=%s;port=%d;dbname=%s', $credentials['host'], $credentials['port'], $credentials['path']);
    $conn = new \PDO($dsn, $credentials['username'], $credentials['password'], [
        // Always use Exception error mode with PDO, as it's more reliable.
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
        // So we don't have to mess around with cursors and unbuffered queries by default.
        \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
        // Make sure MySQL returns all matched rows on update queries including
        // rows that actually didn't have to be updated because the values didn't
        // change. This matches common behavior among other database systems.
        \PDO::MYSQL_ATTR_FOUND_ROWS => TRUE,
    ]);

    // Creating a table.
    $sql = "CREATE TABLE People (
      id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
      name VARCHAR(30) NOT NULL,
      city VARCHAR(30) NOT NULL
      )";
    $conn->query($sql);

    // Insert data.
    $sql = "INSERT INTO People (name, city) VALUES
        ('Neil Armstrong', 'Moon'),
        ('Buzz Aldrin', 'Glen Ridge'),
        ('Sally Ride', 'La Jolla');";
    $conn->query($sql);

    // Show table.
    $sql = "SELECT * FROM People";
    $result = $conn->query($sql);
    $result->setFetchMode(\PDO::FETCH_OBJ);

    if ($result) {
        print <<<TABLE
<table>
<thead>
<tr><th>Name</th><th>City</th></tr>
</thead>
<tbody>
TABLE;
        foreach ($result as $record) {
            printf("<tr><td>%s</td><td>%s</td></tr>\n", $record->name, $record->city);
        }
        print "</tbody>\n</table>\n";
    }

    // Drop table
    $sql = "DROP TABLE People";
    $conn->query($sql);

} catch (\Exception $e) {
    print $e->getMessage();
}

```
```php {}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// The 'database' relationship is generally the name of primary SQL database of an application.
// It could be anything, though, as in the case here here where it's called "postgresql".
$credentials = $config->credentials('postgresql');

try {
    // Connect to the database using PDO.  If using some other abstraction layer you would
    // inject the values from $database into whatever your abstraction layer asks for.
    $dsn = sprintf('pgsql:host=%s;port=%d;dbname=%s', $credentials['host'], $credentials['port'], $credentials['path']);
    $conn = new \PDO($dsn, $credentials['username'], $credentials['password'], [
        // Always use Exception error mode with PDO, as it's more reliable.
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
    ]);

    $conn->query("DROP TABLE IF EXISTS People");

    // Creating a table.
    $sql = "CREATE TABLE IF NOT EXISTS People (
      id SERIAL PRIMARY KEY,
      name VARCHAR(30) NOT NULL,
      city VARCHAR(30) NOT NULL
      )";
    $conn->query($sql);

    // Insert data.
    $sql = "INSERT INTO People (name, city) VALUES
        ('Neil Armstrong', 'Moon'),
        ('Buzz Aldrin', 'Glen Ridge'),
        ('Sally Ride', 'La Jolla');";
    $conn->query($sql);

    // Show table.
    $sql = "SELECT * FROM People";
    $result = $conn->query($sql);
    $result->setFetchMode(\PDO::FETCH_OBJ);

    if ($result) {
        print <<<TABLE
<table>
<thead>
<tr><th>Name</th><th>City</th></tr>
</thead>
<tbody>
TABLE;
        foreach ($result as $record) {
            printf("<tr><td>%s</td><td>%s</td></tr>\n", $record->name, $record->city);
        }
        print "</tbody>\n</table>\n";
    }

    // Drop table.
    $sql = "DROP TABLE People";
    $conn->query($sql);

} catch (\Exception $e) {
    print $e->getMessage();
}

```
```php {}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the RabbitMQ service.
$credentials = $config->credentials('rabbitmq');

try {

    $queueName = 'deploy_days';

    // Connect to the RabbitMQ server.
    $connection = new AMQPStreamConnection($credentials['host'], $credentials['port'], $credentials['username'], $credentials['password']);
    $channel = $connection->channel();

    $channel->queue_declare($queueName, false, false, false, false);

    $msg = new AMQPMessage('Friday');
    $channel->basic_publish($msg, '', 'hello');

    echo "[x] Sent 'Friday'<br/>\n";

    // In a real application you't put the following in a separate script in a loop.
    $callback = function ($msg) {
        printf("[x] Deploying on %s<br />\n", $msg->body);
    };

    $channel->basic_consume($queueName, '', false, true, false, false, $callback);

    // This blocks on waiting for an item from the queue, so comment it out in this demo script.
    //$channel->wait();

    $channel->close();
    $connection->close();

} catch (Exception $e) {
    print $e->getMessage();
}

```
```php {}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Redis service.
$credentials = $config->credentials('redis');

try {
    // Connecting to Redis server.
    $redis = new Redis();
    $redis->connect($credentials['host'], $credentials['port']);

    $key = "Deploy day";
    $value = "Friday";

    // Set a value.
    $redis->set($key, $value);

    // Read it back.
    $test = $redis->get($key);

    printf('Found value <strong>%s</strong> for key <strong>%s</strong>.', $test, $key);

} catch (Exception $e) {
    print $e->getMessage();
}

```
```php {}
<?php
declare(strict_types=1);

use Platformsh\ConfigReader\Config;
use Solarium\Client;

// Create a new config object to ease reading the Upsun Fixed environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Solr service.
$credentials = $config->credentials('solr');

try {

    $config = [
        'endpoint' => [
            'localhost' => [
                'host' => $credentials['host'],
                'port' => $credentials['port'],
                'path' => "/" . $credentials['path'],
            ]
        ]
    ];

    $client = new Client($config);

    // Add a document
    $update = $client->createUpdate();

    $doc1 = $update->createDocument();
    $doc1->id = 123;
    $doc1->name = 'Valentina Tereshkova';

    $update->addDocuments(array($doc1));
    $update->addCommit();

    $result = $client->update($update);
    print "Adding one document. Status (0 is success): " .$result->getStatus(). "<br />\n";

    // Select one document
    $query = $client->createQuery($client::QUERY_SELECT);
    $resultset = $client->execute($query);
    print  "Selecting documents (1 expected): " .$resultset->getNumFound() . "<br />\n";

    // Delete one document
    $update = $client->createUpdate();

    $update->addDeleteById(123);
    $update->addCommit();
    $result = $client->update($update);
    print "Deleting one document. Status (0 is success): " .$result->getStatus(). "<br />\n";

} catch (Exception $e) {
    print $e->getMessage();
}

```

### Configuration reader

While you can read the environment directly from your app,
you might want to use the[PHP configuration reader library](https://github.com/platformsh/config-reader-php).
It decodes service credentials, the correct port, and other information for you.

## PHP settings

You can configure your PHP-FPM runtime configuration by specifying the [runtime in your app configuration](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#runtime).

In addition to changes in runtime, you can also change the PHP settings.
Some commonly used settings are:

| Name | Default | Description                                                                                                                                                                                          |
|------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `max_execution_time` | `300` | The maximum execution time, in seconds, for your PHP scripts and apps. A value of `0` means there are no time limits.                                                                                |
| `max_file_uploads` | `20` | The maximum number of files that can be uploaded in each request.                                                                                                                                    |
| `max_input_time` | `60` | The maximum time in seconds that your script is allowed to receive input (such as for file uploads). A value of `-1` means there are no time limits.                                                 |
| `max_input_vars` | `1000` | The maximum number of input variables that are accepted in each request.                                                                                                                             |
| `memory_limit` | `128M` | The memory limit, in megabytes, for PHP. Ensure that the PHP memory limit is set to a lower value than your environment's memory.                                                                    |
| `post_max_size` | `64M` | The maximum size, in megabytes, per uploaded file. To upload larger files, increase the value.                                                                                                       |
| `zend.assertions` | `-1` | Assertions are optimized and have no impact at runtime. Set assertions to `1` for your local development system. [See more on assertions](https://www.php.net/manual/en/regexp.reference.assertions). |
| `opcache.memory_consumption` | `64` | The number of megabytes available for [the OPcache](https://fixed.docs.upsun.com/languages/php/tuning.md#opcache-preloading). For large apps with many files, increase this value.                                               |
| `opcache.validate_timestamps` | `On` | If your app doesn't generate compiled PHP, you can [disable this setting](https://fixed.docs.upsun.com/languages/php/tuning.md#disable-opcache-timestamp-validation).                                                                          |

### Retrieve the default values

To retrieve the default PHP values, run the following [CLI command](https://fixed.docs.upsun.com/administration/cli/_index.md):

```bash
platform ssh "php --info"
```

To get specific default values, use grep.
For example, to get the value for `opcache.memory_consumption`, run the following command:

```bash
platform ssh "php --info" | grep opcache.memory_consumption
```

### Retrieve the settings

To see the settings used on your environment:

1.  Find the PHP configuration files with the following [CLI command](https://fixed.docs.upsun.com/administration/cli/_index.md):

    ```bash
    platform ssh "php --ini"
    ```

    The output is something like the following:

    ```bash
    Configuration File (php.ini) Path: /etc/php/8.0-zts/cli
    Loaded Configuration File:         /etc/php/8.0-zts/cli/php.ini
    Scan for additional .ini files in: /etc/php/8.0-zts/cli/conf.d
    Additional .ini files parsed:      (none)
    ```

2.  Display the configuration file by adapting the following command with the output from step 1:

    ```bash
    platform ssh "cat <LOADED_CONFIGURATION_FILE_PATH>"
    ```

### Customize PHP settings

For Dedicated Gen 2, see the [configuration options](https://fixed.docs.upsun.com/dedicated-environments/dedicated-gen-2/development.md).

You can customize PHP values for your app in two ways.
The recommended method is to use variables.

For more information, see how to use [PHP-specific variables](https://fixed.docs.upsun.com/development/variables.md#php-specific-variables).
You can provide a custom ``php.ini`` file at the [app root](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory).
Using this method isn’t recommended since it offers less flexibility and is more error-prone.
Consider using variables instead.
For example, to change the PHP memory limit, use the following configuration:

    php.ini

```ini {}
memory_limit = 256M
```

If you're using [PHP-CLI](#execution-mode),
you need to take into account the default settings of PHP-CLI when you customize your PHP settings.
The default settings of PHP-CLI can't be overwritten and are the following:

```text
max_execution_time=0
max_input_time=-1
memory_limit=-1
```

### Disable functions for security

A common recommendation for securing PHP installations is disabling built-in functions frequently used in remote attacks.
By default, Upsun Fixed doesn't disable any functions.

If you're sure a function isn't needed in your app, you can disable it.

For example, to disable `pcntl_exec` and `pcntl_fork`, add the following to your [app configuration](https://fixed.docs.upsun.com/create-apps/_index.md):

```yaml  {location=".platform.app.yaml"}
variables:
    php:
        disable_functions: "pcntl_exec,pcntl_fork"
```
Common functions to disable include:

| Name | Description |
|------|-------------|
| `create_function` | This function has been replaced by anonymous functions and shouldn't be used anymore. |
| `exec`, `passthru`, `shell_exec`, `system`, `proc_open`, `popen` | These functions allow a PHP script to run a bash shell command. Rarely used by web apps except for build scripts that might need them. |
| `pcntl_*` | The `pcntl_*` functions are responsible for process management. Most of them cause a fatal error if used within a web request. Cron tasks or workers may need them. Most are usually safe to disable. |
| `curl_exec`, `curl_multi_exec` | These functions allow a PHP script to make arbitrary HTTP requests. If you're using HTTP libraries such as Guzzle, don't disable them. |
| `show_source` | This function shows a syntax highlighted version of a named PHP source file. Rarely useful outside of development. |

## Execution mode

PHP has two execution modes you can choose from:

- The command line interface mode (PHP-CLI) is the mode used for command line scripts and standalone apps.
  This is the mode used when you're logged into your container via SSH, for [crons](https://fixed.docs.upsun.com/create-apps/image-properties/crons.md),
  and usually also for [alternate start commands](#alternate-start-commands).
  To use PHP-CLI, run your script with `php <PATH_TO_SCRIPT>`,
  where <PATH_TO_SCRIPT> is a file path relative to the [app root](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory).
- The Common Gateway Interface mode (PHP-CGI) is the mode used for web apps and web requests.
  This is the default mode when the `start` command isn't explicitly set.
  To use PHP-CGI, run your script with a symlink: `/usr/bin/start-php-app <PATH_TO_SCRIPT>`,
  where <PATH_TO_SCRIPT> is a file path relative to the [app root](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory).
  With PHP-CGI, PHP is run using the FastCGI Process Manager (PHP-FPM).

## Alternate start commands

To specify an alternative process to run your code, set a `start` command.
For more information about the start command, see the [web commands reference](https://fixed.docs.upsun.com/create-apps/image-properties/web.md#web-commands).

By default, start commands use PHP-CLI.
Find out how and when to use each [execution mode](#execution-mode).

Note that the `start` command must run in the foreground and is executed before the [deploy hook](https://fixed.docs.upsun.com/create-apps/hooks/hooks-comparison.md).
That means that PHP-FPM can't run simultaneously with another persistent process
such as [ReactPHP](https://github.com/platformsh-examples/platformsh-example-reactphp)
or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp).
If you need multiple processes, they have to run in separate containers.

See some generic examples on how to use alternate start commands:

```yaml {}
web:
    commands:
        start: /usr/bin/start-php-app
```

 - Add your web server’s code in a PHP file.

 - Specify an alternative ``start`` command by adapting the following:

    .platform.app.yaml

```yaml {}
web:
    commands:
        start: /usr/bin/start-php-app
```

 - Configure the container to listen on a TCP socket:

    .platform.app.yaml

```yaml {}
web:
    upstream:
        socket_family: tcp
        protocol: http
```

When you listen on a TCP socket, the ``$PORT`` environment variable is automatically set.
See more options on how to [configure where requests are sent](https://fixed.docs.upsun.com/create-apps/image-properties/web.md#upstream).
You might have to configure your app to connect via the ``$PORT`` TCP socket,
especially when using web servers such as [Swoole](https://fixed.docs.upsun.com/languages/php/swoole.md) or [Roadrunner](https://github.com/roadrunner-server/roadrunner).

 - Optional: Override redirects to let the custom web server handle them:

    .platform.app.yaml

```yaml {}
locations:
    "/":
        passthru: true
        scripts: false
        allow: false
```

To execute runtime-specific tasks (such as clearing cache) before your app starts, follow these steps:

 - Create a separate shell script that includes all the commands to be run.

 - Specify an alternative ``start`` command by adapting the following:

    .platform.app.yaml

```yaml {}
web:
    commands:
        start: bash <PATH_TO_SCRIPT> && /usr/bin/start-php-app
```

<PATH_TO_SCRIPT> is the bash script created in step 1.
<PATH_TO_SCRIPT> is a file path relative to the [app root](https://fixed.docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory).

## Foreign function interfaces

PHP 7.4 introduced support for [foreign function interfaces (FFIs)](https://en.wikipedia.org/wiki/Foreign_function_interface).
FFIs allow your PHP program to call routines or use services written in C or Rust.

Note: FFIs are only intended for advanced use cases.
Use with caution.

If you are using C code, you need `.so` library files.
Either place these files directly in your repository or compile them in a makefile using `gcc` in your [build hook](https://fixed.docs.upsun.com/create-apps/hooks/hooks-comparison.md#build-hook).
Note: The `.so` library files shouldn't be located in a publicly accessible directory.

If you are compiling Rust code, use the build hook to [install Rust](https://doc.rust-lang.org/stable/book/ch01-01-installation.md).

To leverage FFIs, follow these steps:

1.  [Enable and configure OPcache preloading](https://fixed.docs.upsun.com/languages/php/tuning.md#enable-opcache-preloading).

2.  Enable the FFI extension:

```yaml  {location=".platform.app.yaml"}
runtime:
    extensions:
        - ffi
```

3.  Make sure that your [preload script](https://fixed.docs.upsun.com/languages/php/tuning.md#opcache-preloading) calls the `FFI::load()` function.
    Using this function in preload is considerably faster than loading the linked library on each request or script run.

4.  If you are running FFIs from the command line,
    enable the preloader by adding the following configuration:

```yaml  {location=".platform.app.yaml"}
variables:
    php:
        opcache.enable_cli: true
```

5.  Run your script with the following command:

    ```bash
    php <CLI_SCRIPT>
    ```

See [complete working examples for C and Rust](https://github.com/platformsh-examples/php-ffi).

## Project templates

  The following list shows templates available for PHP apps.

A template is a starting point for building your project.
It should help you get a project ready for production.

  Drupal 9

    ![Drupal 9](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='186.52541' height='243.71308' viewBox='0 0 186.52541 243.71308'%3E%3Ctitle%3ERisorsa 85%3C/title%3E%3Cg id='Livello_2' data-name='Livello 2'%3E%3Cg id='Livello_1-2' data-name='Livello 1'%3E%3Cpath d='M131.64024,51.90954C114.49124,34.76866,98.12945,18.42858,93.26,0,88.39024,18.42858,72.02583,34.76866,54.8797,51.90954,29.16037,77.61263,0,106.7432,0,150.434a93.26271,93.26271,0,1,0,186.52541,0c0-43.688-29.158-72.8214-54.88517-98.52449M39.63956,172.16578c-5.71847-.19418-26.82308-36.57089,12.32937-75.303l25.90873,28.30088a2.21467,2.21467,0,0,1-.173,3.30485c-6.18245,6.34085-32.53369,32.7658-35.809,41.90292-.676,1.886-1.66339,1.81463-2.25619,1.79436M93.26283,220.1092a32.07521,32.07521,0,0,1-32.07544-32.07543A33.42322,33.42322,0,0,1,69.1821,166.8471c5.7836-7.07224,24.07643-26.96358,24.07643-26.96358s18.01279,20.18332,24.03326,26.89607a31.36794,31.36794,0,0,1,8.04647,21.25418A32.07551,32.07551,0,0,1,93.26283,220.1092m61.3923-52.015c-.69131,1.51192-2.25954,4.036-4.37617,4.113-3.77288.13741-4.176-1.79579-6.96465-5.92291-6.12235-9.06007-59.55167-64.89991-69.54517-75.69925-8.79026-9.49851-1.23783-16.195,2.26549-19.70431C80.42989,66.47768,93.25949,53.656,93.25949,53.656s38.25479,36.29607,54.19029,61.09626,10.44364,46.26024,7.20535,53.342' style='fill:%23009cde'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
    Drupal 9
    This template builds Drupal 9 using the "Drupal Recommended" Composer project.  It is pre-configured to use MariaDB and Redis for caching.  The Drupal installer will skip asking for database credentials as they are already provided.
Drupal is a flexible and extensible PHP-based CMS framework.

### Features:

 - PHP 8.0

 - MariaDB 10.4

 - Redis 6

 - Drush included

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/drupal9).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  GovCMS 9

    ![GovCMS 9](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='199.37' height='225'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:%232ba9e0%7D%3C/style%3E%3C/defs%3E%3Cg %3E%3Cg %3E%3Cpath class='cls-1' d='M93.78 139.31a35.5 35.5 0 1 0 35.5 35.5 35.51 35.51 0 0 0-35.5-35.5zM138 132.51a61.17 61.17 0 0 1-9.26 92.49c29.31-9 53.56-31.06 64.4-57.73 15-36.92 1-64.67-22.43-89.87a45.68 45.68 0 0 1 1.15 10.11 46.88 46.88 0 0 1-33.86 45zM97.82 87.57A27.19 27.19 0 1 0 125 60.43a27.16 27.16 0 0 0-27.18 27.14z'/%3E%3Cpath class='cls-1' d='M47 214.22a61.17 61.17 0 0 1 39.55-100.1 46.82 46.82 0 0 1 44.75-72.89C116 28 100.72 14.62 88.66 0c6.13 64.13-58.4 40.82-82.32 100C-9.62 139.58 4.79 188.56 47 214.22z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
    GovCMS 9
    This template builds the Australian government's GovCMS Drupal 9 distribution using the Drupal Composer project for better flexibility.  It is pre-configured to use MariaDB and Redis for caching.  The Drupal installer will skip asking for database credentials as they are already provided.
GovCMS is a Drupal distribution built for the Australian government, and includes configuration optimized for managing government websites.

### Features:

 - PHP 8.0

 - MariaDB 10.4

 - Redis 6

 - Drush included

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/drupal9-govcms9).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  Laravel

    ![Laravel](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIzLjc3NjIgMTEuNDc2M0MyMy42MDk1IDExLjMwOTYgMjEuNDcwNyA4LjYxNTIgMjEuMTA5NSA4LjE3MDc1QzIwLjcyMDcgNy43MjYzMSAyMC41NTQgNy44MDk2NCAyMC4zMDQgNy44Mzc0MkMyMC4wNTQgNy44NjUyIDE3LjM1OTUgOC4zMzc0MiAxNy4wNTQgOC4zNjUyQzE2Ljc0ODQgOC40MjA3NSAxNi41NTQgOC41MzE4NiAxNi43NDg0IDguODA5NjRDMTYuOTE1MSA5LjA1OTY0IDE4LjY5MjkgMTEuNTU5NiAxOS4wODE4IDEyLjE0M0wxMS45OTg0IDEzLjgzNzRMNi4zODczMyA0LjQyMDc1QzYuMTY1MSA0LjA4NzQyIDYuMTA5NTUgMy45NzYzMSA1LjYwOTU1IDQuMDA0MDlDNS4xMDk1NSA0LjAzMTg2IDEuMTkyODggNC4zNjUyIDAuOTE1MTA2IDQuMzY1MkMwLjYzNzMyOCA0LjM5Mjk4IDAuMzMxNzcyIDQuNTA0MDkgMC42MDk1NSA1LjE3MDc1QzAuODg3MzI4IDUuODM3NDIgNS4zMzE3NyAxNS4zOTMgNS40NDI4OCAxNS42NzA4QzUuNTUzOTkgMTUuOTQ4NSA1Ljg4NzMzIDE2LjM5MyA2LjYzNzMzIDE2LjIyNjNDNy40MTUxIDE2LjAzMTkgMTAuMDgxOCAxNS4zMzc0IDExLjU1NCAxNC45NDg1QzEyLjMzMTggMTYuMzM3NCAxMy44ODczIDE5LjE3MDggMTQuMTkyOSAxOS41ODc0QzE0LjU4MTggMjAuMTQzIDE0Ljg1OTUgMjAuMDMxOSAxNS40NDI5IDE5Ljg2NTJDMTUuOTE1MSAxOS43MjYzIDIyLjcyMDcgMTcuMjgxOSAyMy4wMjYyIDE3LjE0M0MyMy4zMzE4IDE3LjAwNDEgMjMuNTI2MiAxNi45MjA4IDIzLjMwNCAxNi42MTUyQzIzLjEzNzMgMTYuMzkzIDIxLjM1OTUgMTMuOTc2MyAyMC40MTUxIDEyLjcyNjNDMjEuMDU0IDEyLjU1OTYgMjMuMzU5NSAxMS45NDg1IDIzLjYwOTUgMTEuODY1MkMyMy44ODczIDExLjc4MTkgMjMuOTQyOSAxMS42NDMgMjMuNzc2MiAxMS40NzYzWk0xMC45MTUxIDE0LjExNTJDMTAuODMxOCAxNC4xNDMgNi44NTk1NSAxNS4wODc0IDYuNjY1MSAxNS4xNDNDNi40NDI4OCAxNS4xOTg1IDYuNDQyODggMTUuMTcwOCA2LjQ0Mjg4IDE1LjA4NzRDNi4zODczMyAxNS4wMDQxIDEuNzIwNjYgNS4zMzc0MiAxLjYzNzMzIDUuMjI2MzFDMS41ODE3NyA1LjExNTIgMS41ODE3NyA1LjAwNDA5IDEuNjM3MzMgNS4wMDQwOUMxLjY5Mjg4IDUuMDA0MDkgNS4zODczMyA0LjY3MDc1IDUuNDk4NDQgNC42NzA3NUM1LjYzNzMzIDQuNjcwNzUgNS42MDk1NSA0LjY5ODUzIDUuNjY1MSA0Ljc4MTg2QzUuNjY1MSA0Ljc4MTg2IDEwLjg1OTUgMTMuNzU0MSAxMC45NDI5IDEzLjg5M0MxMS4wNTQgMTQuMDMxOSAxMC45OTg0IDE0LjA4NzQgMTAuOTE1MSAxNC4xMTUyWk0yMi4wODE4IDE2LjE5ODVDMjIuMTM3MyAxNi4zMDk2IDIyLjIyMDcgMTYuMzY1MiAyMS45OTg0IDE2LjQyMDhDMjEuODA0IDE2LjUwNDEgMTUuMzA0IDE4LjY5ODUgMTUuMTY1MSAxOC43NTQxQzE1LjAyNjIgMTguODA5NiAxNC45NDI5IDE4LjgzNzQgMTQuNzc2MiAxOC41ODc0QzE0LjYwOTUgMTguMzM3NCAxMi40OTg0IDE0LjY5ODUgMTIuNDk4NCAxNC42OTg1TDE5LjQxNTEgMTIuODkzQzE5LjU4MTggMTIuODM3NCAxOS42MzczIDEyLjgwOTYgMTkuNzQ4NCAxMi45NzYzQzE5Ljg1OTUgMTMuMTcwOCAyMi4wMjYyIDE2LjExNTIgMjIuMDgxOCAxNi4xOTg1Wk0yMi41MjYyIDExLjMwOTZDMjIuMzU5NSAxMS4zMzc0IDE5LjgzMTggMTEuOTc2MyAxOS44MzE4IDExLjk3NjNMMTcuNzQ4NCA5LjE0Mjk3QzE3LjY5MjkgOS4wNTk2NCAxNy42MzczIDguOTc2MzEgMTcuNzc2MiA4Ljk0ODUzQzE3LjkxNTEgOC45MjA3NSAyMC4yNzYyIDguNTA0MDkgMjAuMzg3MyA4LjQ3NjMxQzIwLjQ5ODQgOC40NDg1MyAyMC41ODE4IDguNDIwNzUgMjAuNzIwNyA4LjYxNTJDMjAuODU5NSA4Ljc4MTg2IDIyLjYzNzMgMTEuMDU5NiAyMi43MjA3IDExLjE0M0MyMi44MDQgMTEuMjI2MyAyMi42OTI5IDExLjI4MTkgMjIuNTI2MiAxMS4zMDk2WiIgZmlsbD0iI0ZCNTAzQiIvPgo8L3N2Zz4K)
    Laravel
    This template provides a basic Laravel skeleton.  It comes pre-configured to use a MariaDB database and Redis for caching and sessions using a Laravel-specific bridge library that runs during Composer autoload.  The public files symlink is also replaced with a custom web path definition so it is unnecessary.  It is intended for you to use as a starting point and modify for your own needs.
Laravel is an opinionated, integrated rapid-application-development framework for PHP.

### Features:

 - PHP 8.0

 - MariaDB 10.4

 - Redis 5.0

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/laravel).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  Magento 2 Community Edition

    ![Magento 2 Community Edition](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjc5OTk5IDYuMDA0NTZMMTIuMjAyNSAwTDIyLjU4NDEgNS45OTQxVjE3Ljk5OEwxOS42MTQ1IDE5LjcwOTVWNy43MTg3TDEyLjE4MTUgMy40MjgyTDQuNzQ4NTUgNy43MTg3TDQuNzY5NTIgMTkuNzE0N0wxLjc5OTk5IDE3Ljk5OFY2LjAwNDU2Wk0xMi4xOTIgMjAuNTc0NEwxMy42NzU1IDE5LjcxMjFWNy43MTg2N0wxNi42NDUgOS40MzI3NVYyMS40Mjg5TDEyLjE4OTQgMjRMNy43MzkwMiAyMS40Mjg5TDcuNzMzNzggOS40MzI3NUwxMC43MDA3IDcuNzE4NjdWMTkuNzJMMTIuMTkyIDIwLjU3NDRaIiBmaWxsPSIjRjI2MzIyIi8+Cjwvc3ZnPgo=)
    Magento 2 Community Edition
    This template builds Magento 2 CE on Upsun Fixed.  It includes additional scripts to customize Magento to run effectively in a build-and-deploy environment.  A MariaDB database and Redis cache server come pre-configured and work out of the box.  The installer has been modified to not ask for database information.  Background workers are run using a worker container rather than via cron.
Magento is a fully integrated ecommerce system and web store written in PHP.  This is the Open Source version.

### Features:

 - PHP 7.2

 - MariaDB 10.2

 - Redis 3.2

 - Dedicated worker instance for background processing

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/magento2ce).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  Sylius

    ![Sylius](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDQ4IDQ4Ij4KPHBhdGggZmlsbD0iIzMwYmE5ZCIgZD0iTTEwLjIsMjguMWw5LjYsMTkuMmwxNy43LDBsNC4zLTZMMTAuMiwyOC4xTDEwLjIsMjguMXoiLz4KPHBhdGggZmlsbD0iIzFhOWY4MyIgZD0iTTMuNSwzMC4yTDE2LjQsNDhsMjEuMSwwbDQuMy02LjZMMy41LDMwLjJ6IE0xOSw4LjdsNi4zLDQuOUwzMSwyLjZMMjksMS40QzI5LDEuNCwxOSw4LjcsMTksOC43eiIvPgo8cGF0aCBmaWxsPSIjMzBiYTlkIiBkPSJNMzcuNSw0OEwxOSw4LjdsNC0yLjlsMjEuNSwzMS40TDM3LjUsNDh6IE0yNy4yLDIuN2wxMi4xLDkuN0wzMC44LDBDMzAuOCwwLDI3LjIsMi43LDI3LjIsMi43eiIvPgo8L3N2Zz4K)
    Sylius
    This template builds a Sylius application for Upsun Fixed, which can be used as a starting point for developing complex e-commerce applications.
Sylius is a modern e-commerce solution for PHP, based on Symfony Framework.

### Features:

 - PHP 8.0

 - MySQL 10.2

 - Automatic TLS certificates

 - composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/sylius).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  WooCommerce (Bedrock) for Upsun Fixed

    ![WooCommerce (Bedrock) for Upsun Fixed](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='225' height='225'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:%23525ddc%7D%3C/style%3E%3C/defs%3E%3Cg %3E%3Cg %3E%3Cpath class='cls-1' d='M112.52 74.93V42.67a4.68 4.68 0 0 0-5.48-4.4Q56.94 46.63 6.82 55c-2.25.38-4.33.8-5.69-1.51A6.75 6.75 0 0 1 .05 50.4C0 35.56 0 20.72 0 5.89A6 6 0 0 1 5.92 0h212.81A6 6 0 0 1 225 6.29v43.27a8.1 8.1 0 0 1-6.63 7.7C207.2 59.15 196 61 184.87 62.85l-71.93 12a2.77 2.77 0 0 1-.5 0zM112.47 150.06v31.76a4.68 4.68 0 0 0 5.74 4.86l101.47-17a4.6 4.6 0 0 1 5.33 4.39v45.76c0 2.14-3 5.07-5.14 5.14H6.52c-4 0-6.52-2.47-6.52-6.53V175.7a8.22 8.22 0 0 1 6.88-8q16.62-2.79 33.25-5.54l71.93-12a2.77 2.77 0 0 1 .5 0z'/%3E%3Cpath class='cls-1' d='M112.56 150.15v-37.63l-.08.08 107.04-17.92a4.62 4.62 0 0 1 5.48 4.73v25a8.1 8.1 0 0 1-6.69 7.9c-9.35 1.58-18.71 3.1-28.07 4.66q-35.33 5.88-70.65 11.79c-2.38.4-4.75.87-7.12 1.3zM112.44 74.84v37.76l.08-.08c-9.61 1.56-19.23 3.1-28.83 4.7Q48.58 123.06 13.48 129c-2.47.41-4.94.77-7.4 1.22-3.75.67-6.07-1.2-6.07-5v-25a8.25 8.25 0 0 1 6.37-7.42c10.41-1.8 20.85-3.53 31.28-5.27q35.34-5.88 70.7-11.79c1.4-.23 2.78-.54 4.17-.81z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
    WooCommerce (Bedrock) for Upsun Fixed
    This template builds WordPress on Upsun Fixed using the Bedrock boilerplate by Roots with Composer. It includes WooCommerce and JetPack as dependencies, which when enabled will quickly allow you to create a store on WordPress.
Plugins and themes should be managed with Composer exclusively. The only modifications made to the standard Bedrock boilerplate have been providing database credentials and main site url parameters via environment variables. With this configuration, the database is automatically configured such that the installer will not ask you for database credentials. While Bedrock provides support to replicate this configuration in a ``.env`` file for local development, an example Lando configuration file is included as the recommendated method to do so.
WordPress is a blogging and lightweight CMS written in PHP, and Bedrock is a Composer-based WordPress boilerplate project with a slightly modified project structure and configuration protocol. WooCommerce is an open-source eCommerce platform and plugin for WordPress.

### Features:

 - PHP 7.4

 - MariaDB 10.4

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/wordpress-woocommerce).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  WordPress (Bedrock)

    ![WordPress (Bedrock)](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='225' height='225'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:%23525ddc%7D%3C/style%3E%3C/defs%3E%3Cg %3E%3Cg %3E%3Cpath class='cls-1' d='M112.52 74.93V42.67a4.68 4.68 0 0 0-5.48-4.4Q56.94 46.63 6.82 55c-2.25.38-4.33.8-5.69-1.51A6.75 6.75 0 0 1 .05 50.4C0 35.56 0 20.72 0 5.89A6 6 0 0 1 5.92 0h212.81A6 6 0 0 1 225 6.29v43.27a8.1 8.1 0 0 1-6.63 7.7C207.2 59.15 196 61 184.87 62.85l-71.93 12a2.77 2.77 0 0 1-.5 0zM112.47 150.06v31.76a4.68 4.68 0 0 0 5.74 4.86l101.47-17a4.6 4.6 0 0 1 5.33 4.39v45.76c0 2.14-3 5.07-5.14 5.14H6.52c-4 0-6.52-2.47-6.52-6.53V175.7a8.22 8.22 0 0 1 6.88-8q16.62-2.79 33.25-5.54l71.93-12a2.77 2.77 0 0 1 .5 0z'/%3E%3Cpath class='cls-1' d='M112.56 150.15v-37.63l-.08.08 107.04-17.92a4.62 4.62 0 0 1 5.48 4.73v25a8.1 8.1 0 0 1-6.69 7.9c-9.35 1.58-18.71 3.1-28.07 4.66q-35.33 5.88-70.65 11.79c-2.38.4-4.75.87-7.12 1.3zM112.44 74.84v37.76l.08-.08c-9.61 1.56-19.23 3.1-28.83 4.7Q48.58 123.06 13.48 129c-2.47.41-4.94.77-7.4 1.22-3.75.67-6.07-1.2-6.07-5v-25a8.25 8.25 0 0 1 6.37-7.42c10.41-1.8 20.85-3.53 31.28-5.27q35.34-5.88 70.7-11.79c1.4-.23 2.78-.54 4.17-.81z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
    WordPress (Bedrock)
    This template builds WordPress on Upsun Fixed using the Bedrock boilerplate by Roots with Composer. Plugins and themes should be managed with Composer exclusively. The only modifications made to the standard Bedrock boilerplate have been providing database credentials and main site url parameters via environment variables. With this configuration, the database is automatically configured such that the installer will not ask you for database credentials. While Bedrock provides support to replicate this configuration in a `.env` file for local development, an example Lando configuration file is included as the recommendated method to do so.
WordPress is a blogging and lightweight CMS written in PHP, and Bedrock is a Composer-based WordPress boilerplate project with a slightly modified project structure and configuration protocol. 

### Features:

 - PHP 7.4

 - MariaDB 10.4

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/wordpress-bedrock).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  WordPress (Composer)

    ![WordPress (Composer)](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzY1MTZfMTQwMzcpIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi4wMjU5IDAuOTk5NDQ0QzE0Ljg2NTIgMC45OTk0NDQgMTcuNTEwOSAyLjA5NjQ1IDE5LjQ0NjggMy45MDMyOUMxOC40Nzg5IDMuOTAzMjkgMTcuNTEwOSA0LjQxOTUzIDE3LjUxMDkgNS43NzQ2NkMxNy40NDY0IDguNDIwMzkgMjAuNjcyOSA5LjAwMTE3IDE4LjkzMDYgMTQuMjkyNkwxNy41MTA5IDE4LjY4MDdMMTMuNTc0NiA3LjEyOTc5QzEzLjUxMDEgNi45MzYyIDEzLjU3NDYgNi44NzE2NyAxMy44MzI3IDYuODcxNjdIMTQuOTI5N0MxNC45OTQzIDYuODcxNjcgMTUuMDU4OCA2LjgwNzE0IDE1LjA1ODggNi43NDI2MVY2LjA5NzMxQzE1LjA1ODggNi4wMzI3OCAxNC45OTQzIDUuOTY4MjUgMTQuOTI5NyA1Ljk2ODI1QzEyLjgwMDMgNi4wMzI3OCAxMC43MzUzIDYuMDMyNzggOC42NzAzNCA1Ljk2ODI1QzguNjA1ODEgNS45NjgyNSA4LjU0MTI4IDYuMDMyNzggOC41NDEyOCA2LjA5NzMxVjYuNzQyNjFDOC41NDEyOCA2LjgwNzE0IDguNjA1ODEgNi44NzE2NyA4LjY3MDM0IDYuODcxNjdIOS43NjczNEMxMC4wMjU1IDYuODcxNjcgMTAuMDkgNi45MzYyIDEwLjE1NDUgNy4xMjk3OUwxMS43Njc4IDExLjUxNzhMOS4zMTU2MyAxOC44MDk3TDUuMzE0NzggNy4wNjUyNkM1LjI1MDI1IDYuOTM2MiA1LjMxNDc4IDYuODA3MTQgNS40NDM4MyA2LjgwNzE0SDYuNzM0NDNDNi43OTg5NiA2LjgwNzE0IDYuODYzNDkgNi43NDI2MSA2Ljg2MzQ5IDYuNjc4MDhWNi4wMzI3OEM2Ljg2MzQ5IDUuOTY4MjUgNi43OTg5NiA1LjkwMzcyIDYuNzM0NDMgNS45MDM3MkM1LjM3OTMgNS45NjgyNSA0LjA4ODcxIDUuOTY4MjUgMi43OTgxMSA2LjAzMjc4QzQuNzM0MDEgMi45OTk4NyA4LjE1NDEgMC45OTk0NDQgMTIuMDI1OSAwLjk5OTQ0NFpNMjEuNjQwOSA2LjgwNzE0QzIyLjQ3OTggOC4zNTU4NiAyMi45MzE1IDEwLjE2MjcgMjIuOTMxNSAxMi4wMzQxQzIyLjkzMTUgMTYuMTY0IDIwLjYwODQgMTkuNzc3NyAxNy4yNTI4IDIxLjY0OUwyMC42NzI5IDExLjk2OTVDMjEuMTg5MiAxMC40MjA4IDIxLjcwNTQgOC40MjAzOSAyMS42NDA5IDYuODA3MTRaTTE1LjcwNDEgMjIuMzU4OUMxNC41NDI2IDIyLjc0NjEgMTMuMzE2NSAyMy4wMDQyIDEyLjAyNTkgMjMuMDA0MkMxMC45Mjg5IDIzLjAwNDIgOS44MzE4NyAyMi44MTA2IDguODYzOTIgMjIuNTUyNUwxMi4yMTk1IDEyLjg3M0wxNS43MDQxIDIyLjM1ODlaTTcuMzE1MjEgMjEuOTA3MkMzLjYzNyAyMC4xNjQ5IDEuMDU1OCAxNi4zNTc2IDEuMDU1OCAxMS45Njk1QzEuMDU1OCAxMC4zNTYzIDEuMzc4NDUgOC44MDc1NyAyLjAyMzc1IDcuMzg3OTFMNy4zMTUyMSAyMS45MDcyWk0xMi4wMjU5IDAuMDMxNDk0MUMxOC42NzI1IDAuMDMxNDk0MSAyNC4wMjg1IDUuMzg3NDggMjQuMDI4NSAxMi4wMzQxQzI0LjAyODUgMTguNjgwNyAxOC42NzI1IDI0LjAzNjcgMTIuMDI1OSAyNC4wMzY3QzUuMzc5MzEgMjQuMDM2NyAwLjAyMzMxNTQgMTguNjE2MSAwLjAyMzMxNTQgMTEuOTY5NUMwLjAyMzMxNTQgNS4zMjI5NSA1LjM3OTMxIDAuMDMxNDk0MSAxMi4wMjU5IDAuMDMxNDk0MVoiIGZpbGw9IiM0NjQzNDIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF82NTE2XzE0MDM3Ij4KPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=)
    WordPress (Composer)
    This template builds WordPress on Upsun Fixed using the [johnbloch/wordpress](https://github.com/johnpbloch/wordpress) "Composer Fork" of WordPress.  Plugins and themes should be managed with Composer exclusively.  A custom configuration file is provided that runs on Upsun Fixed to automatically configure the database, so the installer will not ask you for database credentials.  For local-only configuration you can use a `wp-config-local.php` file that gets excluded from Git.
WordPress is a blogging and lightweight CMS written in PHP.

### Features:

 - PHP 8.1

 - MariaDB 10.4

 - Automatic TLS certificates

 - Composer-based build

    View the [repository on GitHub](https://github.com/platformsh-templates/wordpress-composer).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

  WordPress (Vanilla) for Upsun Fixed

    ![WordPress (Vanilla) for Upsun Fixed](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzY1MTZfMTQwMzcpIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi4wMjU5IDAuOTk5NDQ0QzE0Ljg2NTIgMC45OTk0NDQgMTcuNTEwOSAyLjA5NjQ1IDE5LjQ0NjggMy45MDMyOUMxOC40Nzg5IDMuOTAzMjkgMTcuNTEwOSA0LjQxOTUzIDE3LjUxMDkgNS43NzQ2NkMxNy40NDY0IDguNDIwMzkgMjAuNjcyOSA5LjAwMTE3IDE4LjkzMDYgMTQuMjkyNkwxNy41MTA5IDE4LjY4MDdMMTMuNTc0NiA3LjEyOTc5QzEzLjUxMDEgNi45MzYyIDEzLjU3NDYgNi44NzE2NyAxMy44MzI3IDYuODcxNjdIMTQuOTI5N0MxNC45OTQzIDYuODcxNjcgMTUuMDU4OCA2LjgwNzE0IDE1LjA1ODggNi43NDI2MVY2LjA5NzMxQzE1LjA1ODggNi4wMzI3OCAxNC45OTQzIDUuOTY4MjUgMTQuOTI5NyA1Ljk2ODI1QzEyLjgwMDMgNi4wMzI3OCAxMC43MzUzIDYuMDMyNzggOC42NzAzNCA1Ljk2ODI1QzguNjA1ODEgNS45NjgyNSA4LjU0MTI4IDYuMDMyNzggOC41NDEyOCA2LjA5NzMxVjYuNzQyNjFDOC41NDEyOCA2LjgwNzE0IDguNjA1ODEgNi44NzE2NyA4LjY3MDM0IDYuODcxNjdIOS43NjczNEMxMC4wMjU1IDYuODcxNjcgMTAuMDkgNi45MzYyIDEwLjE1NDUgNy4xMjk3OUwxMS43Njc4IDExLjUxNzhMOS4zMTU2MyAxOC44MDk3TDUuMzE0NzggNy4wNjUyNkM1LjI1MDI1IDYuOTM2MiA1LjMxNDc4IDYuODA3MTQgNS40NDM4MyA2LjgwNzE0SDYuNzM0NDNDNi43OTg5NiA2LjgwNzE0IDYuODYzNDkgNi43NDI2MSA2Ljg2MzQ5IDYuNjc4MDhWNi4wMzI3OEM2Ljg2MzQ5IDUuOTY4MjUgNi43OTg5NiA1LjkwMzcyIDYuNzM0NDMgNS45MDM3MkM1LjM3OTMgNS45NjgyNSA0LjA4ODcxIDUuOTY4MjUgMi43OTgxMSA2LjAzMjc4QzQuNzM0MDEgMi45OTk4NyA4LjE1NDEgMC45OTk0NDQgMTIuMDI1OSAwLjk5OTQ0NFpNMjEuNjQwOSA2LjgwNzE0QzIyLjQ3OTggOC4zNTU4NiAyMi45MzE1IDEwLjE2MjcgMjIuOTMxNSAxMi4wMzQxQzIyLjkzMTUgMTYuMTY0IDIwLjYwODQgMTkuNzc3NyAxNy4yNTI4IDIxLjY0OUwyMC42NzI5IDExLjk2OTVDMjEuMTg5MiAxMC40MjA4IDIxLjcwNTQgOC40MjAzOSAyMS42NDA5IDYuODA3MTRaTTE1LjcwNDEgMjIuMzU4OUMxNC41NDI2IDIyLjc0NjEgMTMuMzE2NSAyMy4wMDQyIDEyLjAyNTkgMjMuMDA0MkMxMC45Mjg5IDIzLjAwNDIgOS44MzE4NyAyMi44MTA2IDguODYzOTIgMjIuNTUyNUwxMi4yMTk1IDEyLjg3M0wxNS43MDQxIDIyLjM1ODlaTTcuMzE1MjEgMjEuOTA3MkMzLjYzNyAyMC4xNjQ5IDEuMDU1OCAxNi4zNTc2IDEuMDU1OCAxMS45Njk1QzEuMDU1OCAxMC4zNTYzIDEuMzc4NDUgOC44MDc1NyAyLjAyMzc1IDcuMzg3OTFMNy4zMTUyMSAyMS45MDcyWk0xMi4wMjU5IDAuMDMxNDk0MUMxOC42NzI1IDAuMDMxNDk0MSAyNC4wMjg1IDUuMzg3NDggMjQuMDI4NSAxMi4wMzQxQzI0LjAyODUgMTguNjgwNyAxOC42NzI1IDI0LjAzNjcgMTIuMDI1OSAyNC4wMzY3QzUuMzc5MzEgMjQuMDM2NyAwLjAyMzMxNTQgMTguNjE2MSAwLjAyMzMxNTQgMTEuOTY5NUMwLjAyMzMxNTQgNS4zMjI5NSA1LjM3OTMxIDAuMDMxNDk0MSAxMi4wMjU5IDAuMDMxNDk0MVoiIGZpbGw9IiM0NjQzNDIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF82NTE2XzE0MDM3Ij4KPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=)
    WordPress (Vanilla) for Upsun Fixed
    This template builds WordPress on Upsun Fixed, installing WordPress to a subdirectory instead of to the project root. It does not use a package management tool like Composer, and updating core, themes, and plugins should be done with care. A custom configuration file is provided that runs on Upsun Fixed to automatically configure the database, so the installer will not ask you for database credentials.
WordPress is a blogging and lightweight CMS written in PHP.

### Features:

 - PHP 7.4

 - MariaDB 10.4

 - Automatic TLS certificates

    View the [repository on GitHub](https://github.com/platformsh-templates/wordpress-vanilla).

        ![Deploy on  ](https://platform.sh/images/deploy/lg-blue.svg)

## Modify your PHP runtime when using a composable image

**Note**: 

This section is only relevant when using the Upsun Fixed [composable image](https://fixed.docs.upsun.com/create-apps/app-reference/composable-image.md).

The following table presents the possible modifications you can make to your PHP primary runtime using the `stack` key and composable image.
Each modification should be listed below the stack chosen (i.e. `extensions` are enabled under `.applications.frontend.stack[0]["php@8.3"].extensions` for PHP 8.3).
See the example below for more details.

| Name                        | Type                                                                                                                             | Description                                                                                             |
|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `extensions`                | List of `string`s OR [extensions definitions](https://fixed.docs.upsun.com/create-apps/app-reference/composable-image.md#stack) | [PHP extensions](https://fixed.docs.upsun.com/languages/php/extensions.md) to enable.                                               |
| `disabled_extensions`       | List of `string`s                                                                                                                | [PHP extensions](https://fixed.docs.upsun.com/languages/php/extensions.md) to disable.                                              |
| `request_terminate_timeout` | `integer`                                                                                                                        | The timeout (in seconds) for serving a single request after which the PHP-FPM worker process is killed. |
| `sizing_hints`              | A [sizing hints definition](#sizing-hints)                                         | The assumptions for setting the number of workers in your PHP-FPM runtime.                              |
| `xdebug`                    | An Xdebug definition                                                                                                             | The setting to turn on [Xdebug](https://fixed.docs.upsun.com/languages/php/xdebug.md).                                              |

### PHP-FPM service sizing hints {#sizing-hints}

The following table shows the properties that can be set in `sizing_hints`:

| Name              | Type      | Default | Minimum | Description                                    |
|-------------------|-----------|---------|---------|------------------------------------------------|
| `request_memory`  | `integer` | 45      | 10      | The average memory consumed per request in MB. |
| `reserved_memory` | `integer` | 70      | 70      | The amount of memory reserved in MB.           |

See more about [PHP-FPM workers and sizing](https://fixed.docs.upsun.com/languages/php/fpm.md).

### Example PHP configuration {#example-php-configuration}

Here is an example configuration:

```yaml  {location=".platform.app.yaml"}
name: frontend

stack:
    - "php@8.3":
        extensions:
          - apcu # A PHP extension made available to the PHP runtime
          - sodium
          - xsl
          - pdo_sqlite

        xdebug:
          idekey: YOUR_KEY

        disabled_extensions:
          - gd

        request_terminate_timeout: 200

        sizing_hints:
          request_memory: 45
          reserved_memory: 70

    - "php83Extensions.apcu" # A PHP extension made available to all runtimes.
    - "python@3.12"
    - "python312Packages.yq"
```

**Note**: 

You can also set your [app’s runtime timezone](https://fixed.docs.upsun.com/create-apps/timezone.md).


