yii2-webapplicationend Organize directories for applications with front-end and back-end for yii2

  1. Requirements
  2. Usage
  3. Resources

another classic project directory for your project .

this is a portable version for yii1- WebApplicationEnd to yii2 .

Requirements

yii2

Usage

config your web.php file as following :

'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'language'=>'zh-CN',

    'bootstrap' => [
        'log',
    ],
    'as modulePathChanger'=>[
        'class' => 'app\behaviors\WebApplicationEndBehavior',
    ],

the extension code :

<?php
/**
 * User: yiqing
 */

namespace app\behaviors;


use Yii ;
use yii\base\Module ;
use yii\base\Application;
use yii\base\BootstrapInterface;

// used by WebApplicationEndBehavior class
use yii\base\Behavior;
use yii\base\Event;

class WebApplicationEndBehavior extends Behavior implements BootstrapInterface
{
    /**
     * @var string
     */
    public $eventId = 'changeModulePaths';
    /**
     * Bootstrap method to be called during application bootstrap stage.
     * @param Application $app the application currently running
     */
    public function bootstrap($app)
    {
        $app->attachBehavior($this->eventId, new WebApplicationEndBehavior());

    }


    // Web application end's name.
    private $_endName;

    // Getter.
    // Allows to get the current -end's name
    // this way: Yii::app()->endName;
    public function getEndName()
    {
        return $this->_endName;
    }

    // Run application's end.
    public function runEnd($name)
    {
        $this->_endName = $name;

        // Attach the changeModulePaths event handler
        // and raise it.
        Yii::$app->on($this->eventId, [$this, 'changeModulePaths']);
        //  $this->onModuleCreate = array($this, 'changeModulePaths');
        $this->owner->trigger($this->eventId, new Event(array('sender' => $this->owner)));

        $this->owner->run(); // Run application.
    }


    /**
     * for backward compatible to the old version
     * or Module instances are being initialized.
     * This event should be raised when Application
     *
     * @param Event $event
     */
    public function onModuleCreate($event)
    {
        $this->owner->trigger($this->eventId, $event);
    }

    
    /**
     * onModuleCreate event handler.
     * A sender must have controllerPath and viewPath properties.
     *
     * @param Event|Module $eventOrModule
     */
    public  function changeModulePaths( $eventOrModule)
    {
        /** @var   Application|Module $app   */
        $appOrModule = null ;
        if($eventOrModule instanceof Event){
            $appOrModule = $eventOrModule->sender ;
        }else{
            $appOrModule = $eventOrModule ;
        }


        // custom initialization code goes here
        $appEnd = Yii::$app->getEndName() ;
        $appOrModule->controllerNamespace = str_replace('\controllers', sprintf('\controllers\%s',$appEnd),$appOrModule->controllerNamespace);

        $appOrModule->viewPath .= DIRECTORY_SEPARATOR.$this->_endName;
    }
}

We usually have backend and frontend functionality . the official directory structure is yii2-app-advanced project boilerplate template .

when we have multiple modules , you will have to separate the frontend and backend parts to different top directories (frontend and backend ) . say we will use a module which is developed by third party , a module is a logic unit of system . but you will have to separate the directory as two parts for deploy ,one for frontend another for backend .

the WebApplicationEndBehavior make your module as a logic and physical unit . the front and the admin functionality are mainly reflected in " controllers " and "views" , they will share the others things (models , components etc ..) .

the front entry script :

<?php

// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

$config = require(__DIR__ . '/../config/web.php');

$app = (new yii\web\Application($config));

// Yii::setAlias('@year',Yii::getAlias('@app/year')) ;

$app->runEnd('front');

the backend entry point (admin.php):

<?php

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');


/** @var Composer\Autoload\ClassLoader() $loader */
$loader = require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

$config = require(__DIR__ . '/../config/back.php');


$app = (new yii\web\Application($config));
// $app = (new admin\web\Application($config));

$app->runEnd('back');

the back.php file will config the WebApplicationEnd same as the front config file (normally is the app/config/web.php)

now you will have two separate entry points for your system ,one is frontend application ,another is backend application .

modify your directory structure :

webroot/
        web/
          ...
          admin.php
          index.php
    
        components/
           ..
        controllers/
            /front
                SiteController.php
            /back
                SiteController.php
        views/
            /front
                /layouts
                    column1.php
                    column2.php
                    main.php
                /site
                   /pages
                       about.php
                   contact.php
                   error.php
                   index.php
                   login.php
            /back
                /layouts
                    main.php
                /site
                    error.php
                    index.php
                    login.php

the different from the normal parts is the controller namespace ,you should have to notice it :

namespace app\controllers\front;

use Yii;
...

class SiteController extends Controller 
{
  ...
}

// back end controller have different namespace

namespace app\controllers\back;

use Yii;
...

class SiteController extends Controller 
{
  ...
}

now if you want to apply it to the module , just do it like this .

this is my user module :

namespace app\modules\user;

use Yii ;

class Module extends \yii\base\Module
{
    public $controllerNamespace = 'app\modules\user\controllers';

    public function init()
    {
        parent::init();

  
        if(\Yii::$app instanceof \yii\web\Application){
            Yii::$app->changeModulePaths($this);
        }
    }
}

the controllerNamespace property should be given as normal .

for more detail knowledge you can refer here : Organize directories for applications with front-end and back-end using WebApplicationEnd behavior

bonus : your will have the gii support naturally

Resources

external resources for this extension

1 0
1 follower
0 downloads
Yii Version: 2.0
License: BSD-2-Clause
Category: Others
Developed by: yiqing95
Created on: Oct 24, 2014
Last updated: 10 years ago

Related Extensions