Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Plugin Api Laravel Package

phpcq/plugin-api

phpcq/plugin-api provides the plugin interfaces used by the phpcq tool runner, enabling PHP code quality checks to be integrated and automated in CI pipelines. It defines the contracts plugins implement to extend phpcq’s analysis and reporting.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies Require both the API and the core runner in composer.json:

    composer require phpcq/plugin-api phpcq/phpcq
    
  2. First Use Case: Custom Rule Create a Laravel Artisan command to execute a basic phpcq check:

    php artisan make:command RunPhpcqCheck
    

    Implement the command to run phpcq with a custom plugin:

    // app/Console/Commands/RunPhpcqCheck.php
    use Symfony\Component\Process\Process;
    use Symfony\Component\Process\Exception\ProcessFailedException;
    
    public function handle()
    {
        $process = new Process(['phpcq', 'run', '--plugin=MyCustomPlugin']);
        $process->run();
    
        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }
    
        $this->info($process->getOutput());
    }
    
  3. Where to Look First

    • Interfaces: src/PluginInterface.php, src/RuleInterface.php, src/ConfigInterface.php
    • Laravel Integration: Use Process facade for CLI execution or embed phpcq logic directly.
    • Configuration: Check .phpcq.php in your project root for default settings.

Implementation Patterns

Plugin Development

  1. Basic Plugin Structure Create a plugin class implementing PluginInterface:

    // app/Plugins/CustomLaravelRule.php
    namespace App\Plugins;
    
    use Phpcq\PluginApi\PluginInterface;
    use Phpcq\PluginApi\ResultInterface;
    use Phpcq\PluginApi\RuleInterface;
    
    class CustomLaravelRule implements PluginInterface
    {
        public function getRules(): array
        {
            return [new LaravelMagicMethodRule()];
        }
    
        public function run(): ResultInterface
        {
            // Initialize and execute rules
            return new Result();
        }
    }
    
  2. Rule Implementation Implement RuleInterface for specific checks:

    // app/Rules/LaravelMagicMethodRule.php
    use Phpcq\PluginApi\RuleInterface;
    use Phpcq\PluginApi\Violation;
    
    class LaravelMagicMethodRule implements RuleInterface
    {
        public function check(string $filePath): array
        {
            $violations = [];
            $content = file_get_contents($filePath);
    
            if (preg_match('/__get|__set|__call/', $content)) {
                $violations[] = new Violation(
                    'Magic methods detected',
                    $filePath,
                    1
                );
            }
    
            return $violations;
        }
    }
    
  3. Configuration Integration Merge Laravel config with phpcq settings:

    // config/phpcq.php
    return [
        'plugins' => [
            'custom_laravel_rule' => [
                'enabled' => env('PHPcq_CUSTOM_RULE_ENABLED', true),
                'severity' => 'high',
            ],
        ],
    ];
    

Workflows

  1. CI/CD Integration Add a GitHub Actions workflow:

    # .github/workflows/phpcq.yml
    name: PHP Code Quality
    on: [push, pull_request]
    
    jobs:
      phpcq:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - run: composer install
          - run: php artisan phpcq:check
    
  2. Pre-Commit Hooks Use Laravel Pint or a custom script to run phpcq before commits:

    # .git/hooks/pre-commit
    #!/bin/bash
    php artisan phpcq:check || exit 1
    
  3. Dynamic Plugin Loading Register plugins dynamically in a service provider:

    // app/Providers/PhpcqServiceProvider.php
    use Phpcq\PluginApi\PluginManager;
    
    public function register()
    {
        $this->app->singleton(PluginManager::class, function ($app) {
            $manager = new PluginManager();
            $manager->addPlugin(new CustomLaravelRule());
            return $manager;
        });
    }
    

Laravel-Specific Patterns

  1. Artisan Command Wrapper Extend phpcq functionality with Laravel commands:

    // app/Console/Commands/PhpcqFix.php
    public function handle()
    {
        $process = new Process(['phpcq', 'fix', '--plugin=MyCustomPlugin']);
        $process->run();
        $this->info('Fixed issues: ' . $process->getOutput());
    }
    
  2. Event-Driven Execution Trigger phpcq checks on file changes:

    // app/Providers/EventServiceProvider.php
    protected $listen = [
        'Illuminate\Filesystem\Events\FileUpdated' => [
            'App\Listeners\RunPhpcqOnUpdate',
        ],
    ];
    
  3. Notification Integration Convert phpcq violations to Laravel notifications:

    // app/Listeners/NotifyPhpcqViolations.php
    public function handle($event)
    {
        if ($event->violations->count()) {
            Notification::send(
                auth()->user(),
                new PhpcqViolationNotification($event->violations)
            );
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Configuration Conflicts

    • Issue: Laravel’s config and .phpcq.php may override each other unpredictably.
    • Fix: Use Laravel’s mergeConfigFrom to prioritize settings:
      $this->mergeConfigFrom(__DIR__.'/phpcq.php', 'phpcq');
      
  2. Plugin Isolation

    • Issue: Plugins may conflict if not namespaced properly.
    • Fix: Use unique plugin IDs and namespaces:
      class CustomLaravelRule implements PluginInterface
      {
          public function getId(): string
          {
              return 'app::laravel.magic_methods';
          }
      }
      
  3. Performance Overhead

    • Issue: Running phpcq in HTTP requests slows responses.
    • Fix: Offload to queues or run in CI only:
      // config/phpcq.php
      'run_in_ci_only' => env('APP_ENV') !== 'local',
      
  4. Dependency Hell

    • Issue: phpcq/plugin-api may lag behind phpcq/phpcq.
    • Fix: Pin versions strictly in composer.json:
      "require-dev": {
          "phpcq/plugin-api": "1.0.0",
          "phpcq/phpcq": "2.0.0"
      }
      

Debugging

  1. Log Output Redirect phpcq logs to Laravel’s storage:

    $process = new Process(['phpcq', 'run'], null, [
        'phpcq.log' => ['file', '/tmp/phpcq.log', 'a'],
    ]);
    
  2. Mocking Plugins Use Laravel’s mocking for testing:

    $this->mock(PluginManager::class, function ($mock) {
        $mock->shouldReceive('getPlugin')
             ->with('custom_rule')
             ->andReturn(new MockPlugin());
    });
    
  3. Violation Tracing Track violations back to source files:

    $violations = $result->getViolations();
    foreach ($violations as $violation) {
        $this->error("File {$violation->getFile()}, Line {$violation->getLine()}: {$violation->getMessage()}");
    }
    

Tips

  1. Leverage Laravel’s DI Bind phpcq interfaces to Laravel’s container for easier testing:

    $this->app->bind(RuleInterface::class, function ($app) {
        return new LaravelMagicMethodRule();
    });
    
  2. Custom Result Formatters Convert phpcq results to Laravel-friendly formats (e.g., JSON for APIs):

    $result = $plugin->run();
    return response()->json($result->toArray());
    
  3. Plugin Scaffolding Create a Laravel command to scaffold new plugins:

    php artisan make:phpcq-plugin CustomRule --rule="CheckForDeprecatedMethods"
    
  4. Environment-Specific Rules Dynamically enable/disable rules based on environment:

    // In your PluginInterface implementation
    public function isEnabled(): bool
    {
        return app()->environment('local') || config('phpcq.debug_mode');
    }
    
  5. Cache Results Cache phpcq results to avoid redundant scans:

    $cacheKey = 'phpcq.results.' . md5_file($filePath);
    $result = Cache::remember($cacheKey, now()->addHours(1), function () use ($filePath) {
        return $this->check($filePath);
    });
    
  6. Extend with Events Dispatch Laravel events for phpcq violations:

    event(new
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor