{"id":28323975,"url":"https://github.com/lumosolutions/actionable","last_synced_at":"2026-05-05T22:40:34.387Z","repository":{"id":292032436,"uuid":"979288932","full_name":"LumoSolutions/actionable","owner":"LumoSolutions","description":"Transform your Laravel code into clean, testable, and reusable actions. Say goodbye to bloated controllers and hello to elegantly organized business logic!","archived":false,"fork":false,"pushed_at":"2025-05-26T10:11:54.000Z","size":50,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-02T02:01:57.510Z","etag":null,"topics":["actionable","actions","dto-pattern","laravel","laravel-package","lumosolutions"],"latest_commit_sha":null,"homepage":"https://actionable.lumosolutions.org/","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/LumoSolutions.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-05-07T09:31:08.000Z","updated_at":"2025-05-26T20:26:13.000Z","dependencies_parsed_at":"2025-05-07T20:19:08.626Z","dependency_job_id":"f84c02c8-2ec9-43c1-899e-052647f9c9f0","html_url":"https://github.com/LumoSolutions/actionable","commit_stats":null,"previous_names":["lumosolutions/actionable"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/LumoSolutions/actionable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LumoSolutions%2Factionable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LumoSolutions%2Factionable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LumoSolutions%2Factionable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LumoSolutions%2Factionable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LumoSolutions","download_url":"https://codeload.github.com/LumoSolutions/actionable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LumoSolutions%2Factionable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261586219,"owners_count":23181060,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["actionable","actions","dto-pattern","laravel","laravel-package","lumosolutions"],"created_at":"2025-05-25T17:09:22.602Z","updated_at":"2026-05-05T22:40:34.360Z","avatar_url":"https://github.com/LumoSolutions.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ⚡ Actionable\n\u003cdiv align=\"center\"\u003e\n\n[![CI Pipeline](https://github.com/LumoSolutions/actionable/actions/workflows/build.yml/badge.svg)](https://github.com/LumoSolutions/actionable/actions/workflows/build.yml)\n[![codecov](https://codecov.io/gh/LumoSolutions/actionable/branch/main/graph/badge.svg)](https://codecov.io/gh/LumoSolutions/actionable)\n[![Latest Stable Version](https://poser.pugx.org/lumosolutions/actionable/v/stable)](https://packagist.org/packages/lumosolutions/actionable)\n[![Total Downloads](https://poser.pugx.org/lumosolutions/actionable/downloads)](https://packagist.org/packages/lumosolutions/actionable)\n[![License](https://img.shields.io/github/license/LumoSolutions/actionable)](LICENSE)\n\n**[Installation](#-installation)** • **[Quick Start](#-quick-start)** • **[Features](#-key-features)** • **[Documentation](#-documentation)** • **[Examples](#-real-world-examples)**\n\n\u003c/div\u003e\n\n![hero](https://github.com/user-attachments/assets/9d7e5e3b-cb82-4fff-a242-847d16051d18)\n\n\u003e **Transform your Laravel code into clean, testable, and reusable actions.** Say goodbye to bloated controllers and hello to elegantly organized business logic!\n\n## 💡 Why Actionable?\n\nEver found yourself writing the same business logic patterns over and over? Controllers getting too fat? Service classes becoming a mess? **Actionable is here to save the day!**\n\n```php\n// ❌ The old way - Fat controllers, messy code\nclass UserController extends Controller\n{\n    public function register(Request $request)\n    {\n        // Validation logic...\n        // User creation logic...\n        // Email sending logic...\n        // Queue processing...\n        // 200 lines later...\n    }\n}\n\n// ✅ The Actionable way - Clean, focused, reusable\nRegisterUser::run($userData);\n```\n\n## 🎯 Key Features\n\n### 🏃‍♂️ **Runnable Actions**\nExecute business logic with a single, expressive call. No more hunting through service classes!\n\n### 📬 **Dispatchable Actions**\nSeamlessly queue your actions for background processing. It's as easy as changing `run()` to `dispatch()`!\n\n### 💡 **Smart Code Completion**\nFull IntelliSense support with auto-completion for runnable and dispatchable actions across all major IDEs.\n\n### 🔄 **Smart Array Conversion**\nConvert between arrays and objects effortlessly with our powerful attribute system. Perfect for APIs!\n\n### 🛠️ **Artisan Generators**\nScaffold Actions and DTOs in seconds with our intuitive Artisan commands.\n\n### 🎨 **Flexible Attributes**\nFine-tune serialization behavior with elegant attributes like `#[FieldName]`, `#[DateFormat]`, and more!\n\n## 📦 Installation\n\n```bash\ncomposer require lumosolutions/actionable\n```\n\nThat's it! No configuration needed. Start writing better code immediately.\n\n## 🚀 Quick Start\n\n### Your First Action in 30 Seconds\n\n**1️⃣ Generate an action:**\n```bash\nphp artisan make:action SendWelcomeEmail\n```\n\n**2️⃣ Define your logic:**\n```php\nclass SendWelcomeEmail\n{\n    use IsRunnable;\n\n    public function handle(string $email, string $name): void\n    {\n        Mail::to($email)-\u003esend(new WelcomeEmail($name));\n    }\n}\n```\n\n**3️⃣ Use it anywhere:**\n```php\nSendWelcomeEmail::run('user@example.com', 'John Doe');\n```\n\n**That's it!** Clean, testable, reusable. 🎉\n\n## 📚 Documentation\n\n### ⚡ Actions\n\nActions are the heart of your application's business logic. They're single-purpose classes that do one thing and do it well.\n\n#### Basic Actions\n\n```php\nclass CalculateOrderTotal\n{\n    use IsRunnable;\n\n    public function handle(Order $order): float\n    {\n        return $order-\u003eitems-\u003esum(fn($item) =\u003e $item-\u003eprice * $item-\u003equantity);\n    }\n}\n\n// Usage\n$total = CalculateOrderTotal::run($order);\n```\n\n#### Queueable Actions\n\nNeed background processing? Just add a trait!\n\n```php\nclass ProcessVideoUpload\n{\n    use IsRunnable, IsDispatchable;\n\n    public function handle(Video $video): void\n    {\n        // Heavy processing logic here\n    }\n}\n\n// Run synchronously\nProcessVideoUpload::run($video);\n\n// Or dispatch to queue\nProcessVideoUpload::dispatch($video);\n\n// Use a specific queue\nProcessVideoUpload::dispatchOn('video-processing', $video);\n```\n\n### 🗄️ Data Transfer Objects (DTOs)\n\nDTOs with superpowers! Convert between arrays and objects seamlessly.\n\n```php\nclass ProductData\n{\n    use ArrayConvertible;\n\n    public function __construct(\n        public string $name,\n        public float $price,\n        public int $stock\n    ) {}\n}\n\n// From request data\n$product = ProductData::fromArray($request-\u003evalidated());\n\n// To API response\nreturn response()-\u003ejson($product-\u003etoArray());\n```\n\n### 🏷️ Powerful Attributes\n\n#### `#[FieldName]` - API-Friendly Naming\n\n```php\nclass UserResponse\n{\n    use ArrayConvertible;\n\n    public function __construct(\n        #[FieldName('user_id')]\n        public int $userId,\n        \n        #[FieldName('full_name')]\n        public string $fullName\n    ) {}\n}\n```\n\n#### `#[DateFormat]` - Date Formatting Made Easy\n\n```php\nclass EventData\n{\n    use ArrayConvertible;\n\n    public function __construct(\n        #[DateFormat('Y-m-d')]\n        public DateTime $date,\n        \n        #[DateFormat('H:i')]\n        public DateTime $startTime\n    ) {}\n}\n```\n\n#### `#[ArrayOf]` - Handle Nested Objects\n\n```php\nclass ShoppingCart\n{\n    use ArrayConvertible;\n\n    public function __construct(\n        #[ArrayOf(CartItem::class)]\n        public array $items\n    ) {}\n}\n```\n\n#### `#[Ignore]` - Keep Secrets Secret\n\n```php\nclass UserAccount\n{\n    use ArrayConvertible;\n\n    public function __construct(\n        public string $email,\n        \n        #[Ignore]\n        public string $password,\n        \n        #[Ignore]\n        public string $apiSecret\n    ) {}\n}\n```\n\n### 🛠️ Artisan Commands\n\nGenerate boilerplate with style:\n\n```bash\n# Basic action\nphp artisan make:action ProcessOrder\n\n# Queueable action\nphp artisan make:action SendNewsletter --dispatchable\n\n# Invokable action\nphp artisan make:action CalculateShipping --invokable\n\n# DTO with array conversion\nphp artisan make:dto OrderData\n\n# Enable Smart Code Completion\nphp artisan ide-helper:actions\n```\n\n## 🌟 Real-World Examples\n\n### E-commerce Order Processing\n\n```php\n// The DTO\nclass OrderData\n{\n    use ArrayConvertible;\n\n    public function __construct(\n        #[FieldName('customer_email')]\n        public string $customerEmail,\n        \n        #[ArrayOf(OrderItemData::class)]\n        public array $items,\n        \n        #[FieldName('discount_code')]\n        public ?string $discountCode = null\n    ) {}\n}\n\n// The Action\nclass ProcessOrder\n{\n    use IsRunnable, IsDispatchable;\n\n    public function handle(OrderData $orderData): Order\n    {\n        $order = DB::transaction(function () use ($orderData) {\n            $order = Order::create([...]);\n            \n            // Process items\n            foreach ($orderData-\u003eitems as $item) {\n                $order-\u003eitems()-\u003ecreate([...]);\n            }\n            \n            // Apply discount\n            if ($orderData-\u003ediscountCode) {\n                ApplyDiscount::run($order, $orderData-\u003ediscountCode);\n            }\n            \n            return $order;\n        });\n\n        // Queue follow-up actions\n        SendOrderConfirmation::dispatch($order);\n        UpdateInventory::dispatch($order);\n        \n        return $order;\n    }\n}\n\n// Usage - It's this simple!\n$orderData = OrderData::fromArray($request-\u003evalidated());\n$order = ProcessOrder::run($orderData);\n```\n\n### User Registration Flow\n\n```php\nclass RegisterUser\n{\n    use IsRunnable;\n\n    public function handle(RegistrationData $data): User\n    {\n        $user = CreateUser::run($data);\n        \n        SendWelcomeEmail::dispatch($user);\n        NotifyAdmins::dispatch($user);\n        TrackRegistration::dispatch($user, $data-\u003ereferralSource);\n        \n        return $user;\n    }\n}\n```\n\n## 🤲 Contributing\n\nWe love contributions! Whether it's a bug fix, new feature, or improvement to our docs - we appreciate it all.  Please feel free to submit a pull request or open an issue.\n\n## 📄 License\n\nActionable is open-sourced software licensed under the [MIT license](LICENSE).\n\n## 💬 Support \u0026 Community\n\n- 🐛 **Found a bug?** [Open an issue](https://github.com/LumoSolutions/actionable/issues)\n- 💡 **Have an idea?** [Start a discussion](https://github.com/LumoSolutions/actionable/discussions)\n- 🔒 **Security concern?** Email me at richard@lumosolutions.org\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**Built with ❤️ by [Lumo Solutions](https://lumosolutions.org)**\n\n*Actionable: Making Laravel development more enjoyable, one action at a time.*\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flumosolutions%2Factionable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flumosolutions%2Factionable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flumosolutions%2Factionable/lists"}