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

Module Api Laravel Package

slick/module-api

Slick Module API gives Laravel applications a modular foundation for building maintainable APIs. Package endpoints into self-contained modules with their own routes, controllers, resources, and middleware, keeping large APIs organized, versionable, and easy to extend or remove.

View on GitHub
Deep Wiki
Context7

Getting Started

slick/module-api remains primarily a contract-only package: it ships interfaces (and small helpers) that a Slick module implements. It still contains no runtime kernel and no bootstrap logic. However, v0.4.0 adds slick/di as a dependency and changes ConsoleModuleInterface::configureConsole() to receive a ContainerInterface, so console-aware modules can build commands through the dependency container.

Minimal setup:

composer require slick/module-api

Steps to get productive in the first 10 minutes:

  1. Read composer.json for the PHP constraint, PSR-4 prefix, version tag, and the new slick/di dependency. Confirm the exact ContainerInterface FQCN in src/ (likely under Slick\Di\).
  2. Open src/ and read every interface. The primary contract is still the module contract. Also read ConsoleModuleInterface; its configureConsole(ContainerInterface $container) signature is the v0.4.0 change.
  3. Look at a real first-party Slick module. For console behavior, find one implementing ConsoleModuleInterface to see how it uses the injected container to construct and configure commands.
  4. Scaffold your module in your own package:
namespace Acme\Blog;

use Slick\ModuleApi\ModuleInterface; // verify exact FQCN in src/

final class BlogModule implements ModuleInterface
{
    // Use the IDE's "Implement methods" — the installed interface is the spec.
}

For a console-aware module:

namespace Acme\Blog;

use Slick\ModuleApi\ConsoleModuleInterface;
use Slick\Di\ContainerInterface; // verify exact FQCN in src/

final class BlogConsoleModule implements ConsoleModuleInterface
{
    public function configureConsole(ContainerInterface $container): void
    {
        // Build/register console commands using the container.
    }
}

The first realistic use case is unchanged: you are building a reusable Slick package (router extension, admin panel, persistence layer, console tooling) and want the host application to discover and wire it without editing the framework.

Implementation Patterns

Contract-first dependency direction. Your module package should require slick/module-api and avoid requiring the Slick kernel. If your module implements ConsoleModuleInterface or exposes ContainerInterface in its own public signatures, be aware that slick/module-api now pulls in slick/di; consider requiring slick/di explicitly when your package directly type-hints it.

Module-as-service-provider. The dominant pattern remains: the module acts as a PSR-11 service provider, returning a callable or definition set that receives the container and registers services. Keep the module class thin — wiring only — and put real behavior in ordinary services resolved from the container.

final class BlogModule implements ModuleInterface
{
    public function services(): callable
    {
        return function ($container): void {
            $container->set(BlogRepository::class, fn () => new BlogRepository(/* deps */));
        };
    }
}

Console integration is an optional interface. Implement ConsoleModuleInterface only when your module adds commands. Use configureConsole(ContainerInterface $container) to resolve dependencies and construct commands through the container rather than using globals, static factories, or manual new chains.

final class BlogConsoleModule implements ConsoleModuleInterface
{
    public function configureConsole(ContainerInterface $container): void
    {
        $container->set('blog.command.sync', fn () => new SyncCommand(
            $container->get(BlogRepository::class)
        ));
    }
}

One module, one capability. Resist the god module. Split persistence, routing, web, and console concerns into separate modules; the host app composes them. This keeps config keys namespaced and optional interfaces meaningful.

Separate the interface implementation from service wiring. A common refinement is XModule (module identity and config defaults) plus XServiceProvider (service graph registration). It makes unit-testing wiring trivial because you can pass a stub container.

Test against the interface, not the framework. Mock the container and assert your module registers the expected service IDs. For console modules, call configureConsole() with a fake container and assert the expected commands/services are registered. Reserve full-kernel tests for end-to-end module loading.

Config defaults belong in the module. Return defaults from the module and let the host merge them. Namespace keys under your module name to avoid collisions.

Version pinning matters more now. v0.4.0 changes the console configuration signature. Pin slick/module-api to ^0.4 if you rely on the container-aware configureConsole(); keep older pins only if you deliberately support pre-v0.4 modules. Because the package is pre-1.0, treat minor bumps as potentially breaking at interface boundaries.

Gotchas and Tips

  • It is an API package, not a running module. Requiring it still gives you no executable behavior. For concrete examples, install the framework or a first-party module alongside it.
  • v0.4.0 is a breaking change for console modules. ConsoleModuleInterface::configureConsole() now receives a ContainerInterface. Existing implementations with the old no-argument signature will fatal. Regenerate method stubs from the installed interface rather than copying old examples.
  • New dependency: slick/di. The package now depends on it to expose ContainerInterface. If your own module's public signatures reference that interface, declare slick/di directly in your package rather than relying only on transitive resolution.
  • Interface mismatch is still the #1 failure mode. If your module is silently skipped, check that it actually implements the expected interface, that the FQCN in the module list matches, and that the autoloader is current.
  • Signature drift across majors and pre-1.0 minors. Method names and return types on the module contract have changed between Slick generations. Always let the IDE regenerate stubs from the installed interface.
  • Prefer optional interfaces over fattening the base contract. Console behavior belongs in ConsoleModuleInterface; do not add console methods to the core module contract, forcing every implementation to stub them.
  • Don't leak implementation into the API. The package itself now depends on slick/di, but that is not license to add your own concrete or third-party dependencies to interfaces others must implement.
  • Debugging module loading comes down to: is the class autoloadable (composer dump-autoload), is it listed in the application's module configuration, does the instance satisfy the expected instanceof check, and — for console modules — did configureConsole() receive and use the container correctly?
  • Composer pitfalls after upgrading. Run composer update slick/module-api slick/di and composer dump-autoload after switching to v0.4.0. A stale lockfile or autoload map can leave you with the old interface signature and confusing “interface not found” or fatal signature errors.
  • Release-note quirk: the announcement text may still say v0.3.1 while the changelog points to v0.4.0. Verify the installed tag with composer show slick/module-api when diagnosing signature changes.
  • Extension point worth knowing: the module contract is where you hang your package's public integration surface. Document service IDs, config keys, command names, and any required container bindings as part of your module's own contract; module-api itself will not describe your specific module.
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.
skyraptor/chatter
edlugz/sasapay
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