setup-php action has been tested with a wide range of PHP frameworks and packages. This page collects the official example workflows so you can copy a starting point that matches your stack.
All examples follow the same pattern:
- Check out your code with
actions/checkout - Set up PHP with
shivammathur/setup-php@v2 - Cache Composer dependencies with
actions/cache - Install dependencies and run your test suite
examples/ directory on GitHub.
Available examples
| Framework / Package | Runs on | Workflow file |
|---|---|---|
| Blackfire | macOS, Ubuntu, Windows | blackfire.yml |
| Blackfire Player | macOS, Ubuntu | blackfire-player.yml |
| CakePHP with MySQL and Redis | Ubuntu | cakephp-mysql.yml |
| CakePHP with PostgreSQL and Redis | Ubuntu | cakephp-postgres.yml |
| CakePHP without services | macOS, Ubuntu, Windows | cakephp.yml |
| CodeIgniter | macOS, Ubuntu, Windows | codeigniter.yml |
| Drupal 11 (Composer-managed) | Ubuntu | drupal.yml |
| Laminas MVC | macOS, Ubuntu, Windows | laminas-mvc.yml |
| Laravel with MySQL and Redis | Ubuntu | laravel-mysql.yml |
| Laravel with PostgreSQL and Redis | Ubuntu | laravel-postgres.yml |
| Laravel without services | macOS, Ubuntu, Windows | laravel.yml |
| Lumen with MySQL and Redis | Ubuntu | lumen-mysql.yml |
| Lumen with PostgreSQL and Redis | Ubuntu | lumen-postgres.yml |
| Lumen without services | macOS, Ubuntu, Windows | lumen.yml |
| Phalcon with MySQL | Ubuntu | phalcon-mysql.yml |
| Phalcon with PostgreSQL | Ubuntu | phalcon-postgres.yml |
| Slim Framework | macOS, Ubuntu, Windows | slim-framework.yml |
| Symfony with MySQL | Ubuntu | symfony-mysql.yml |
| Symfony with PostgreSQL | Ubuntu | symfony-postgres.yml |
| Symfony without services | macOS, Ubuntu, Windows | symfony.yml |
| WordPress plugin | Ubuntu | wordpress.yml |
| WordPress with Roots/Bedrock | Ubuntu | bedrock.yml |
| WordPress with Roots/Sage | Ubuntu | sage.yml |
| Yii3 with MySQL | Ubuntu | yii3-mysql.yml |
| Yii3 with PostgreSQL | Ubuntu | yii3-postgres.yml |
| Yii3 web application | Ubuntu, Windows | yii3.yml |
Workflow examples
The sections below show representative workflows you can use as a starting point. Each example includes Composer caching, which speeds up repeated runs by reusing previously downloaded packages.Laravel (cross-platform, no services)
Laravel (cross-platform, no services)
Tests a Laravel application on Ubuntu, Windows, and macOS across multiple PHP versions. Uses Xdebug for coverage.
# GitHub Action for Laravel
name: Testing Laravel
on: [push, pull_request]
jobs:
laravel:
name: Laravel (PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }})
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
php-versions: ['8.3', '8.4', '8.5']
steps:
- name: Checkout
uses: actions/checkout@v6
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, dom, fileinfo
coverage: xdebug
- name: Get composer cache directory
id: composer-cache
shell: bash
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Prepare the application
run: |
php -r "file_exists('.env') || copy('.env.example', '.env');"
php artisan key:generate
- name: Clear Config
run: php artisan config:clear
- name: Test with phpunit
run: vendor/bin/phpunit --coverage-text
Laravel with MySQL and Redis (Ubuntu)
Laravel with MySQL and Redis (Ubuntu)
Tests a Laravel application with MySQL and Redis service containers. The service ports are mapped dynamically and passed to the application via environment variables.
# GitHub Action for Laravel with MySQL and Redis
name: Testing Laravel with MySQL
on: [push, pull_request]
jobs:
laravel:
name: Laravel (PHP ${{ matrix.php-versions }})
runs-on: ubuntu-latest
env:
DB_CONNECTION: mysql
DB_HOST: 127.0.0.1
DB_DATABASE: laravel
DB_USERNAME: root
DB_PASSWORD: password
BROADCAST_CONNECTION: log
CACHE_STORE: redis
QUEUE_CONNECTION: redis
SESSION_DRIVER: redis
# Docs: https://docs.github.com/en/actions/using-containerized-services
services:
mysql:
image: mysql:latest
env:
MYSQL_ALLOW_EMPTY_PASSWORD: false
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: laravel
ports:
- 3306/tcp
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
redis:
image: redis
ports:
- 6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8.4', '8.5']
steps:
- name: Checkout
uses: actions/checkout@v6
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, dom, fileinfo, mysql
coverage: xdebug
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Prepare the application
run: |
php -r "file_exists('.env') || copy('.env.example', '.env');"
php artisan key:generate
- name: Clear Config
run: php artisan config:clear
- name: Run Migration
run: php artisan migrate -v
env:
DB_PORT: ${{ job.services.mysql.ports['3306'] }}
REDIS_PORT: ${{ job.services.redis.ports['6379'] }}
- name: Test with phpunit
run: vendor/bin/phpunit --coverage-text
env:
DB_PORT: ${{ job.services.mysql.ports['3306'] }}
REDIS_PORT: ${{ job.services.redis.ports['6379'] }}
Symfony (cross-platform, no services)
Symfony (cross-platform, no services)
Tests a Symfony application on all three operating systems. Installs the common Symfony extensions and runs PHPUnit with coverage.
# GitHub Action for Symfony
name: Testing Symfony
on: [push, pull_request]
jobs:
symfony:
name: Symfony (PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }})
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
php-versions: ['8.4', '8.5', '8.6']
steps:
- name: Checkout
uses: actions/checkout@v6
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, zip
coverage: xdebug
- name: Get composer cache directory
id: composer-cache
shell: bash
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Run tests
run: ./bin/phpunit --coverage-text
CakePHP (tests, coding standard, and static analysis)
CakePHP (tests, coding standard, and static analysis)
Demonstrates a multi-job workflow for CakePHP: one job for tests using PCOV coverage, a second for PHP CodeSniffer, and a third for PHPStan static analysis.
# GitHub Action for CakePHP
# Tested with https://github.com/cakephp/app
name: Testing CakePHP
on: [push, pull_request]
jobs:
tests:
strategy:
matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
php-versions: ['8.4', '8.5']
runs-on: ${{ matrix.operating-system }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, intl, pdo_sqlite, pdo_mysql
coverage: pcov
- name: Get composer cache directory
id: composer-cache
shell: bash
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: |
composer install --no-progress --prefer-dist --optimize-autoloader
composer run-script post-install-cmd --no-interaction
- name: Test with phpunit
run: vendor/bin/phpunit --coverage-text
coding-standard:
name: Coding Standard
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: mbstring, intl
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: PHP CodeSniffer
run: composer cs-check
static-analysis:
name: Static Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: mbstring, intl
tools: phpstan
- name: Install dependencies
run: |
composer install --no-progress --prefer-dist --optimize-autoloader
composer run-script post-install-cmd --no-interaction
- name: Static Analysis using PHPStan
run: phpstan analyse --no-progress src/
WordPress plugin (Ubuntu with MySQL)
WordPress plugin (Ubuntu with MySQL)
Tests a WordPress plugin using the official
wp scaffold plugin-tests scaffolding. Requires a MySQL service container and the WordPress test environment install script.# GitHub Action for WordPress plugins
# Tested with files scaffolded by wp scaffold plugin-tests --ci=github
# Requires phpunit/phpunit and yoast/phpunit-polyfills in require-dev for vendor/bin/phpunit
name: Testing WordPress
on: [push, pull_request]
jobs:
wordpress:
name: WordPress (PHP ${{ matrix.php-versions }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8.4', '8.5']
# Docs: https://docs.github.com/en/actions/using-containerized-services
services:
mysql:
image: mysql:latest
env:
MYSQL_ALLOW_EMPTY_PASSWORD: false
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress_test
ports:
- 3306/tcp
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, xml, zip, intl, mysql
coverage: none
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install system dependencies
run: sudo apt-get update && sudo apt-get install -y subversion default-mysql-client
- name: Install Composer dependencies
run: composer install --no-interaction --no-progress --prefer-dist --optimize-autoloader
- name: Install WordPress test environment
run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1:${{ job.services.mysql.ports['3306'] }} latest true
- name: Test with phpunit
run: vendor/bin/phpunit
The complete set of example workflows, including database variants (MySQL, PostgreSQL) and additional frameworks, is available in the
examples/ directory of the setup-php repository.