Skip to content

ironflow-framework/ironflow

Repository files navigation

IronFlow Logo

A Powerful Modular Framework for Laravel 12+

Latest Version Total Downloads License Stars


About IronFlow

IronFlow is a complete rewrite of the popular modular framework for Laravel. It enables you to build highly modular, maintainable, and scalable applications by organizing your code into isolated, self-contained modules.

Why IronFlow?

  • True Modularity: Each module is completely isolated with its own routes, views, migrations, and services
  • Service Exposure: Modules can expose services to other modules with fine-grained access control
  • Smart Lazy Loading: Hybrid lazy loading optimizes boot time and memory usage
  • Dependency Management: Automatic dependency resolution with circular dependency detection
  • Manifest Caching: Lightning-fast module discovery in production
  • Testing Framework: Comprehensive ModuleTestCase for testing your modules
  • Laravel 12+ Ready: Built for modern Laravel with PHP 8.2+ features

Installation

Existing Laravel Project

composer require ironflow/ironflow
php artisan ironflow:install

New Project

composer create-project ironflow/skeleton my-project
cd my-project
php artisan ironflow:install

Quick Start

1. Create Your First Module

php artisan ironflow:module:make Blog

This generates a complete module structure:

modules/Blog/
├── BlogModule.php                # Main module class
├── BlogServiceProvider.php       # Laravel service provider (optional)
├── Http/Controllers/             # Controllers
├── Models/                       # Eloquent models
├── Services/                     # Business logic
├── Resources/views/              # Blade templates
├── Database/Migrations/          # Database migrations
├── routes/web.php                # Routes
└── config/blog.php               # Configuration

2. Define Your Module

namespace Modules\Blog;

use IronFlow\Core\{BaseModule, ModuleMetaData};
use IronFlow\Interfaces\{ViewableInterface, RoutableInterface};

class BlogModule extends BaseModule implements 
    ViewableInterface, 
    RoutableInterface
{
    protected function defineMetadata(): ModuleMetaData
    {
        return new ModuleMetaData(
            name: 'Blog',
            version: '1.0.0',
            description: 'Blog module with posts and comments',
            author: 'Your Name',
            dependencies: [],
            provides: ['BlogService'],
            path: __DIR__,
            namespace: __NAMESPACE__,
        );
    }

    public function bootModule(): void
    {
        // Boot logic here
    }

    public function expose(): array
    {
        return [
            'blog' => Services\BlogService::class,
        ];
    }

    // Implement ViewableInterface and RoutableInterface methods...
}

3. Discover and Boot Modules

# Discover all modules
php artisan ironflow:discover

# List modules
php artisan ironflow:list --detailed

# Cache for production
php artisan ironflow:cache

4. Use Exposed Services

use IronFlow\Facades\Anvil;

// Resolve a service from any module
$blogService = Anvil::getService('blog.blog');
$posts = $blogService->getPublishedPosts();

// In controllers via dependency injection
class DashboardController extends Controller
{
    public function __construct(
        private BlogService $blogService
    ) {}

    public function index()
    {
        return view('dashboard', [
            'posts' => $this->blogService->getPublishedPosts()
        ]);
    }
}

Key Features

Module Lifecycle

UNREGISTERED → REGISTERED → PRELOADED → BOOTING → BOOTED
                                ↓
                            FAILED/DISABLED

Each module goes through a well-defined lifecycle with automatic state management.

Service Exposure

Public Services (accessible by all):

public function expose(): array
{
    return [
        'blog' => Services\BlogService::class,
        'post-repo' => Repositories\PostRepository::class,
    ];
}

Linked Services (restricted access):

public function exposeLinked(): array
{
    return [
        'admin-service' => [
            'class' => Services\BlogAdminService::class,
            'allowed' => ['Admin', 'Dashboard'],
        ],
    ];
}

Lazy Loading

Configure what to load eagerly vs lazily:

'lazy_loading' => [
    'enabled' => true,
    'eager' => ['routes', 'views', 'config'],
    'lazy' => ['services', 'events', 'commands'],
]

Dependency Management

Declare dependencies and IronFlow handles the rest:

protected function defineMetadata(): ModuleMetaData
{
    return new ModuleMetaData(
        name: 'Comments',
        version: '1.0.0',
        dependencies: [
          'Blog' => '^1.0', // Comptible with 1.x
          'Users' => '~1.5' // Only 1.5.x version
        ],
        // ...
    );
}

IronFlow automatically:

  • Resolves boot order
  • Detects circular dependencies
  • Validates missing dependencies

Module Versioning

IronFlow adheres to Semantic Version (semver).

Contraintes Supportées

  • ^1.2.3 - Caret : >=1.2.3 <2.0.0
  • ~1.2.3 - Tilde : >=1.2.3 <1.3.0
  • >=1.0.0 - Supérieur ou égal
  • <2.0.0 - Inférieur
  • 1.2.3 - Version exacte
  • * - Toute version
  • ^1.0 || ^2.0 - OR logique
  • >=1.0 <2.0 - AND logique

Bumper une Version

# Patch (1.2.3 → 1.2.4)
php artisan ironflow:version:bump Blog patch

# Minor (1.2.3 → 1.3.0)
php artisan ironflow:version:bump Blog minor

# Major (1.2.3 → 2.0.0)
php artisan ironflow:version:bump Blog major

# With commit et tag
php artisan ironflow:version:bump Blog minor --commit --tag

Running Tests

IronFlow uses Pest for an elegant testing experience.

# Run all tests
composer test

# Run with coverage
composer test:coverage

# Run in parallel
composer test:parallel

# Run specific test file
./vendor/bin/pest tests/Unit/ModuleMetaDataTest.php

# Run tests with filter
./vendor/bin/pest --filter="permissions"

# Run tests in watch mode
./vendor/bin/pest --watch

Writing Tests

use IronFlow\Testing\ModuleTestCase;

test('my module feature works', function () {
    $module = createTestModule('MyModule');
    
    expect($module->getName())->toBe('MyModule')
        ->and($module->getState())->toBe(ModuleState::UNREGISTERED);
});

Custom Expectations

expect($module)->toBeBooted();
expect($module)->toHaveState(ModuleState::BOOTED);

Interfaces

IronFlow provides several activatable interfaces:

ViewableInterface

Register and manage Blade views:

implements ViewableInterface

RoutableInterface

Register web/API routes:

implements RoutableInterface

MigratableInterface

Manage database migrations:

implements MigratableInterface

ConfigurableInterface

Handle module configuration:

implements ConfigurableInterface

SeedableInterface

Database seeding support:

implements SeedableInterface

ExposableInterface

Expose services to other modules:

implements ExposableInterface

Artisan Commands

Command Description
ironflow:install Install IronFlow in your project
ironflow:discover Discover all modules
ironflow:cache Cache module manifest for production
ironflow:clear Clear module cache
ironflow:module:make {name} Create a new module
ironflow:migrate {module?} Run module migrations
ironflow:list List all registered modules


Example: Blog Module

Complete working example included in the repository:

namespace Modules\Blog;

use IronFlow\Core\{BaseModule, ModuleMetaData};

class BlogModule extends BaseModule implements 
    ViewableInterface, 
    RoutableInterface,
    MigratableInterface,
    ConfigurableInterface
{
    // Define metadata
    protected function defineMetadata(): ModuleMetaData
    {
        return new ModuleMetaData(
            name: 'Blog',
            version: '1.0.0',
            description: 'Complete blog with posts and comments',
            author: 'IronFlow Team',
            dependencies: [],
            provides: ['BlogService', 'PostRepository'],
            path: __DIR__,
            namespace: __NAMESPACE__,
        );
    }

    // Register services
    public function register(): void
    {
        $this->app->singleton(Services\BlogService::class);
        $this->app->bind(Services\PostRepository::class);
    }

    // Boot module
    public function bootModule(): void
    {
        $this->loadTranslations();
    }

    // Expose services
    public function expose(): array
    {
        return [
            'blog' => Services\BlogService::class,
            'post-repository' => Services\PostRepository::class,
        ];
    }

    // Implement interfaces...
}

Features:

  • ✅ Complete CRUD for posts
  • ✅ Comment system
  • ✅ Categories and tags
  • ✅ SEO-friendly URLs
  • ✅ View counters
  • ✅ Blade templates
  • ✅ Migrations and seeders
  • ✅ Full test coverage

Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

Development Setup

git clone https://github.com/ironflow/ironflow.git
cd ironflow
composer install
composer test

Running Tests

# Run all tests
composer test

# Run with coverage
composer test-coverage

# Run static analysis
composer analyse

# Format code
composer format

Requirements

  • PHP 8.2 or higher
  • Laravel 12.0 or higher
  • Composer 2.0 or higher

Security

If you discover any security-related issues, please email ironflow.framework@gmail.com instead of using the issue tracker.


License

IronFlow is open-sourced software licensed under the MIT license.


Credits

IronFlow is developed and maintained by:

Special thanks to:

  • Laravel community for inspiration
  • All contributors and testers
  • Package sponsors

Links


Sponsors

Support IronFlow development by becoming a sponsor.

Become a Sponsor


Made with ❤️ by Aure Dulvresse

Build Modular Laravel Applications with Confidence 🚀

About

Laravel Modular Framework - Build Modular, Scale Fast, Code Clean

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages