{"id":33948107,"url":"https://github.com/monzer15/filament-workflows","last_synced_at":"2026-04-04T12:58:58.134Z","repository":{"id":279236781,"uuid":"938166737","full_name":"monzer15/filament-workflows","owner":"monzer15","description":"Automation made easy!","archived":false,"fork":false,"pushed_at":"2025-09-30T12:28:57.000Z","size":187,"stargazers_count":64,"open_issues_count":7,"forks_count":14,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-03-26T16:11:57.891Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monzer15.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-24T14:25:38.000Z","updated_at":"2026-03-06T22:33:57.000Z","dependencies_parsed_at":"2025-02-24T14:55:14.576Z","dependency_job_id":"74d76a42-c4b7-4bbb-b7cc-f4b39c816f6e","html_url":"https://github.com/monzer15/filament-workflows","commit_stats":null,"previous_names":["monzer15/filament-workflows"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/monzer15/filament-workflows","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monzer15%2Ffilament-workflows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monzer15%2Ffilament-workflows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monzer15%2Ffilament-workflows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monzer15%2Ffilament-workflows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monzer15","download_url":"https://codeload.github.com/monzer15/filament-workflows/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monzer15%2Ffilament-workflows/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31400460,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-12T18:25:09.301Z","updated_at":"2026-04-04T12:58:58.128Z","avatar_url":"https://github.com/monzer15.png","language":"PHP","funding_links":["https://paypal.me/monzer15"],"categories":[],"sub_categories":[],"readme":"# 🚀 Filament Workflows Plugin for Laravel\n\n## ✨ Introduction\n\nThis package is a **FilamentPHP plugin** designed to provide a workflow automation system within FilamentPHP\napplications. It enables users to create and manage workflows triggered by model events, custom events, or scheduled\ntasks. The package integrates seamlessly with FilamentPHP, offering a Filament Resource for managing workflows.\n\n## 🌟 Features\n\n- 🔄 Workflow automation via **model events, custom events, or scheduling**.\n- 🛠️ Filament Resource for **CRUD workflow management**.\n- 🏗️ **Supports custom workflow actions**.\n- 📜 **Execution logs** viewable through Filament.\n- 🔗 Chaining of multiple actions.\n- 🌍 **Webhook sending** as an external integration.\n- ✨ **Magic Attributes** enable dynamic replacement of placeholders with model attributes or event data, allowing\n  seamless data binding and automation within the system.\n\n## Screenshots\n\n![Create workflow](art/1.png)\n![Action 1](art/2.png)\n![Action 2](art/3.png)\n\n## ⚙️ Installation \u0026 Setup\n\n### 🖥️ Requirements\n\nEnsure your Laravel application meets the following requirements:\n\n- Laravel 10+\n- FilamentPHP 3.2\n- PHP 8.1+\n\n### 📥 Install the Package\n\n```bash\ncomposer require monzer/filament-workflows\n```\n\n### ⚡ Publish Migration\n\n```bash\nphp artisan vendor:publish --provider=\"Monzer\\FilamentWorkflows\\FilamentWorkflowsServiceProvider\" --tag=\"migrations\"\n```\n\n### ⚡ Publish Configuration (Optional)\n\n```bash\nphp artisan vendor:publish --provider=\"Monzer\\FilamentWorkflows\\FilamentWorkflowsServiceProvider\" --tag=\"config\"\n```\n\n### 📊 Migrate Database\n\n```bash\nphp artisan migrate\n```\n\n### 🔧 Registering the Plugin\n\nUsers must manually register the plugin in their `PanelProvider.php`:\n\n```php\nuse Filament\\Facades\\Filament;\nuse Monzer\\FilamentWorkflows\\WorkflowsPlugin;\n\npublic function panel(Panel $panel): Panel\n{\n    return $panel\n        -\u003eplugin(WorkflowsPlugin::make());\n}\n```\n\n## 📌 Setting Up Model Event Workflows\n\nTo integrate a model with the model event workflow system, the model must implement the following trait:\n\n```php\nuse Monzer\\FilamentWorkflows\\Traits\\TrackWorkflowModelEvents;\n\nclass Order extends Model\n{\n    use TrackWorkflowModelEvents;\n}\n```\n\nTo change the model display name you can use the getModelName() static function:\n\n```php\nuse Monzer\\FilamentWorkflows\\Traits\\TrackWorkflowModelEvents;\n\nclass Order extends Model\n{\n    use TrackWorkflowModelEvents;\n\n    public static function getModelName(): string\n    {\n        return __(\"order.plural\"); //for example \n    }\n}\n```\n\nTo change the attributes display name you can use the getAttributeName() static function:\n\n```php\nuse Monzer\\FilamentWorkflows\\Traits\\TrackWorkflowModelEvents;\n\nclass Order extends Model\n{\n    use TrackWorkflowModelEvents;\n\n    public static function getAttributeName(string $attribute): ?string\n    {\n        switch ($attribute) {\n            case 'id':\n                return __(\"order.fields.id\");\n            case 'type':\n                return __(\"order.fields.type\");\n            //... extra \n            default:\n                return null;\n        }\n    }\n}\n```\n\n## NOTE:\n\nYou need to run php artisan schedule:work command to run the workflows.\n\n## 🔧 Configuration\n\nExample configuration in `config/workflows.php`:\n\n```php\nreturn [\n    'actions' =\u003e [\n        \\Monzer\\FilamentWorkflows\\Actions\\SendFilamentNotification::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\SendEmail::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\SendSmsViaTwilio::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\CreateRecord::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\UpdateRecord::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\SendWebhook::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\PushFirebaseNotification::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\BackupMySqlDBUsingMySqlDump::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\SendWhatsAppMessageViaWassenger::class,\n        \\Monzer\\FilamentWorkflows\\Actions\\SendTelegramMessage::class\n    ],\n    //scan the following directories for models\n    'models_directory' =\u003e [\n        'App\\\\Models',\n    ],\n    'services' =\u003e [\n        'firebase' =\u003e [\n            'server_key' =\u003e env('FIREBASE_SERVER_KEY'),\n            'model_token_attribute_name' =\u003e env('FIREBASE_MODEL_TOKEN_ATTRIBUTE_NAME', 'fcm_token'),\n            'icon' =\u003e env('FIREBASE_ICON'),\n        ],\n        'telegram' =\u003e [\n            'bot_token' =\u003e env('TELEGRAM_BOT_TOKEN'),\n        ],\n        'wassenger' =\u003e [\n            'api_key' =\u003e env('WASSENGER_API_KEY'),\n        ],\n        'twilio' =\u003e [\n            'sid' =\u003e env('TWILIO_SID'),\n            'token' =\u003e env('TWILIO_TOKEN'),\n            'from' =\u003e env('TWILIO_FROM'),\n        ],\n    ],\n    \n    /*\n    |--------------------------------------------------------------------------\n    | Maximum Log Entries\n    |--------------------------------------------------------------------------\n    |\n    | This value determines the maximum number of log entries to keep for\n    | each workflow. When this limit is exceeded, older entries will be\n    | automatically removed to prevent database overflow. Set to null to\n    | disable log rotation (not recommended for production).\n    |\n    */\n    'max_log_entries' =\u003e env('WORKFLOWS_MAX_LOG_ENTRIES', 100),\n];\n```\n\n## 📝 Log Management\n\n### Automatic Log Rotation\n\nStarting from version 0.3.0, this package includes automatic log rotation to prevent database overflow. By default, only the last 100 log entries are kept for each workflow.\n\n#### Configuration\n\nYou can customize the maximum number of log entries by setting the `WORKFLOWS_MAX_LOG_ENTRIES` environment variable:\n\n```env\nWORKFLOWS_MAX_LOG_ENTRIES=200\n```\n\nOr modify it directly in the config file:\n\n```php\n'max_log_entries' =\u003e 200, // Keep last 200 entries\n```\n\nTo disable log rotation (not recommended):\n\n```php\n'max_log_entries' =\u003e null, // Disable rotation\n```\n\n### Cleaning Up Existing Logs\n\nIf you have existing workflows with large log histories, you can clean them up using the provided artisan command:\n\n```bash\n# Clean up logs using the configured limit\nphp artisan workflows:cleanup-logs\n\n# Clean up logs with a custom limit\nphp artisan workflows:cleanup-logs --limit=50\n\n# Preview what would be cleaned without making changes\nphp artisan workflows:cleanup-logs --dry-run\n```\n\n### Database Migration for Large Logs\n\nFor existing installations that experience database errors due to large logs, run the optional migration to increase column size:\n\n```bash\nphp artisan migrate --path=vendor/monzer/filament-workflows/database/migrations/2024_01_01_000000_update_workflows_logs_column_size.php\n```\n\n## 🪄 Magic Attributes\n\nMagic attributes are placeholders that get dynamically replaced with actual data from the model or event triggering the\nworkflow.\n\n### 🔄 **Model Event Workflows**\n\n- **`@email@`** → Replaced by the model's email attribute.\n    - Example:\n      ```\n      Hello @email@, your order has been processed.\n      ```\n    - If the model contains `email = user@example.com`, the message will be:\n      ```\n      Hello user@example.com, your order has been processed.\n      ```\n\n### 🎭 **Custom Event Workflows**\n\n- **`@event-\u003ename@`** → Replaced by the event’s name attribute.\n    - Example:\n      ```\n      A new event named @event-\u003ename@ has been created.\n      ```\n    - If the event contains `name = System Update`, the message will be:\n      ```\n      A new event named System Update has been created.\n      ```\n\n## 🎯 Defining Custom Workflow Actions\n\nUsers can create custom actions by implementing the `Action` interface. Below is an example implementation of the *\n*SendEmail** action:\n\n```php\nnamespace Monzer\\FilamentWorkflows\\Actions;\n\nuse Filament\\Forms\\Components\\Textarea;\nuse Filament\\Forms\\Components\\TextInput;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\Mail;\nuse Monzer\\FilamentWorkflows\\Contracts\\Action;\nuse Monzer\\FilamentWorkflows\\Models\\WorkflowActionExecution;\n\nclass SendEmail extends Action\n{\n    public function getId(): string\n    {\n        return 'send-email';\n    }\n\n    public function getName(): string\n    {\n        return 'Send Email';\n    }\n\n    public function getFields(): array\n    {\n        return [\n            TextInput::make('data.email')\n                -\u003ehelperText(\"Supports magic attributes\")\n                -\u003erequired(),\n            TextInput::make('data.subject')\n                -\u003ehelperText(\"Supports magic attributes\")\n                -\u003erequired(),\n            Textarea::make('data.message')\n                -\u003ehelperText(\"Supports magic attributes\")\n                -\u003erequired()\n                -\u003erows(5),\n        ];\n    }\n\n    public function getMagicAttributeFields(): array\n    {\n        return ['email', 'subject', 'message'];\n    }\n\n    public function execute(array $data, WorkflowActionExecution $actionExecution, ?Model $model, array $custom_event_data, array \u0026$sharedData)\n    {\n        Mail::raw($data['message'], function ($message) use ($data) {\n            $message-\u003eto($data['email'])-\u003esubject($data['subject']);\n        });\n        $actionExecution-\u003elog(\"Email successfully sent to: {$data['email']} regarding: {$data['subject']}\");\n    }\n\n    public function canBeUsedWithScheduledWorkflows(): bool\n    {\n        return true;\n    }\n\n    public function canBeUsedWithRecordEventWorkflows(): bool\n    {\n        return true;\n    }\n\n    public function canBeUsedWithCustomEventWorkflows(): bool\n    {\n        return true;\n    }\n    \n    public function requireInstalledPackages(): array\n    {\n        return [];\n    }\n}\n```\n\nThen add your custom action\n\n```php\nuse Filament\\Facades\\Filament;\nuse Monzer\\FilamentWorkflows\\WorkflowsPlugin;\n\npublic function panel(Panel $panel): Panel\n{\n    return $panel\n        -\u003eplugin(WorkflowsPlugin::make()-\u003eactions([CustomAction::class]));\n}\n```\n\n## 🔗 Sharing Data Between Actions\n\nTo allow actions to be aware of each other and share data, a **shared data array** is passed between actions in\nthe `execute` function. This enables actions to store and retrieve information dynamically as they execute.\n\n### 📌 How It Works:\n\n- Each action **receives a shared data array**.\n- Actions can **store values** inside this array to be used by subsequent actions.\n- The shared data persists **throughout the workflow execution**.\n\n### 📝 Example: Sharing Data Between Actions\n\nLet's say we need to:\n\n1️⃣ **Generate an Invoice** and store the `invoice_id`.\n2️⃣ **Send an Email** using that `invoice_id`.\n\n#### **🛠️ Action 1: Generate Invoice**\n\n```php\nclass GenerateInvoice extends Action\n{\n    public function execute(array $data, WorkflowActionExecution $execution, ?Model $model, array $custom_event_data, array \u0026$sharedData)\n    {\n        // Generate invoice\n        $invoiceId = Str::uuid();\n        $sharedData['invoice_id'] = $invoiceId;\n\n        $execution-\u003elog(\"Generated Invoice ID: $invoiceId\");\n    }\n}\n```\n\n#### **📧 Action 2: Send Email with Invoice ID**\n\n```php\nclass SendEmail extends Action\n{\n    public function execute(array $data, WorkflowActionExecution $execution, ?Model $model, array $custom_event_data, array \u0026$sharedData)\n    {\n        $invoiceId = $sharedData['invoice_id'] ?? 'Unknown';\n\n        Mail::raw(\"Invoice ID: $invoiceId\", function ($message) use ($data) {\n            $message-\u003eto($data['email'])-\u003esubject(\"Your Invoice\");\n        });\n\n        $execution-\u003elog(\"Email sent with Invoice ID: $invoiceId\");\n    }\n}\n```\n\n## Using workflows with tenancy\n\nCreate a middleware to setup tenancy\n\n```php\n\nnamespace App\\Http\\Middleware;\n\nuse Monzer\\FilamentWorkflows\\Models\\Workflow;\n\nclass ApplyTenantScopes\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Closure(\\Illuminate\\Http\\Request): (\\Symfony\\Component\\HttpFoundation\\Response) $next\n     */\n    public function handle(Request $request, Closure $next): Response\n    {\n            Workflow::resolveRelationUsing('team', function ($model) {\n            return $model-\u003ebelongsTo(Team::class, 'team_id');\n        });\n        return $next($request);\n    }\n}\n```\n\nThen, add the middleware to the panel\n\n```php\nuse Filament\\Facades\\Filament;\nuse Monzer\\FilamentWorkflows\\WorkflowsPlugin;\n\npublic function panel(Panel $panel): Panel\n{\n    return $panel\n            -\u003etenantMiddleware([\n                ApplyTenantScopes::class,\n            ], isPersistent: true);\n}\n```\n\n---\n\n## 🧪 Tests\n\nCurrently, **automated tests are not available** for this package. Future updates may include unit tests and integration\ntests to ensure workflow stability and execution accuracy.\n\n## ❤️ Support \u0026 Contributions\n\nFor issues and feature requests, please visit the [GitHub repository](https://github.com/monzer15/filament-workflows) and\ncreate an issue.\n\nPull requests are welcome. Make sure to follow the contribution guidelines.\n\n## 💰 Support the Project\n\nIf you find this package helpful and would like to support its development, consider making a donation:\n\n[☕ Buy Me a Coffee](https://paypal.me/monzer15)\n\nYour support helps improve and maintain this package! 🙌\n\n## 📜 License\n\nThis package is licensed under the MIT License. See the `LICENSE` file for details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonzer15%2Ffilament-workflows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonzer15%2Ffilament-workflows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonzer15%2Ffilament-workflows/lists"}