edalzell/laravel-features

Self-contained feature modules for Laravel with auto-registration of routes, migrations, views, events, and seeders

Maintainers

Package info

github.com/edalzell/laravel-features

pkg:composer/edalzell/laravel-features

Statistics

Installs: 161

Dependents: 0

Suggesters: 0

Stars: 18

Open Issues: 0

v0.6.0 2026-07-01 01:06 UTC

This package is auto-updated.

Last update: 2026-07-01 01:07:31 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Add self-contained features to your Laravel app or package, including all resources/routes/etc.

.
└── app/
...
└── features/
  │   └── MyGreatFeature/
  │       ├── config/
  │       │   └── my-great-feature.php
  │       ├── database/
  │       │   ├── factories
  │       │   ├── migrations
  │       │   └── seeders
  │       ├── resources
  │       ├── routes
  │       └── src/
  │           ├── Models
  │           ├── ...
  │           └── ServiceProvider.php

Each feature behaves like a mini Laravel app. The following are auto-registered and booted:

Phase What
Register Config, Migrations, Routes, Seeders, Views
Boot Config publishing, Listeners, Policies, Seeders

Installation

You can install the package via composer:

composer require edalzell/laravel-features

Usage

To add a new feature in your app:

php artisan make:feature MyGreatFeature

To add feature to a package:

php artisan make:feature MyGreatFeature the-dev/my-package

This creates a ServiceProvider that extends FeatureServiceProvider — everything is auto-registered with no further code required.

Option 1: Extend FeatureServiceProvider

The zero-friction path. Your provider gets boot() and register() for free:

class MyGreatFeatureServiceProvider extends FeatureServiceProvider
{
    // nothing needed — everything is auto-registered
}

Override any of these protected methods to customise behaviour:

protected function configFileName(): string      // default: kebab-cased feature name
protected function configGroup(): string         // default: '' (no subdirectory)
protected function configPublishHandle(): string // default: kebab-cased feature name
protected function featuresPath(): string        // default: base_path('features/FeatureName')

Option 2: Standalone Features object

When your provider already extends another class, wire up Features directly:

use Edalzell\Features\Features;

class MyServiceProvider extends SomeOtherProvider
{
    private Features $features;

    public function __construct(Application $app)
    {
        parent::__construct($app);

        $this->features = (new Features($this))
            ->path($this->featuresPath())
            ->name($this->name())
            ->configFileName($this->configFileName())
            ->configGroup($this->configGroup())
            ->configPublishHandle($this->configPublishHandle());
    }

    public function boot(): void
    {
        $this->features->bootFeature();
    }

    public function register(): void
    {
        $this->features->registerFeature();
    }
}

Features derives the path, namespace, and app from your provider via reflection. You only need to call the fluent setters when overriding the defaults.

Auto-discovering features

Use the HasFeatures trait in any service provider to automatically register all features from a directory. In your app, add it to AppServiceProvider:

use Edalzell\Features\Concerns\HasFeatures;

class AppServiceProvider extends ServiceProvider
{
    use HasFeatures;

    public function register(): void
    {
        $this->registerFeatures(app_path('../features'), 'App\\Features');
    }
}

For a package, add it to your package's main service provider:

use Edalzell\Features\Concerns\HasFeatures;

class MyPackageServiceProvider extends ServiceProvider
{
    use HasFeatures;

    public function register(): void
    {
        $this->registerFeatures();
    }
}

In a package, registerFeatures() defaults to looking in <package-root>/features/ and registering providers under YourPackage\Features\FeatureName\ServiceProvider. Pass explicit arguments to override either default:

$this->registerFeatures('/path/to/features', 'My\\Namespace\\Features');

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

License

The MIT License (MIT). Please see License File for more information.