...

понедельник, 17 августа 2015 г.

[Из песочницы] Yii environment. Наследования и переопределение конфгнов

Хочу рассказать вам про интересный опыт, с которым я столкнулся на своей последней работе. Нужна была гибкая система Environment-ов. После некоторого времени экспериментов я таки добился идеального варианта. Перейдем сразу к делу.

В protected я создал environment.php c такими вот 2я классами:

environment.php
class Environment
{
        /**
         *
         */
        const PRODUCTION = 10;
        /**
         *
         */
        const STAGING = 20;
        /**
         *
         */
        const TESTING = 30;
        /**
         *
         */
        const DEVELOPMENT = 40;

        /**
         * @var int
         */
        protected static $current;

        /**
         * @var
         */
        private static $currentObj;

        /**
         *
         */
        public static function instance()
        {
                if(!self::$currentObj)
                {
                        self::$currentObj = new self();
                }
                return self::$currentObj;
        }

        /**
         * @param int $ENV
         * @return bool
         */
        public function set($ENV = Environment::DEVELOPMENT)
        {
                if(self::$current)
                {
                        return false;
                }

                if(isset($_GET['DEBUG']))
                {
                        $this->setEnvironment($_GET['DEBUG']);

                        $_SESSION['systemEnvironment'] = $_GET['DEBUG'];

                }
                elseif(isset($_SESSION['systemEnvironment']) and $_SESSION['systemEnvironment'] !== 'off')
                {
                        $this->setEnvironment($_SESSION['systemEnvironment']);

                }
                else
                {
                        self::$current = $ENV;

                }
                return true;
        }


        /**
         * @return int
         */
        public static function getCurrent()
        {
                return self::$current;
        }


        /**
         * @param $level
         */
        private function setEnvironment($level)
        {
                switch($level)
                {
                        case 'PRODUCTION':
                                self::$current = self::PRODUCTION;
                                break;
                        case 'STAGING':
                                self::$current = self::STAGING;
                                break;
                        case 'TESTING':
                                self::$current = self::TESTING;
                                break;
                        case 'DEVELOPMENT':
                                self::$current = self::DEVELOPMENT;
                                break;
                        case 'off':
                                if(isset($_SERVER['ENVIRONMENT']))
                                {
                                        self::$current = constant('Environment::' . strtoupper($_SERVER['ENVIRONMENT']));
                                }
                                $_SESSION['systemEnvironment'] = null;
                                break;

                }
        }

}


/**
 * Class EnvironmentUtils
 */
class EnvironmentUtils extends Environment
{
        /**
         * @param $rootDirectory
         * @param $fileName
         * @return string
         */
        public static function getConfigFile($rootDirectory, $fileName)
        {
                $fileLink = $rootDirectory . '/config/';
                switch(parent::$current)
                {
                        case Environment::DEVELOPMENT:
                                $fileLink .= 'Development/';
                                break;
                        case Environment::PRODUCTION:
                                $fileLink .= 'Production/';
                                break;
                        case Environment::STAGING:
                                $fileLink .= 'Staging/';
                                break;
                        case Environment::TESTING:
                                $fileLink .= 'Testing/';
                                break;

                }
                return $fileLink . $fileName;
        }
}



После чего немного изменил структуру файлов в папке config:
Вот дерево файлов.

├── Base
│   ├── API
│   │   ├── Morpher.php
│   │   └── XmlRpcClient.php
│   ├── Common
│   │   ├── Daemon.php
│   │   ├── Email.php
│   │   └── Filtrator.php
│   ├── console.php
│   ├── DB
│   │   ├── 1c.php
│   │   └── BaseConnect.php
│   ├── main.php
│   ├── routes.php
├── Development
│   ├── cli.php
│   ├── DB
│   │   ├── 1c.php
│   │   ├── BaseConnect.php
│   └── Web.php
├── Production
│   ├── cli.php
│   ├── DB
│   │   ├── 1c.php
│   │   ├── BaseConnect.php
│   │   ├── Sape.php
│   └── Web.php
├── Staging
│   ├── cli.php
│   ├── DB
│   │   ├── 1c.php
│   │   ├── BaseConnect.php
│   └── Web.php
└── Testing
├── cli.php
├── DB
│   ├── 1c.php
│   └── BaseConnect.php
└── Web.php


В Base/Web.php находится базовый конфиг. Из серии:
return [
        'basePath'          => PROTECTED_PATH,
        'name'              => 'MyApp',
        'theme'             => 'classic',
        'language'          => 'ru',
        'defaultController' => 'user/login',
        // preloading 'log' component
        // autoloading model and component classes
        'aliases'           => [
                'bootstrap' => PROTECTED_PATH.'extensions/bootstrap',
                // change this if necessary
        ],
        'preload'           => [
                'log',
                'bootstrap'
        ],
        'import'            => [
                'application.models.*',
        ]


Тоже самое в cli.php. А вот в Production/Web.php чтоб не копировать постоянно какой то параметр если меняешь, я сделал так:
return CMap::mergeArray(include(PROTECTED_PATH.'config/Base/main.php'),
        [
                'components'=>
                [
                        'db'         => include(dirname(__FILE__) . '/DB/BaseConnect.php'),
                        'db1c'       => include(dirname(__FILE__) . '/DB/1c.php')
                ]
        ]
);


Таким образом я просто перезаписываю настройки бд, ну или то, что мне нужно. Теперь самое интересное. Подгрузка. index.php.

P.S.: У меня в проекте ядро yii тянется через composer:

index.php
define("PROTECTED_PATH",realpath(dirname(__FILE__)).'/protected/');
if(!file_exists(PROTECTED_PATH.'vendor/autoload.php'))
{
        die('autoload.php not found. Composer update!');
}

require_once(PROTECTED_PATH.'vendor/autoload.php');
require_once(PROTECTED_PATH.'environment.php');

if(isset($_SERVER['HTTP_ORIGIN']))
{
        if(in_array($_SERVER['HTTP_ORIGIN'],[....]))
        {
              header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
              header('Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE, PUT');
              header('Access-Control-Max-Age: 1728000');
              header('Access-Control-Allow-Credentials: true');
              header("Access-Control-Allow-Headers: access-token, expiry, token-type, uid, client");
              header("Access-Control-Expose-Headers: access-token, expiry, token-type, uid, client");
        }       
}


if($_SERVER['REQUEST_METHOD'] == 'OPTIONS')
{
        header("HTTP/1.0 204 No Content");
        die();
}

Environment::instance()->set(Environment::DEVELOPMENT);

switch(Environment::getCurrent())
{
        case Environment::DEVELOPMENT:

                define('YII_DEBUG', false);
                define('YII_SKIP_AUTH', true);
                define('YII_KERNEL_LOG', true);
                define('DISPLAY_ERROR_TRACE', true);
                define('YII_TRACE_LEVEL', 0);
                define('MINIFY_INTERFACE', false);

                error_reporting(E_ALL);
                ini_set('display_errors','On');
                break;
        case Environment::PRODUCTION:

                define('YII_DEBUG', false);
                define('YII_SKIP_AUTH', false);
                define('YII_KERNEL_LOG', false);
                define('DISPLAY_ERROR_TRACE', false);
                define('YII_TRACE_LEVEL', 3);
                define('MINIFY_INTERFACE', true);

                error_reporting(0);
                ini_set('display_errors','Off');
                break;
        case Environment::STAGING:

                define('YII_DEBUG', true);
                define('YII_SKIP_AUTH', false);
                define('YII_KERNEL_LOG', true);
                define('DISPLAY_ERROR_TRACE', true);
                define('YII_TRACE_LEVEL', 0);

                error_reporting(E_ALL);
                ini_set('display_errors','On');
                break;
}

/** @noinspection PhpUndefinedClassInspection */
Yii::$enableIncludePath = true; //For init Yii kernel
$config = EnvironmentUtils::getConfigFile(PROTECTED_PATH,'Web.php');

//Other constants
define('DATE_FORMAT', 'Y/m/d');
define('STATUS_NOACTIVE', 0);
define('STATUS_ACTIVE', 1);
date_default_timezone_set("Europe/Kiev");

/** @noinspection PhpUndefinedClassInspection */
Yii::createWebApplication($config)->run();




По аналогии сделано и в cli.php. Система себя отлично зарекомендовала.

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Комментариев нет:

Отправить комментарий