dem1-off/laravel-modular 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

dem1-off/laravel-modular

Composer 安装命令:

composer require dem1-off/laravel-modular

包简介

Modular architecture tools for Laravel — DDD modules that promote to standalone packages with zero code churn

README 文档

README

Latest Version on Packagist Total Downloads PHP Version License

Modular architecture tooling for Laravel. DDD modules (Domain / Application / Infrastructure) that are real Composer packages from day one, so any module can be promoted to a standalone package with zero code churn.

Highlights

  • Attribute-driven wiring — declare bindings and listeners with #[Bind] and #[Listen], or let an implementation auto-bind itself with #[Provides] (Symfony-style autoconfigure for Laravel modules). Config, migrations, views and routes load by convention, so the common provider is empty.
  • Fast by designmodule:cache compiles discovery and attributes into one PHP file (zero reflection, zero filesystem scanning at runtime), wired into php artisan optimize.
  • A designed-in promotion path — module namespaces never change, so moving a module into its own repo is a Composer change, not a refactor.
  • Familiar layout — works with the Modules/ directory, module.json, modules_statuses.json, and module_path() conventions, so existing projects interoperate.

A module at a glance

#[Bind(PostRepositoryInterface::class, EloquentPostRepository::class)]
#[Listen(ChapterPublished::class, SendDigest::class)]
final class BlogServiceProvider extends ModuleServiceProvider {}

Installation

composer require dem1-off/laravel-modular
php artisan vendor:publish --tag=modules-config

config/modules.php uses conventional module config keys (namespace, paths, statuses_file), so an existing modular project migrates without editing modules.

Creating a module

php artisan make:module Blog

Produces a promotion-ready package:

Modules/Blog/
├── composer.json          # type: laravel-module, PSR-4 Modules\Blog\
├── module.json            # module manifest
├── config/blog.php
├── database/{migrations,factories,seeders}/
├── resources/views/
├── src/{Domain,Application,Infrastructure}/
│   └── Infrastructure/Providers/BlogServiceProvider.php
└── tests/

Configuring a module

Convention loads, attributes wire. Config, migrations, views and routes load automatically when their folders exist. Declare container bindings and listeners with attributes:

use Dem1Off\LaravelModular\Module\Attributes\Bind;
use Dem1Off\LaravelModular\Module\Attributes\Listen;
use Dem1Off\LaravelModular\Module\ModuleServiceProvider;

#[Bind(PostRepositoryInterface::class, EloquentPostRepository::class)]
#[Bind(FeedCache::class, RedisFeedCache::class, singleton: true)]
#[Listen(ChapterPublished::class, SendDigest::class)]
final class BlogServiceProvider extends ModuleServiceProvider {}

Need more than attributes? Override register()/boot() and call the parent — it's a normal Laravel provider. See the docs.

Performance

Attributes reflect in development. In production, php artisan module:cache compiles discovery and attributes into one PHP file — a request does zero reflection and zero filesystem scanning. It's wired into php artisan optimize.

Runtime API

use Dem1Off\LaravelModular\Facades\Modules;

Modules::all();           // every module, keyed by name
Modules::enabled();       // only enabled ones
Modules::find('Blog');    // ModuleDescriptor|null
Modules::isEnabled('Blog');
Modules::path('Blog');    // absolute path

module_path('Blog', 'resources/views'); // path helper

Customising behaviour

A module provider is a normal Laravel ServiceProvider. For anything beyond attributes, override register()/boot() and call the parent:

public function boot(): void
{
    parent::boot();

    Livewire::component('blog.feed', Feed::class);
}

Keep anything proprietary (navigation, mailing, metrics, …) in your application, invoked from the module's boot() — never inside this package.

Promoting a module to a standalone package

Because a module is already a Composer package and its namespace (Modules\Blog\) never changes, promotion is mechanical:

  1. Move the directory to its own git repo

    git subtree split --prefix=Modules/Blog -b blog-module
    # push that branch to a new repo, or copy Modules/Blog out
  2. Point the app at it via Composer — swap the path entry for a VCS/version constraint in the root composer.json:

    // before — local development
    "repositories": [{ "type": "path", "url": "Modules/*" }],
    "require": { "acme/blog-module": "*" }
    
    // after — promoted package
    "repositories": [{ "type": "vcs", "url": "git@github.com:acme/blog-module.git" }],
    "require": { "acme/blog-module": "^1.0" }
  3. composer update acme/blog-module — done.

No namespace changes, no provider rewrites: Laravel package auto-discovery reads extra.laravel.providers from the module's own composer.json, exactly as it did in-app. Tests, static-analysis config, and the module_path() helper all keep working because the module's internal layout is unchanged.

Tip: develop with "type": "path" + "url": "Modules/*" and "symlink": true so in-app modules and promoted packages behave identically during development.

License

MIT.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-20

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固