Supporting two PHP versions means running the suite on both, and doing that as two copies of the job is two things to keep in step.
strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0']
laravel: ['^7.0', '^8.0']
exclude:
- php: '7.4'
laravel: '^8.0'
steps:
- uses: shivammathur/setup-php@v2
with: { php-version: "${{ matrix.php }}" }
- run: composer require laravel/framework:"${{ matrix.laravel }}" --no-update
fail-fast: false is the setting worth changing from the default: without it, one failing combination cancels the rest and you learn about one problem instead of four. The exclude block is what keeps the matrix honest — a full cross product usually contains combinations nobody supports, and running them produces failures that mean nothing. Each combination is a separate runner, so a four-way matrix is four times the minutes.