Skip to content

Commands ​

Run application commands directly from the debug panel — tests, static analysis, and composer scripts.

Commands

Built-in Commands ​

Built-in commands are auto-discovered. If the tool is installed, the command appears automatically — no configuration needed.

Static Analysis ​

CommandToolAuto-detection
analyse/psalmPsalmvimeo/psalm in Composer
analyse/phpstanPHPStanphpstan/phpstan in Composer
analyse/magoMagocarthage-software/mago in Composer or mago binary in PATH

Testing ​

CommandToolAuto-detection
test/phpunitPHPUnitphpunit/phpunit in Composer
test/codeceptionCodeceptioncodeception/codeception in Composer
test/pestPestpestphp/pest in Composer
test/testoTestotesto/testo in Composer

Other ​

CommandSourceDescription
composer/*composer.jsonAll scripts entries are auto-discovered as composer/{scriptName}

How It Works ​

Commands are discovered from three sources:

  1. Built-in commands — All analyse and test commands from the table above. Each command has an isAvailable() check; unavailable commands are hidden automatically.
  2. Custom commands — Additional commands registered via adapter config (commandMap).
  3. Composer scripts — All scripts entries from composer.json are exposed as composer/{scriptName} commands.

Click a command button to execute it. Output is displayed in a dialog with status indication.

Creating Custom Commands ​

Implement CommandInterface to create a custom command:

php
<?php

declare(strict_types=1);

namespace App\Debug\Command;

use AppDevPanel\Api\Inspector\CommandInterface;
use AppDevPanel\Api\Inspector\CommandResponse;
use AppDevPanel\Api\PathResolverInterface;
use Symfony\Component\Process\Process;

class MyLinterCommand implements CommandInterface
{
    public const COMMAND_NAME = 'analyse/my-linter';

    public function __construct(
        private readonly PathResolverInterface $pathResolver,
    ) {}

    public static function isAvailable(): bool
    {
        return \Composer\InstalledVersions::isInstalled('vendor/my-linter');
    }

    public static function getTitle(): string
    {
        return 'My Linter';
    }

    public static function getDescription(): string
    {
        return 'Run custom linter on the project';
    }

    public function run(): CommandResponse
    {
        $process = new Process(['vendor/bin/my-linter', 'check']);
        $process->setWorkingDirectory($this->pathResolver->getRootPath())
            ->setTimeout(null)
            ->run();

        $output = rtrim($process->getOutput());

        if ($process->getExitCode() > 1) {
            return new CommandResponse(
                status: CommandResponse::STATUS_FAIL,
                result: null,
                errors: array_filter([$output, $process->getErrorOutput()]),
            );
        }

        return new CommandResponse(
            status: $process->isSuccessful()
                ? CommandResponse::STATUS_OK
                : CommandResponse::STATUS_ERROR,
            result: $output,
        );
    }
}

CommandInterface ​

php
interface CommandInterface
{
    public static function isAvailable(): bool; // Return false to hide the command
    public static function getTitle(): string;  // Display name in the panel
    public static function getDescription(): string;
    public function run(): CommandResponse;
}

CommandResponse ​

StatusMeaning
okCommand succeeded
errorCommand ran but reported issues (e.g., lint errors found)
failCommand could not run (e.g., binary not found, crash)

Registering Custom Commands ​

Custom commands are registered via the commandMap parameter. Built-in commands are always included — commandMap only adds extras.

Yii 3 ​

In your application params (config/params.php):

php
return [
    'app-dev-panel/yii3' => [
        'api' => [
            'commandMap' => [
                'analyse' => [
                    'analyse/my-linter' => \App\Debug\Command\MyLinterCommand::class,
                ],
            ],
        ],
    ],
];

Register dependencies in your DI config if the command needs constructor injection:

php
\App\Debug\Command\MyLinterCommand::class => static fn(
    \AppDevPanel\Api\PathResolverInterface $pathResolver,
) => new \App\Debug\Command\MyLinterCommand($pathResolver),

Symfony ​

In your config/packages/app_dev_panel.yaml:

yaml
services:
    App\Debug\Command\MyLinterCommand:
        arguments:
            - '@AppDevPanel\Api\PathResolverInterface'

Override CommandController to pass the commandMap:

yaml
services:
    AppDevPanel\Api\Inspector\Controller\CommandController:
        arguments:
            $commandMap:
                analyse:
                    analyse/my-linter: App\Debug\Command\MyLinterCommand

Laravel ​

In a service provider:

php
use AppDevPanel\Api\Inspector\Controller\CommandController;
use AppDevPanel\Api\PathResolverInterface;

$this->app->singleton(MyLinterCommand::class, fn() => new MyLinterCommand(
    $this->app->make(PathResolverInterface::class),
));

$this->app->extend(CommandController::class, function (CommandController $controller) {
    // Built-in commands are already included.
    // Use the commandMap constructor parameter for custom commands.
    return new CommandController(
        $this->app->make(\AppDevPanel\Api\Http\JsonResponseFactoryInterface::class),
        $this->app->make(PathResolverInterface::class),
        $this->app,
        [
            'analyse' => [
                'analyse/my-linter' => MyLinterCommand::class,
            ],
        ],
    );
});

Yii 2 ​

In your application config (config/web.php):

php
'modules' => [
    'debug' => [
        'class' => \AppDevPanel\Adapter\Yii2\Module::class,
        'commandMap' => [
            'analyse' => [
                'analyse/my-linter' => \App\Debug\Command\MyLinterCommand::class,
            ],
        ],
    ],
],

API Endpoints ​

MethodPathDescription
GET/inspect/api/commandList available commands
POST/inspect/api/command?command=analyse/psalmExecute a command

Response format:

json
{
    "status": "ok",
    "result": "...",
    "error": []
}

TIP

PHPUnit and Codeception commands use custom JSON reporters for structured output in the panel. Other commands return plain text output.

Released under the MIT License.