laravel modules 使用数据库进行模块管理以及 filement modules 自定义模块管理器 | laravel china 社区-金年会app官方网
laravel modules 使用数据库进行模块管理
laravel modules
默认是使用文件系统进行进行模块管理的,如果本地开发是没有问题的,但是如果放到线上,由于模块信息默认是在项目根目录的,那么就要把根目录的这个文件进行权限配置。背离了我们只放开 public/storage 目录权限的目标(这里描述的的可能不准确),所以下面只有两个选择
- 把模块信息文件放到 public 或者 storage 下。
- 采用数据库进行模块管理
在这里我选择使用数据库进行模块管理的操作,创建 model
和迁移文件 php artisan make:model moduleactivator -m
编辑迁移文件
use illuminate\database\migrations\migration;
use illuminate\database\schema\blueprint;
use illuminate\support\facades\schema;
return new class extends migration
{
/**
* run the migrations.
*/
public function up(): void
{
schema::create('module_activators', function (blueprint $table) {
$table->id();
$table->string('module_name')->unique();
$table->boolean('module_status');
$table->timestamps();
});
}
/**
* reverse the migrations.
*/
public function down(): void
{
schema::dropifexists('module_activators');
}
};
增加两个字段 module_name
和 module_status
分别表示模块名称和模块状态
执行迁移 php artisan migrate
。
接下来修改配置文件modules.php
如果没有文件,记得 publish 一下就可以了
'activators' => [
'file' => [
'class' => fileactivator::class,
'statuses-file' => base_path('modules_statuses.json'),
],
'database' => [
'class' => databaseactivator::class,
'model' => moduleactivator::class,
]
],
'activator' => 'database',
activators
增加 database
配置,activator
修改为 database
。database
配置中的 model
就是刚才创建的 moduleactivator
模型。database
配置中的 class
是 databaseactivator
数据库管理器,我们自己创建,代码如下
namespace app\activators;
use nwidart\modules\contracts\activatorinterface;
use nwidart\modules\module;
use illuminate\container\container;
use illuminate\database\eloquent\model;
class databaseactivator implements activatorinterface
{
/**
* 模块管理的模型
* @var class-string $modelclass
*/
private string $modelclass;
public function __construct(container $app)
{
$this->modelclass = $app['config']['modules.activators.database.model'];
}
/**
* enables a module
*/
public function enable(module $module): void
{
$this->setactivebyname($module->getname(), true);
}
/**
* disables a module
*/
public function disable(module $module): void
{
$this->setactivebyname($module->getname(), false);
}
/**
* determine whether the given status same with a module status.
*/
public function hasstatus(module|string $module, bool $status): bool
{
$name = $module instanceof module ? $module->getname() : $module;
$modulerecord = $this->modelclass::where('module_name', $name)->first();
if ($modulerecord) {
return boolval($modulerecord['module_status']) === $status;
} else {
return $status === false;
}
}
/**
* set active state for a module.
*/
public function setactive(module $module, bool $active): void
{
$this->setactivebyname($module->getname(), $active);
}
/**
* sets a module status by its name
*/
public function setactivebyname(string $name, bool $active): void
{
$this->modelclass::upsert(['module_name' => $name, 'module_status' => $active], ['module_name'], ['module_status']);
}
/**
* deletes a module activation status
*/
public function delete(module $module): void
{
$modulerecord = $this->modelclass::where('module_name', $module->getname())->first();
if ($modulerecord) {
$modulerecord->delete();
}
}
/**
* deletes any module activation statuses created by this class.
*/
public function reset(): void
{
$this->modelclass::truncate();
}
}
database
配置中的 model
, 就是为了可以更换为你自己的模块状态管理模型。
这个类实现了 activatorinterface
接口。
这样模块的激活状态就会存储在数据库中了。可以使用 laravel modules
的 artisan
命令来测试模块的激活状态。
filament-module 自动注册模块,只激活启用模块中的 plugin
是 filament
中的一个插件,可以搭配 laravel modules
来进行开发,每一个模块都是一个 filament
插件。方便我们模块化的组织系统。
但是默认的配置filament-modules.auto-register-plugins
存在一个问题,如果打开这个配置,那么所有的模块中的 plugin
都会被注册到 filament
中,即使这个模块没有被激活。
这显然不是我们想要的,我们只希望激活的模块中的 plugin
被注册到 filament
中。
但是如果把这个配置设置为 false
又得自己手动注册管理,会更麻烦。
所以我们需要一个自定义的模块管理器,来管理模块的激活状态,并且根据模块的激活状态来注册 plugin
。
namespace app\plugin;
use coolsam\modules\facades\filamentmodules;
use coolsam\modules\modulesplugin as basemodulesplugin;
use nwidart\modules\facades\module;
class modulesplugin extends basemodulesplugin
{
protected function getmoduleplugins(): array
{
if (! config('filament-modules.auto-register-plugins', false)) {
return [];
}
$enabledmodules = module::allenabled();
$pluginpaths = [];
foreach ($enabledmodules as $module) {
$path = $module->getpath() . directory_separator . 'app' . directory_separator . 'filament' . directory_separator . '*plugin.php';
$modulepluginpaths = glob($path);
if(is_array($modulepluginpaths)) {
$pluginpaths = array_merge($pluginpaths, $modulepluginpaths);
}
}
return collect($pluginpaths)
->map(fn ($path) => filamentmodules::convertpathtonamespace($path))
->filter()->toarray();
// return collect($enabledmodules)->map(function ($module) {
// $path = $module->getpath() . directory_separator . 'app' . directory_separator . 'filament' . directory_separator . $module->getname() . 'plugin.php';
// if(file_exists($path)) {
// return filamentmodules::convertpathtonamespace($path);
// }
// return null;
// })->filter()->toarray();
}
}
注意我注释的部分,一般我个人都会使用我注释部分的代码。因为我的规划是每个模块都只有一个插件,且插件名跟模块名称统一(这样略显死板)。这样注释部分的速度会更快。未注释的部分,单纯是为了防止模块有多个插件的情况。喜欢用哪个就自己开放关闭就可以了。
这个类继承了 use coolsam\modules\modulesplugin
,并重写了 getplugins
方法。这个方法用于获取所有激活模块的插件类。
这样修改panelprovider
中的 plugin 方法 ->plugin(modulesplugin::make())
, 参数设定为上面那个自定义类就可以了,这样就可以自动注册已激活模块的插件了。
本作品采用《cc 协议》,转载必须注明作者和本文链接
这头像我以为是超哥