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
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.