bernardosecades/php-quality-tools
Collection of PHP quality and static analysis tools bundled for easier setup and consistent code standards across projects, including linters, formatters, and test/coverage helpers to streamline CI and improve code health.
Installation Add the package via Composer:
composer require --dev bernardosecades/php-quality-tools
Register the service provider in config/app.php under providers:
Bernardosecades\PhpQualityTools\PhpQualityToolsServiceProvider::class,
Basic Configuration Publish the default config file:
php artisan vendor:publish --provider="Bernardosecades\PhpQualityTools\PhpQualityToolsServiceProvider" --tag="config"
Edit config/php-quality-tools.php to define your preferred tools (e.g., phpstan, pint, phpunit).
First Use Case Run a quality check for your project:
php artisan php-quality-tools:check
This executes all configured tools in sequence, stopping on failures if stop_on_failure is true.
CI/CD Pipeline Trigger checks in GitHub Actions, GitLab CI, or other CI tools:
# Example GitHub Actions workflow
jobs:
quality-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: php artisan php-quality-tools:check
Pre-Commit Hooks
Use php-quality-tools:check in a pre-commit hook (via husky or pre-commit) to enforce quality before commits:
# .husky/pre-commit
#!/bin/sh
php artisan php-quality-tools:check --stop-on-failure
Custom Commands Extend the base command for project-specific logic:
// app/Console/Commands/CustomQualityCheck.php
namespace App\Console\Commands;
use Bernardosecades\PhpQualityTools\Commands\QualityCheckCommand;
use Illuminate\Console\Scheduling\Schedule;
class CustomQualityCheck extends QualityCheckCommand
{
protected function getTools(): array
{
return array_merge(parent::getTools(), [
'phpstan' => [
'command' => 'phpstan analyse --level=max src',
],
]);
}
}
Register the command in app/Console/Kernel.php:
protected function commands()
{
$this->load(__DIR__.'/Commands');
$this->call('custom:quality-check');
}
Parallel Execution
For faster feedback, run tools in parallel using parallel-lint or GNU parallel:
find . -name "*.php" | parallel --will-cite php -l {} > /dev/null
php artisan php-quality-tools:check --tools=phpstan,pint
PHPStan
Configure in php-quality-tools.php:
'phpstan' => [
'command' => 'phpstan analyse --level=max src',
'ignore_failures' => false,
],
Use phpstan.neon for project-specific rules.
Pint Auto-format PHP files:
php artisan php-quality-tools:check --tools=pint
Customize rules in pint.json.
PHPUnit Run tests with custom configurations:
'phpunit' => [
'command' => 'phpunit --testdox-html=tests/coverage.html',
],
Custom Tools
Add arbitrary commands (e.g., psalm or infection):
'psalm' => [
'command' => 'vendor/bin/psalm --init',
'stop_on_failure' => true,
],
Tool Dependencies
Ensure all tools (e.g., phpstan, pint) are installed via Composer:
composer require --dev phpstan/phpstan pintphp/pint
Configuration Overrides Avoid hardcoding tool paths. Use the config file or environment variables:
'phpstan' => [
'command' => env('PHPSTAN_COMMAND', 'vendor/bin/phpstan analyse'),
],
Performance
--generate-baseline for PHPStan to skip unchanged files.pint, phpstan) in parallel.Exit Codes
Tools may return non-zero exit codes on warnings. Use ignore_failures to bypass:
'pint' => [
'command' => 'pint',
'ignore_failures' => env('IGNORE_PINT_WARNINGS', false),
],
Verbose Output Enable debug mode for detailed logs:
php artisan php-quality-tools:check --verbose
Dry Runs Test configurations without executing:
php artisan php-quality-tools:check --dry-run
Tool-Specific Flags Pass custom flags directly:
php artisan php-quality-tools:check --tools="phpstan:--memory-limit=1G"
Custom Validators
Extend the QualityCheckCommand to add validation logic:
protected function validateTools(): void
{
foreach ($this->tools as $tool => $config) {
if (!file_exists($config['command'])) {
$this->error("Tool '$tool' command not found: {$config['command']}");
exit(1);
}
}
}
Event Listeners Dispatch events for post-check actions (e.g., Slack notifications):
// app/Providers/EventServiceProvider.php
protected $listen = [
'Bernardosecades\PhpQualityTools\Events\CheckCompleted' => [
'App\Listeners\NotifySlackOnFailure',
],
];
Dynamic Tool Loading Load tools dynamically from a database or API:
protected function getTools(): array
{
return Cache::remember('quality-tools', now()->addHours(1), function () {
return Tool::where('enabled', true)->pluck('command', 'name')->toArray();
});
}
Environment-Specific Tools Use environment variables to toggle tools:
'phpstan' => [
'command' => env('RUN_PHPSTAN', false) ? 'phpstan analyse' : null,
],
Tool Chaining
Chain tools to pass output between them (e.g., phpunit → phpstan):
'phpunit' => [
'command' => 'phpunit --testdox-html=tests/coverage.html',
'output_file' => 'tests/coverage.html',
],
'phpstan' => [
'command' => 'phpstan analyse --coverage tests/coverage.html',
],
Silent Mode Suppress output for CI/CD:
php artisan php-quality-tools:check --quiet
How can I help you explore Laravel packages today?