Hello community.
As the topic says, is there a module managment tool in Yii2 ?
I found this one for yii1 : github . com/antonCPU/app-manager
I need something to manage modules/components on the fly for my project.
Big Thanks
Mafi
Hello community.
As the topic says, is there a module managment tool in Yii2 ?
I found this one for yii1 : github . com/antonCPU/app-manager
I need something to manage modules/components on the fly for my project.
Big Thanks
Mafi
I implementation about that
<?php
namespace app\components\base;
use app\models\Modules;
use yii\base\component;
use yii\base\BootstrapInterface;
use yii\base\InvalidParamException;
use yii\helpers\Json;
class ModuleLoader extends Component implements BootstrapInterface
{
private $_enabledModules = [];
public function bootstrap($application)
{
//Load Enabled Modules Form storage
$this->_enabledModules = Modules::find()->enabled()->asArray()->indexBy('module')->all();
foreach ($this->_enabledModules as $module) {
//TODO Add config for each modules from DB
\Yii::trace('Load Module:' . $module['module'], 'application.ModuleLoader');
$config = Json::decode($module['config']);
if (json_last_error() && !isset($config['configure'])) {
throw new InvalidParamException($module['module'] . ' config is not valid json ');
}
$application->setModule($module['module'], $config['configure']);
}
}
public function getEnabledModules()
{
return $this->_enabledModules;
}
/**
* Load Modules Dir Name From Modules Path(@app/modules)
*
* @return array
*/
public function getModuleDirs()
{
$modulePath = $this->getModulePath();
$dirs = (array)glob($modulePath . '*');
$moduleDirs = array();
foreach ($dirs as $dir) {
if (is_dir($dir)) {
$d = basename($dir);
$moduleDirs[] = $d;
}
}
return $moduleDirs;
}
/**
* Get the Modules List which in modules Dir that not in db
*
* @return array
*/
public function unInstallModules()
{
$unInstall = [];
$install = $this->installedModules();
$allModules = $this->getModuleDirs();
if (!$install) {
return $this->loadModuleConfig($allModules);
}
foreach ($allModules as $module) {
if (!isset($install[$module])) {
$unInstall[] = $module;
}
}
return $this->loadModuleConfig($unInstall);
}
/**
* Get All Modules From DB
*
* @return array|\yii\db\ActiveRecord[]
*/
public function installedModules()
{
return Modules::find()->asArray()->indexBy('module')->all();
}
private function loadModuleConfig($modules)
{
$return = [];
if (!$modules) {
return [];
}
foreach ($modules as $module) {
$return[$module] = $this->getModuleConfig($module);
}
return $return;
}
public function getModulePath()
{
return \Yii::getAlias('@app/modules') . DIRECTORY_SEPARATOR;
}
public function getModuleClass($module)
{
$class = "\\app\\modules\\" . $module . "\\Module";
if (class_exists($class)) {
return $class;
}
\Yii::trace(
'Load Module Config : The module class not exist:' . $module['module'] . '',
'application.ModuleLoader'
);
return false;
}
public function getModuleConfig($module)
{
if (!$module) {
return [];
}
$class = $this->getModuleClass($module);
if ($class && method_exists($class, 'moduleConfig')) {
return $class::moduleConfig();
}
return [];
}
public function install($module)
{
$class = $this->getModuleClass($module);
if (!$class) {
throw new InvalidParamException($module . "'s Modules.php not exist");
}
return $class::install();
}
public function uninstall($module)
{
$class = $this->getModuleClass($module);
if (!$class) {
throw new \HttpInvalidParamException($module . "'s Modules.php not exist");
}
return $class::uninstall();
}
}
if you config in your config file like this:
[
'bootstrap' => ['log', 'moduleLoader'],
'components' => [
......
'moduleLoader' => [
'class' => 'app\components\base\ModuleLoader'
]
......
]
]
the database modules:
CREATE TABLE `modules` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`module` varchar(30) NOT NULL DEFAULT '' COMMENT 'module id',
`name` varchar(20) NOT NULL DEFAULT '' COMMENT 'module name',
`url` varchar(100) NOT NULL DEFAULT '' COMMENT '',
`version` varchar(50) NOT NULL DEFAULT '' COMMENT 'version',
`icon` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'icon for the module',
`category` varchar(30) NOT NULL DEFAULT '' COMMENT '',
`description` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`config` text COMMENT '模块配置,数组形式',
`sort` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT ' ',
`disabled` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'status for module',
`created_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '',
`updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
now create the model:
<?php
namespace app\models;
use app\models\query\ModulesQuery;
use Yii;
use yii\base\InvalidParamException;
use yii\behaviors\TimestampBehavior;
use yii\helpers\Json;
/**
* This is the model class for table "phpci_modules".
*
* @property integer $id
* @property string $module
* @property string $name
* @property string $url
* @property string $version
* @property integer $icon
* @property string $category
* @property string $description
* @property string $config
* @property integer $sort
* @property integer $disabled
* @property string $created_at
* @property string $updated_at
*/
class Modules extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return '{{%modules}}';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['module', 'name', 'description'], 'required'],
[['icon', 'sort', 'disabled', 'created_at', 'updated_at'], 'integer'],
[['module', 'category'], 'string', 'max' => 30],
[['name'], 'string', 'max' => 20],
[['url'], 'string', 'max' => 100],
[['version'], 'string', 'max' => 50],
[['description'], 'string', 'max' => 255],
[['config'], 'safe']
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'module' => 'module id',
'name' => 'module name',
'url' => 'url',
'version' => 'version',
'icon' => 'icon for module',
'category' => 'category',
'description' => 'desc',
'config' => 'config',
'sort' => 'sort',
'disabled' => 'status',
'created_at' => 'created',
'updated_at' => 'updated',
];
}
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
public static function find()
{
return new ModulesQuery(get_called_class());
}
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if (is_array($this->config) || !$this->config) {
$this->config = $this->config ? Json::encode($this->config) : Json::encode([]);
}
if ($insert) {
$this->disabled = 1;
}
return true;
}
return false;
}
public function getConfig($configKey = null)
{
if (!$this->config) {
return false;
}
$config = Json::decode($this->config);
if ($configKey === null) {
return $config;
}
if (isset($config[$configKey])) {
return $config[$configKey];
}
return [];
}
public function install()
{
//TODO uninstall 和 install 合并冗代码
$transaction = self::getDb()->beginTransaction();
try {
if ($this->save(false) && Yii::$app->moduleLoader->install($this->module)) {
Yii::trace($this->module . '安装成功', 'application.ModuleInstall');
$transaction->commit();
return true;
} else {
$transaction->rollBack();
return '安装失败()';
}
} catch (InvalidParamException $e) {
$transaction->rollBack();
Yii::error($e->getMessage(), 'application.ModuleInstall');
return $e->getMessage();
} catch (\Exception $e) {
$transaction->rollBack();
Yii::error($e->getMessage(), 'application.ModuleInstall');
return $e->getMessage();
}
}
public function uninstall()
{
//TODO uninstall 和 install 合并冗代码
$transaction = self::getDb()->beginTransaction();
try {
if ($this->delete() && Yii::$app->moduleLoader->uninstall($this->module)) {
Yii::trace($this->module . '卸载成功', 'application.ModuleInstall');
$transaction->commit();
return true;
} else {
$transaction->rollBack();
return '卸载失败';
}
} catch (InvalidParamException $e) {
$transaction->rollBack();
Yii::error($e->getMessage(), 'application.ModuleInstall');
return $e->getMessage();
} catch (\Exception $e) {
$transaction->rollBack();
Yii::error($e->getMessage(), 'application.ModuleInstall');
return $e->getMessage();
}
}
}
last you must crate a config file named config.php in your module dir :
<?php
return [
//module basic info
'module' => 'phploc',
'name' => 'PHPLoc',
'description' => 'phploc is a tool for quickly measuring the size and analyzing the structure of a PHP project.',
'version' => '1.0',
'category' => '',
'url' => '',
//module config info
'config' => [
'configure' => [
'class' => 'app\modules\phploc\Module',
],
'setting' => [
'route' => 'phploc/default/index',
]
],
];
now you can set config your module like this in module.php
<?php
namespace app\modules\phploc;
class Module extends \yii\base\Module
{
public $controllerNamespace = 'app\modules\phploc\controllers';
public function init()
{
parent::init();
// custom initialization code goes here
}
public static function install()
{
return true;
}
public static function uninstall()
{
return true;
}
public static function moduleConfig()
{
if (is_file(__DIR__ . DIRECTORY_SEPARATOR . 'config.php')) {
return require(__DIR__ . DIRECTORY_SEPARATOR . 'config.php');
}
return [];
}
}
Big thanks, i will try it!