Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Base Laravel Package

micro-module/base

Micro-Module Base provides a lightweight foundation for building modular Laravel applications, with core abstractions for module registration, service providers, and lifecycle management so you can split features into self-contained packages with minimal boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require micro-module/base

Because the package sits at 0 stars / 0 dependents and its API is not yet stabilized, pin an exact version so a patch release cannot silently change base-class signatures:

"micro-module/base": "0.1.*"

First places to look (in order)

  1. composer.json → extra.laravel.providers to confirm whether the service provider is auto-discovered.
  2. src/ for the base classes you are expected to extend — typically a base ServiceProvider, an abstract Module/BaseModule class, and a manifest/registry class.
  3. config/ for the module-discovery and path settings.
  4. README.md and any tests/ directory — with a package this young, the tests are often the most accurate documentation of intended usage.

Publish config if the tag exists

php artisan vendor:publish --provider="MicroModule\Base\Providers\BaseServiceProvider"

First use case — scaffold one module

The intended entry point for a package like this is: you define a module directory (usually under app/Modules or modules/), give it a class that extends the package's base module class, and the base library handles registration of that module's routes, migrations, views, translations and service providers. Start by creating a single "Hello" module and confirming it boots, before splitting anything real into modules.

// app/Modules/Blog/BlogModule.php
namespace App\Modules\Blog;

use MicroModule\Base\Module;   // confirm exact FQCN from src/

class BlogModule extends Module
{
    public function name(): string
    {
        return 'blog';
    }
}

Then verify the module is discovered:

php artisan about

Implementation Patterns

One module = one folder with a fixed shape. The value of a base library like this is convention over configuration. Keep every module structurally identical (Providers/, Http/Controllers/, routes/, database/migrations/, resources/views/) so the base provider can resolve paths by convention instead of you wiring each one.

Base service provider subclassing. Rather than writing loadRoutesFrom / loadMigrationsFrom / loadViewsFrom / mergeConfigFrom by hand in every module, each module's provider should extend the base provider and only declare its name and optional hooks:

class BlogServiceProvider extends ModuleServiceProvider
{
    protected string $module = 'blog';

    public function register(): void
    {
        parent::register();          // base wiring: config, bindings, singletons
        $this->app->bind(BlogRepository::class, EloquentBlogRepository::class);
    }
}

Keep parent::register() first — any bindings the base class performs (repositories, module registry, event dispatcher) are usually prerequisites for what you override.

Cross-module communication. Modules should never new each other's concrete classes. Use contracts in the base library (or your own Contracts/ namespace) and bind implementations in the consuming module's provider. Emit events for one-way notifications; use interfaces for synchronous needs. This keeps modules extractable into separate Composer packages later — which is the whole point of "micro-module".

Register modules explicitly in config, not by filesystem scan. Discovery-by-scan is convenient in development and a liability in production (a stray folder changes boot order). Prefer an ordered list:

// config/micro-module.php
return [
    'modules' => [
        'core' => \App\Modules\Core\CoreModule::class,
        'blog' => \App\Modules\Blog\BlogModule::class,
    ],
    'cache' => env('MICRO_MODULE_CACHE', true),
];

Testing. Unit-test a module without booting the whole app by instantiating its classes directly. For integration, boot only the modules under test — most base libraries of this type expose a way to swap the module list in a test case's setUp(), either via config override or a dedicated trait.

When to reach for it. If your app has more than ~3 modules with real boundaries (billing, catalog, notifications) and you want consistent registration, this is the right layer. If you have two modules, plain service providers are less machinery.

Gotchas and Tips

Treat it as pre-1.0. With a single release, 0 stars and no dependents, the API can move. Wrap your usage: extend the package's base classes in your own App\Support\Module abstract class, so a breaking change is a one-file fix instead of a sweep across every module.

Namespace / autoload collisions. Modules that aren't yet separate Composer packages need PSR-4 entries. If the base library assumes a namespace root (e.g. Modules\), a mismatch with your composer.json autoload map produces class-not-found errors that look like discovery failures. Run composer dump-autoload after adding any module and check composer dump-autoload -o behaves the same.

Boot order matters. Modules that register routes or bind interfaces consumed by others must load earlier. If you see "target class does not exist" only in some modules, it is almost certainly ordering — make the config list explicit and ordered, and never rely on directory scan order.

Cache the manifest in production. If the base library caches module metadata, a stale cache after deploy is the most common "my changes do nothing" bug. Build a deploy step:

php artisan config:cache
php artisan route:cache
php artisan module:cache   # verify exact command name in src/Console

And the corresponding clear when debugging locally.

Missing routes/views inside a module. The base provider usually resolves paths relative to the module class file's directory. Move a module folder and paths break silently (View [blog::index] not found). The view:clear + route:clear pair resolves most of these; if not, dump the registered paths via a one-off php artisan tinker call into the base class's path accessor.

Config merge semantics. mergeConfigFrom is shallow for nested arrays — if your module publishes a nested config and the base library merges only top-level keys, nested defaults vanish. Explicitly array_merge_recursive in the module provider when nesting matters.

Debugging tip. Since documentation is thin, php artisan about and php artisan list are your fastest way to see which providers and commands the package actually registers. Read the src/Providers/ and src/Console/ directories directly; for a package this size you can read the entire source in under ten minutes and that will beat any guesswork.

Extension points to favor. Prefer the base library's documented hooks (abstract methods to implement, events to listen for) over overriding internal methods. With no dependents, there is no community precedent for which internals are safe — anything private or marked @internal should be considered unstable.

Vendor it if it stalls. A single-release package can go unmaintained. If you rely on it, fork the repo into your org's VCS and require your fork by path or VCS repository, keeping upstream as a remote so you can pull fixes if they appear.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package