PHPackages                             danilovl/web-command-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. danilovl/web-command-bundle

ActiveSymfony-bundle

danilovl/web-command-bundle
===========================

A Symfony bundle for running console commands via web interface

v0.0.5(1mo ago)03↑2900%MITPHPPHP ^8.5

Since Mar 29Pushed 1mo agoCompare

[ Source](https://github.com/danilovl/web-command-bundle)[ Packagist](https://packagist.org/packages/danilovl/web-command-bundle)[ RSS](/packages/danilovl-web-command-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (15)Versions (6)Used By (0)

[![phpunit](https://github.com/danilovl/web-command-bundle/actions/workflows/phpunit.yml/badge.svg)](https://github.com/danilovl/web-command-bundle/actions/workflows/phpunit.yml)[![downloads](https://camo.githubusercontent.com/f6d714d089894f1782da8787952a07b70324d90528930904a5377886fb915461/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f64616e696c6f766c2f7765622d636f6d6d616e642d62756e646c65)](https://packagist.org/packages/danilovl/web-command-bundle)[![latest Stable Version](https://camo.githubusercontent.com/4c642a5a8e3e30cc2e4f6ba2d51f7d738cfe01d26ec78e40a32ff1a70ea61cd0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f64616e696c6f766c2f7765622d636f6d6d616e642d62756e646c65)](https://packagist.org/packages/danilovl/web-command-bundle)[![license](https://camo.githubusercontent.com/396a9840d140a3c3aa1d8d5a9ee1a9887edba2c5fa10339a39b1b76a25e1fe90/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f64616e696c6f766c2f7765622d636f6d6d616e642d62756e646c65)](https://packagist.org/packages/danilovl/web-command-bundle)

WebCommandBundle
================

[](#webcommandbundle)

A Symfony bundle for running console commands via web interface (REST API). Supports both synchronous and asynchronous (via Messenger) execution.

Features
--------

[](#features)

- REST API for listing and running commands.
- Support for asynchronous command execution using Symfony Messenger.
- Configurable API prefix, console path, memory and time limits.
- Entity-based management for commands, jobs and history.
- EasyAdmin integration for managing commands and viewing history.
- Flexible command configuration (voters, async, history, parameters, etc.).
- Automatic PHP binary detection.

Available dashboard
-------------------

[](#available-dashboard)

[![Alt text](/readme/dashboard.png?raw=true "Dashboard")](/readme/dashboard.png?raw=true)

Installation
------------

[](#installation)

1. Install the bundle via composer:

```
composer require danilovl/web-command-bundle
```

2. Add the bundle to `config/bundles.php`:

```
return [
    // ...
    Danilovl\WebCommandBundle\WebCommandBundle::class => ['all' => true],
];
```

3. Import routes in `config/routing.yaml` (routing is not automatic):

```
web_command:
    resource: '@WebCommandBundle/src/Resources/config/routing.yaml'
```

4. Doctrine entity mapping

Add entity mapping to `doctrine.yaml` in `packages` folder.

```
orm:
  mappings:
    Danilovl\WebCommandBundle:
      is_bundle: false
      type: attribute
      dir: "%kernel.project_dir%/vendor/danilovl/web-command-bundle/src/Entity/"
      prefix: 'Danilovl\WebCommandBundle\Entity'
```

5. Update your database schema:

```
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
```

Configuration
-------------

[](#configuration)

Create `config/packages/web_command.yaml`:

```
danilovl_web_command:
    api_prefix: '/api/web'
    console_path: null
    enable_async: false
    default_timeout: null
    default_time_limit: null
    default_memory_limit: null
    enabled_admin_dashboard: false
    enabled_dashboard_live_status: true
```

*Note:*

- `console_path`: if `null` (default), it's `%kernel.project_dir%/bin/console`. If set, it's used as is (absolute path).
- `default_timeout`, `default_time_limit` and `default_memory_limit` are `null` by default.
- `default_timeout`: default timeout (seconds) for synchronous command execution via API.
- `default_time_limit`: default timeout (seconds) for asynchronous command execution.
- `default_memory_limit`: applied via `-d memory_limit=...` during process execution.
- `enabled_admin_dashboard`: enable EasyAdmin dashboard integration.
- `enabled_dashboard_live_status`: enable/disable interval requests to check job status on the web dashboard.

### Messenger Configuration

[](#messenger-configuration)

To enable asynchronous execution, configure Symfony Messenger:

```
framework:
    messenger:
        transports:
            async: '%env(MESSENGER_TRANSPORT_DSN)%'
        routing:
            'Danilovl\WebCommandBundle\Message\RunCommandMessage': async
```

Usage
-----

[](#usage)

### REST API

[](#rest-api)

The bundle provides a REST API to interact with commands. By default, the API is available under the `/api/web` prefix.

### Admin Interface

[](#admin-interface)

The bundle includes a built-in EasyAdmin dashboard for managing commands and viewing execution history. To use it, ensure you have `EasyAdminBundle` installed and configured, and enable it in the configuration:

```
danilovl_web_command:
    enabled_admin_dashboard: true
```

The dashboard is available at `/admin/danilovl/web-command`.

The admin interface allows you to:

- Create, update, and delete commands.
- View execution history and command outputs.

### Web Dashboard

[](#web-dashboard)

The bundle also provides a standalone web dashboard to run commands and view their history.

The dashboard is available at `/danilovl/web-command/dashboard`. **Route Name:** `danilovl_web_command_dashboard_index`

**Features:**

- List of active commands.
- Input for additional parameters.
- Formatted output display.
- History of recent executions with pagination.

To use the web dashboard, you need to install assets:

```
php bin/console assets:install
```

#### Managing Commands

[](#managing-commands)

Each command is represented as an entity with several configuration options:

- **Name**: The display name of the command.
- **Command**: The actual Symfony console command (e.g., `app:sync-users`).
- **Parameters**: Default arguments and options (e.g., `["--force", "prod"]`).
- **Allow Custom Parameters**: If enabled, users can provide additional parameters when running the command.
- **Async**: Enable asynchronous execution via Symfony Messenger.
- **Save History**: Whether to record execution history in the database.
- **Save Output**: Save the command's stdout/stderr in the history record.
- **Voter Class**: Specify a Symfony Voter class or a security role (e.g., `ROLE_ADMIN`) to restrict command execution based on custom logic.
- **Active**: Easily enable/disable command from being executed.
- **Description**: Add notes about the command's purpose.

When adding a command, specify its name and optional default parameters. The `Parameters` field must be a **JSON array of strings**. These are arguments and options passed to the command.

**Example for `app:example --fix`:**

- **Name**: `app:example`
- **Parameters**: `["--fix"]`

**Example for `app:example arg1 --option=value`:**

- **Name**: `app:example`
- **Parameters**: `["arg1", "--option=value"]`

#### 1. List Commands

[](#1-list-commands)

Retrieve a list of all active commands that can be executed via the web interface.

**Endpoint:** `GET /api/web/commands/`
**Route Name:** `danilovl_web_commands`

**Response (200 OK):**

```
[
  {
    "id": 1,
    "name": "app:example-command",
    "command": "app:example",
    "allowCustomParameters": true,
    "voterClass": "App\\Security\\Voter\\ExampleVoter",
    "description": "This is an example command description",
    "active": true,
    "async": false,
    "saveHistory": true,
    "saveOutput": false,
    "parameters": [],
    "createdAt": "2024-03-28T10:00:00+00:00",
    "updatedAt": null
  }
]
```

#### 2. Run Command

[](#2-run-command)

Execute a command.

**Endpoint:** `POST /api/web/commands/{id}/run`
**Route Name:** `danilovl_web_command_run`

**Request Body:**

```
{
  "input": ["--option=value", "argument"],
  "timeout": 300
}
```

**Response (200 OK - Synchronous execution):**

```
{
  "output": "Command output string...",
  "exitCode": 0,
  "duration": 1.5
}
```

**Response (202 Accepted - Asynchronous execution):***Returned when the command has `async: true` and asynchronous execution is enabled.*

```
{
  "status": "queued",
  "jobId": 1
}
```

**Response (404 Not Found):**

```
{
  "error": "Command not found or disabled"
}
```

#### 3. List Histories

[](#3-list-histories)

Retrieve a paginated list of histories for a specific command.

**Endpoint:** `GET /api/web/commands/{command}/histories`
**Route Name:** `danilovl_web_command_histories`

**Path Parameters:**

- `command`: The ID of the command.

**Query Parameters:**

- `page` (optional): Page number (default: 1)

**Response (200 OK):**

```
{
  "histories": [
    {
      "id": 1,
      "command": { "id": 1, "name": "app:example-command", ... },
      "async": true,
      "duration": 1.5,
      "exitCode": 0,
      "errorMessage": null,
      "output": "Command output...",
      "metaInfo": { "userId": 1, "userName": "admin" },
      "createdAt": "2024-03-28 10:00:00"
    }
  ],
  "totalPages": 1,
  "currentPage": 1
}
```

#### 4. Get History Details

[](#4-get-history-details)

Retrieve details and output of a specific history record.

**Endpoint:** `GET /api/web/commands/histories/{id}`
**Route Name:** `danilovl_web_command_history_detail`

**Response (200 OK):**

```
{
  "id": 1,
  "command": { "id": 1, "name": "app:example-command", ... },
  "async": true,
  "duration": 1.5,
  "exitCode": 0,
  "errorMessage": null,
  "output": "Command output...",
  "metaInfo": { "userId": 1, "userName": "admin" },
  "createdAt": "2024-03-28 10:00:00"
}
```

**Response (404 Not Found):**

```
{
  "error": "History not found"
}
```

#### 5. Get Job Status

[](#5-get-job-status)

Retrieve the status of a specific job.

**Endpoint:** `GET /api/web/jobs/{id}/status`
**Route Name:** `danilovl_web_command_job_status`

**Response (200 OK):**

```
{
  "status": "queued"
}
```

### Security

[](#security)

#### Voter

[](#voter)

Each command can be protected by a Symfony Voter. Specify a **Voter Class** (or a role like `ROLE_ADMIN`) in the command configuration. The bundle will check permissions using `AuthorizationCheckerInterface::isGranted()`.

#### URL Security

[](#url-security)

To restrict access to the dashboards and API to specific roles, configure Symfony's `access_control` in `config/packages/security.yaml`:

```
security:
    access_control:
        - { path: ^/api/web, roles: ROLE_ADMIN }
        - { path: ^/danilovl/web-command/dashboard, roles: ROLE_ADMIN }
```

Events
------

[](#events)

The bundle dispatches events during the command execution lifecycle, allowing you to intercept and modify the process.

### CommandStartEvent

[](#commandstartevent)

Dispatched before a command is executed.

**Usage:**

- Cancel command execution.
- Modify command input.
- Add or modify meta information.

```
use Danilovl\WebCommandBundle\Event\CommandStartEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

#[AsEventListener]
class CommandStartListener
{
    public function __invoke(CommandStartEvent $event): void
    {
        if ($someCondition) {
            $event->setShouldContinue(false);
            $event->setReason('Reason for cancellation');
        }

        $metaInfo = $event->getMetaInfo() ?? [];
        $metaInfo['custom_key'] = 'custom_value';

        $event->setMetaInfo($metaInfo);
    }
}
```

### CommandEndEvent

[](#commandendevent)

Dispatched after a command has finished execution (successfully or with an error).

```
use Danilovl\WebCommandBundle\Event\CommandEndEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

#[AsEventListener]
class CommandEndListener
{
    public function __invoke(CommandEndEvent $event): void
    {
        $exitCode = $event->getExitCode();
        $output = $event->getOutput();

        // Do something with the result
    }
}
```

Meta Information
----------------

[](#meta-information)

The `History` entity includes a `metaInfo` field (JSON). By default, if the Symfony Security component is available, it automatically stores:

- `userId`: ID of the current user.
- `userIdentifier`: Identifier of the current user.

You can customize this data via `CommandStartEvent::setMetaInfo()`. If you set it to `null`, no meta information will be saved.

Database Schema Example
-----------------------

[](#database-schema-example)

```
CREATE TABLE danilovl_web_command
(
    id                      INT AUTO_INCREMENT NOT NULL,
    name                    VARCHAR(255)       NOT NULL,
    command                 VARCHAR(255)       NOT NULL,
    parameters              JSON               NOT NULL,
    allow_custom_parameters TINYINT            NOT NULL,
    voter_class             VARCHAR(255)                DEFAULT NULL,
    active                  TINYINT            NOT NULL,
    async                   TINYINT            NOT NULL,
    save_history            TINYINT(1)         NOT NULL DEFAULT 1,
    save_output             TINYINT(1)         NOT NULL DEFAULT 0,
    description             LONGTEXT                    DEFAULT NULL,
    created_at              DATETIME           NOT NULL,
    updated_at              DATETIME                    DEFAULT NULL,

    UNIQUE INDEX UNIQ_73DBE01B5E237E06 (name),
    PRIMARY KEY (id)
) DEFAULT CHARACTER SET utf8mb4;

CREATE TABLE danilovl_web_command_job
(
    id         INT AUTO_INCREMENT NOT NULL,
    command_id INT                NOT NULL,
    input      JSON               NOT NULL,
    status     VARCHAR(20)        NOT NULL,
    created_at DATETIME           NOT NULL,

    PRIMARY KEY (id),
    INDEX IDX_3389C56E33E1689A (command_id),
    CONSTRAINT FK_3389C56E33E1689A FOREIGN KEY (command_id) REFERENCES danilovl_web_command (id) ON DELETE CASCADE
) DEFAULT CHARACTER SET utf8mb4;

CREATE TABLE danilovl_web_command_history
(
    id            INT AUTO_INCREMENT NOT NULL,
    command_id    INT                NOT NULL,
    async         TINYINT(1)         NOT NULL,
    duration      DOUBLE PRECISION   NOT NULL,
    exit_code     INT                NOT NULL,
    error_message LONGTEXT DEFAULT NULL,
    output        LONGTEXT DEFAULT NULL,
    meta_info     JSON     DEFAULT NULL,
    created_at    DATETIME           NOT NULL,

    PRIMARY KEY (id),
    INDEX IDX_HISTORY_COMMAND (command_id),
    CONSTRAINT FK_HISTORY_COMMAND FOREIGN KEY (command_id) REFERENCES danilovl_web_command (id) ON DELETE CASCADE
) DEFAULT CHARACTER SET utf8mb4;
```

License
-------

[](#license)

The WebCommandBundle is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance90

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

5

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1f695c3614981d994e19a87e7b2c892768642a577d7eeeb1c6b4bf899b566557?d=identicon)[danilovl](/maintainers/danilovl)

---

Top Contributors

[![danilovl](https://avatars.githubusercontent.com/u/16228565?v=4)](https://github.com/danilovl "danilovl (5 commits)")

---

Tags

phpsymfonybundleREST APIweb interfaceconsole commandweb-command

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/danilovl-web-command-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/danilovl-web-command-bundle/health.svg)](https://phpackages.com/packages/danilovl-web-command-bundle)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
