すべての人に挨拶! 現在のプロジェクトではYii2を使用しており、開発プロセス中にモジュールとして何らかのエンティティが必要でした。
Yii2はすでにモジュラーシステムを実装していますが、1つのモジュールが1つのモジュールを別のモジュールに表示することを許可せず、ウィジェットの使用も適切ではないという1つの欠点があります。 これはビューの一部であり、たとえば着信POST要求などのアクションを処理する方法がわかりません(ただし、一度はいくつかの松葉杖でウィジェットを使用していました)。
任意のコントローラーで使用できるネストされたモジュールを含むモジュールを作成します。
その結果、以下が得られます。
- モジュールはどのコントローラーにも表示されます
- モジュールの状態(オン/オフ)とその位置のデータベースによる管理
- インバウンド処理
- 特定のページにのみ必要なモジュールを出力します
このアイデアは、CMS OpenCartのモジュールの実装に取り入れられています。
giiを介して
ディスパッチャモジュールを作成し、
web.php構成にプラグインすることから始めましょう
'dispatcher' => [ 'class' => 'app\modules\dispatcher\Module', ],
モジュールディレクトリ
app \ modules \ dispatcherで、 \ yii \ base \ Moduleを継承する
BasicModuleクラスを作成します。
BasicModule.php <?php namespace app\modules\dispatcher; use app\modules\dispatcher\components\Controller; use app\modules\dispatcher\models\LayoutModule; class BasicModule extends \yii\base\Module { const POSITION_HEADER = 'header'; const POSITION_FOOTER = 'footer'; const POSITION_LEFT = 'left'; const POSITION_RIGHT = 'right'; static protected $positions = [ self::POSITION_HEADER, self::POSITION_FOOTER, self::POSITION_LEFT, self::POSITION_RIGHT, ]; public $defaultControllerName = 'DefaultController'; public $modulesDir = 'catalog'; private $_modulesNamespace; public $modulePath; public function init() { parent::init(); $this->_setModuleVariables(); $this->loadModules(); } protected function loadModules() { $handle = opendir($this->modulePath); while (($dir = readdir($handle)) !== false) { if ($dir === '.' || $dir === '..') { continue; } $class = $this->_modulesNamespace . '\\' . $dir . '\\Module'; if (class_exists($class)) { $this->modules = [ $dir => [ 'class' => $class, ], ]; } } closedir($handle); } public function run($layout, array $positions = []) { $model = $this->findModel($layout, $positions); $data = []; foreach ($model as $item) { if ($controller = $this->findModuleController($item['module'])) { $data[$item['position']][] = \Yii::createObject($controller, [$item['module'], $this])->index(); } } return $data; } public function findModel($layout_id, array $positions = []) { if (empty($positions)) { $positions = self::$positions; } return LayoutModule::find() ->where([ 'layout_id' => $layout_id, 'position' => $positions, 'status' => LayoutModule::STATUS_ACTIVE, ])->orderBy([ 'sort_order' => SORT_ASC ])->asArray()->all(); } public function findModuleController($name) { $className = $this->_modulesNamespace . '\\' . $name . '\controllers\\' . $this->defaultControllerName; return is_subclass_of($className, Controller::class) ? $className : null; } private function _setModuleVariables() { $class = new \ReflectionClass($this); $this->_modulesNamespace = $class->getNamespaceName() . '\\' . $this->modulesDir; $this->modulePath = dirname($class->getFileName()) . DIRECTORY_SEPARATOR . $this->modulesDir; } }
BasicModuleからモジュールクラス
アプリ\モジュール\ディスパッチャー\モジュールを継承します
Module.php <?php namespace app\modules\dispatcher; class Module extends BasicModule { public function init() { parent::init(); } }
移行を作成して実行します。
移行 public $table = '{{%layout_module}}'; public function safeUp() { $tableOptions = null; if ($this->db->driverName === 'mysql') { $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; } $this->createTable($this->table, [ 'id' => $this->primaryKey(), 'layout_id' => $this->integer()->notNull(),
作成したテーブルに入力します。
INSERT INTO `layout_module` VALUES ('1', '1', 'test', '1', 'header', '1'); INSERT INTO `layout_module` VALUES ('2', '1', 'test', '1', 'footer', '1'); INSERT INTO `layout_module` VALUES ('3', '1', 'test', '1', 'left', '1');
ディスパッチャモジュールのルートで、
componentsディレクトリを追加し
ます 。
\ yii \ web \ Controllerを継承するクラス
Controllerを作成し
ます 。 その中で
render()メソッドを再定義し
ます 。
Controller.php <?php namespace app\modules\dispatcher\components; class Controller extends \yii\web\Controller { public function render($view, $params = []) { $controller = str_replace('Controller', '', $this->module->defaultControllerName); $path = '@app/modules/dispatcher/' . $this->module->modulesDir . '/' . $this->id . '/views/' . $controller; return $this->getView()->render($path . '/' . 'index', $params, $this); } }
カタログディレクトリを
ディスパッチャモジュールのルートに追加します-これはモジュールの親ディレクトリです。
次に、最初のモジュールを作成します。その構造は、通常の
Yii2モジュールと
変わりません。
テストディレクトリを作成し、その中に
Moduleクラスを作成します。
Module.php <?php namespace app\modules\dispatcher\catalog\test; class Module extends \yii\base\Module { public $controllerNamespace = 'app\modules\dispatcher\catalog\test\controllers'; }
controllersディレクトリを作成し、その中に
app \ modules \ dispatcher \ components \ Controllerから継承するクラス
DefaultControllerを作成し
ます 。
Defaultcontroller.php <?php namespace app\modules\dispatcher\catalog\test\controllers; use app\modules\dispatcher\components\Controller; class DefaultController extends Controller { public function index() { return $this->render('index'); } }
重要:モジュールが機能するには、常にapp \ modules \ dispatcher \ components \ Controllerから継承し、 indexメソッドを含む必要がありますビュー/デフォルトビューとビューファイルのディレクトリを作成します。
index.php <div class="dispatcher-default-index"> <p> You may customize this page by editing the following file:<br> <code><?= __FILE__ ?></code> </p> </div>
ほとんどすべての準備が整いました。モジュールを呼び出すだけです。 これを行うには、
app \ modules \ dispatcher \ componentsに Dispatcherコンポーネントを作成し
ます 。
Dispatcher.php <?php namespace app\modules\dispatcher\components; use yii\base\Object; class Dispatcher extends Object { private $_module; public $module = 'dispatcher'; public function __construct(array $config = []) { parent::__construct($config); $this->_module = \Yii::$app->getModule($this->module); } public function modules($layout, array $positions = []) { return $this->_module->run($layout, $positions); } }
次に、
web.phpでコンポーネントを接続する必要があります
'dispatcher' => [ 'class' => 'app\modules\dispatcher\components\Dispatcher', ],
コンポーネントをコンポーネント配列に追加する必要があることを忘れないでください。任意のコントローラー(例えば
SiteController )で、
actionIndex()メソッドに追加します
$modules = \Yii::$app->dispatcher->modules(1); return $this->render('index', compact('modules'));
ビュー内のモジュール
ビュー/サイト/ index.phpの出力に位置を追加するだけです。
index.php <?php $this->title = 'My Yii Application'; use app\modules\dispatcher\Module; ?> <div class="site-index"> <?php if (isset($modules[Module::POSITION_HEADER])) { ?> <div class="row"> <?php foreach ($modules[Module::POSITION_HEADER] as $module) { echo $module; } ?> </div> <?php } ?> <div class="jumbotron"> <h1>Congratulations!</h1> <p class="lead">You have successfully created your Yii-powered application.</p> <p><a class="btn btn-lg btn-success" href="http://www.yiiframework.com">Get started with Yii</a></p> </div> <div class="body-content"> <div class="row"> <div class="col-lg-4"> <h2>Heading</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> <p><a class="btn btn-default" href="http://www.yiiframework.com/doc/">Yii Documentation »</a></p> </div> <div class="col-lg-4"> <h2>Heading</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> <p><a class="btn btn-default" href="http://www.yiiframework.com/forum/">Yii Forum »</a> </p> </div> <div class="col-lg-4"> <h2>Heading</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> <p><a class="btn btn-default" href="http://www.yiiframework.com/extensions/">Yii Extensions »</a></p> </div> </div> </div> <?php if (isset($modules[Module::POSITION_FOOTER])) { ?> <div class="row"> <?php foreach ($modules[Module::POSITION_FOOTER] as $module) { echo $module; } ?> </div> <?php } ?> </div>
モジュールの公式ドキュメントをお勧めし
ます 。
すべてのコードは
GitHubに投稿され
ます 。