定制 baconfy/core 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

baconfy/core

Composer 安装命令:

composer require baconfy/core

包简介

Core module system for Baconfy.

README 文档

README

Core

Tests Latest Version License Total Downloads PHP Version

The module system at the heart of the Baconfy ecosystem. It lets Composer packages register themselves as application modules — with a name, label, icon, entry route, navigation tree and visibility rules — so the application shell can discover and render them with zero configuration.

This package is pure PHP and has no opinion about your frontend. It is consumed by baconfy/interface, which turns registered modules into a launcher and sidebar.

Requirements

  • PHP 8.3+
  • Laravel 11, 12 or 13

Installation

composer require baconfy/core

The service provider is auto-discovered. A ModuleRegistry singleton becomes available in the container.

Creating a module

A module is a regular Laravel package whose service provider extends ModuleProvider. Three methods are required:

use Baconfy\Core\ModuleProvider;

class NotesServiceProvider extends ModuleProvider
{
    public function name(): string
    {
        return 'notes';
    }

    public function label(): string
    {
        return __('Notes');
    }

    public function icon(): string
    {
        return 'notebook-pen';
    }
}

That's it. The module is registered automatically when the provider boots.

Your boot() stays yours

ModuleProvider does not touch the boot() method — registration happens through a provider booting callback. Write your boot exactly the way you would in any Laravel package:

public function boot(): void
{
    Route::middleware('web')
        ->prefix($this->name())
        ->name($this->name().'.')
        ->group(fn () => $this->loadRoutesFrom(__DIR__.'/../routes/web.php'));

    $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
}

Conventions

The module name is the universal key. By convention it is also:

Concern Convention Override
Entry route {name}.index routeName(): ?string
Visibility gate gate named {name}, if defined can(): ?string
Launcher position order = 100 order(): int
JS page namespace extra.baconfy.module in composer.json — (must match name())

Visibility

Three rules, checked in order:

  1. Explicit can() — the module is visible only to users allowed by that gate.
  2. Convention gate — if a gate named after the module exists (Gate::define('notes', ...)), it decides. The application controls access without the module knowing.
  3. Otherwise — the module is public, including for guests.

Manifest validation

If the package's composer.json declares a Baconfy manifest, the module key must match the provider's name():

{
    "extra": {
        "baconfy": {
            "module": "notes"
        }
    }
}

A mismatch throws ManifestMismatchException at boot — configuration errors die early and loudly. The manifest is optional: headless modules (no frontend pages) don't need one.

Navigation

Modules may expose a navigation tree by overriding navigation():

use Baconfy\Core\Navigation;

public function navigation(): ?iterable
{
    return [
        Navigation::make(__('All notes'))->icon('list')->route('notes.index'),

        Navigation::make(__('Archive'))->children(
            Note::distinctYears()->map(
                fn (int $year) => Navigation::make((string) $year)
                    ->route('notes.archive', ['year' => $year]),
            ),
        ),

        Navigation::make(__('Settings'))
            ->route('notes.settings')
            ->can('notes.settings'),
    ];
}
  • Trees nest to any depth through children() (accepts arrays or Collections).
  • Items with can() are pruned for users who fail the gate — and for guests.
  • Route-less items act as group headings; a group whose children were all pruned disappears with them.
  • Returning null (the default) means the module has no sidebar navigation at all.

Lazy by design

label() and navigation() are never called during boot. They are wrapped in closures and evaluated only at serialization time, per request. This means:

  • labels translate to the locale of the current request, not the boot locale;
  • navigation may safely query the database without taxing every request;
  • long-running runtimes (Octane) never freeze stale values.

Consuming the registry

use Baconfy\Core\ModuleRegistry;

$registry = app(ModuleRegistry::class);

$registry->all();                       // every module, sorted by order then name
$registry->visibleFor($user);           // only what this user may see
$registry->get('notes');                // a single module

Sharing modules with an Inertia frontend is a one-liner:

Inertia::share('baconfy.modules', fn () => app(ModuleRegistry::class)
    ->visibleFor(auth()->user())
    ->map->toArray(auth()->user()));

Each module serializes to:

{
    "name": "notes",
    "label": "Notes",
    "icon": "notebook-pen",
    "url": "https://app.test/notes",
    "order": 100,
    "navigation": [
        { "label": "All notes", "icon": "list", "url": "https://app.test/notes", "children": [] }
    ]
}

url is null when the entry route doesn't exist; navigation is null when the module defines none.

Testing

composer test   # pest
composer lint   # pint + phpstan

The suite runs against PHP 8.3/8.4/8.5 × Laravel 11/12/13 in CI.

License

MIT.

统计信息

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

GitHub 信息

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

其他信息

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

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固