【Yii系列】最佳實踐之后台業務框架


緣起

上面的幾章都講概念了,沒有怎么講到實踐的東西,可能會有些枯燥,這很正常的,概念還是需要慢慢啃的,尤其是官網其他的部分,需要狠狠的啃。

什么,你啃不動了?看看官網旁邊的那個在線用戶吧。

你不啃的時候可是有這么多人在啃知識,如果不想以后被這打擊,趕緊學!!!一如當年大學的我,每天夜里都抱着一本《算法導論》在啃一樣,自律相當重要。

這一章我就帶大伙了解一下前兩章的概念有啥用,應用到實際,這是臨門一腳,但是,我總是覺得概念的重要性至少要占70%,臨門的一腳實踐只占30%,望君能體會~

環境

操作系統:OS X EI Capitan

PHP版本:PHP 5.6.30

Yii版本:Yii 2.0

編輯器:PHPStorm

整體框架

首先,我們做這個框架的目的不是給我們自己看的,而是給廣大以后會在這套框架中學習工作的人看的,所以,千萬不能融入自己的思想,要盡可能的通俗易懂,符合一般的邏輯設計。

這張圖是Yii提供給我們的源代碼,首先,為了能夠更能適合我們的業務框架,我決定來簡單的修改一下這個文件結構。

首先,增加業務模塊文件夾modules。用以區分每個不同的業務線。

增加全局基礎類文件夾commons。用以定義application需要使用到的基礎類。

在剛剛創建的Commons文件夾下面創建環境配置文件Config.php和全局方法文件Common.php

Config.php文件用以配置環境和獲取相應環境的配置常量。

Common方法用以定義全局使用到的一些function。【注意,這邊的Common只是用於保存全局的方法,不用做namespace】

 

Common里面比較重要的一個方法就是獲取配置常量方法,后面在很多配置文件中會用到這個方法。

/**
 * 獲取配置文件
 * @param $key string min;
 * @param string $env $string dev:開發環境
 * @return mixed
 */
function Config($key, $val = null)
{
    return \app\commons\Config::get($key, $val);
}

這邊的Config就是我們剛才創建的Config.php文件,具體代碼如下:

<?php
namespace app\commons;

/**
 * 主要實現不同文件配置查找擴展 file.param.param1
 *
 * 文件.數組變量.變量
 */
class Config
{
    const ENV_SIT = 'sit';

    const ENV_PRE = 'pre';

    const ENV_PRD  = 'prd';

    private static $_config = null;

    /**
     * 初始化配置,永遠加載prd, 默認加載sit
     * @param type $configPath
     * @param type $env
     * @throws \Exception
     */
    public static function init($configPath = null, $env = self::ENV_SIT)
    {
        if (!is_dir($configPath)) {
            die('配置目錄不存在');
        }

        $paths[] = $configPath . DIRECTORY_SEPARATOR . self::ENV_PRD;

        switch ($env) {
            case self::ENV_PRE:
                $paths[] = $devconfig = $configPath . DIRECTORY_SEPARATOR . self::ENV_PRE;
                break;
            case self::ENV_SIT:
                if (is_dir($configPath . DIRECTORY_SEPARATOR . self::ENV_SIT)) {
                    $paths[] = $configPath . DIRECTORY_SEPARATOR . self::ENV_SIT;
                }
                break;

            default:
                break;
        }

        static::$_config = \Noodlehaus\Config::load($paths);
    }

    public static function get($key, $default = null)
    {
        return static::$_config->get($key, $default);
    }

    public static function set($key, $value)
    {
        return static::$_config->set($key, $value);
    }
}

另外,我們需要在config文件夾中新增幾個文件,用以區分線上環境【prd】,線上測試環境【pre】,本地開發環境【sit】的配置文件,具體的區分是在config這個文件夾中建立三個對應的目錄,我們來先創建一下。

每個目錄下面建立一個app.php的文件,用以存放app的相關配置常量。

那么,我們如何區分是哪個環境呢,以及如何對應到相應的環境配置常量中去呢。

這邊,我給大伙帶來了一個非常好用的配置第三方組件。Noodlehaus。

github地址:https://github.com/hassankhan/config

我們可以通過composer去下載和自動加載它。

$ composer require hassankhan/config

這里面有個問題,不知道是我學識不足,還是因為這個自動配置文件有問題,這個配置文件加載器始終不讓我來按照文件名去區分配置變量,沒辦法,我暴力的修改了它的一行源代碼。

打開Config的源代碼,vendor/hassankhan/config/src/Config.php

修改構造函數里面的一行代碼

// Try and load file
$this->data = array_replace_recursive($this->data, array($info['filename'] => (array) $parser->parse($path)));

將原本的(array) $parser->parse($path)修改為:array($info['filename'] => (array) $parser->parse($path))即可。

那么,為了保證這邊的代碼能夠在第一時間被加載,以便於配置好環境常量,方便下面的操作,我們需要在入口腳本index.php處加上如下代碼:

//我們每個環境的域名都會在Nginx虛擬配置里面設置,和環境有關
if (empty(getenv('ENV'))) {
    $hostInfo = $_SERVER['HTTP_HOST'];
    $environment = 'prd';
    if (strpos($hostInfo, 'sit') !== false) {
        $environment = 'sit';
    }

    if (strpos($hostInfo, 'pre') !== false) {
        $environment = 'pre';
    }
} else {
    $environment = in_array(getenv('ENV'), array('sit', 'pre', 'prd')) ?
        getenv('ENV') : 'sit';
}

\app\commons\Config::init(__DIR__, $environment);

這段代碼的意思是如果沒有設置環境,我們就根據_SERVER魔術變量中關於HTTP_HOST的值,去判斷我們處理的應用主體處於哪個環境,這是一個靈活的配置,希望大家多思考思考這里面的思想。

但是,這樣一來,我們的入口腳本就會變得很冗長,這是我們不願意看到的,之前也和大家講過,如果覺得在腳本中有過長的代碼該如何,我們在config文件中新建一個bootstrap.php文件來存放上面的代碼,包括include需要的兩個文件,那么整體bootstrap.php的代碼就如下所述:

<?php

ini_set('memory_limit', '128M');

//初始化全局函數
include dirname(__DIR__) . '/Commons/Common.php';
//初始化環境配置
include dirname(__DIR__) . '/Commons/Config.php';

... ... // 上面的代碼

$getDebug = empty($_GET['debug']) ? '' : $_GET['debug'];

bootstrap.php擼完了,我們需要在入口腳本里面做一些小的改變,具體改變如下:

<?php

require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../config/bootstrap.php');

// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', Config('app.debug'));
defined('YII_ENV') or define('YII_ENV', Config('app.env'));

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

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

(new yii\web\Application($config))->run();

上面這邊已經使用了Config,這個方法是Common.php里面的一個方法,調用的就是Config.php里面的get方法,上面已經給大伙演示過啦,如果使用編輯器,應該會直接帶出來,非常方便。

好的,到這邊,我們對整個環境的區分配置就已經完成。現在就可以在app.php里面放置一些變量了~

示例為prd目錄下app.php的配置代碼。

<?php
/**
 * app.php 線上環境項目配置
 */

return [
    'name' => 'fengye-prd',
    'env' => 'prd',
    'debug' => false,
    'log' => [
        'traceLevel' => YII_DEBUG ? 3 : 0,
        'targets' => [
            [
                'class' => 'yii\log\FileTarget',
                'levels' => ['error', 'warning'],
            ],
            [
                'class' => 'yii\log\FileTarget',
                'categories' => ['fengye.info.*'],
                'levels' => ['info'],
                'logVars' => [],
            ]
        ],

    ]
];

其實吧,prd,pre,sit這三個目錄下面還需要配置兩個文件,一個是數據庫配置文件,三個環境要予以區分;還有一個是緩存配置文件,redis,memcache的配置需要三個環境的區分。這會在后面講完數據庫和緩存再和大伙聊聊這邊的配置的事。

對於MVC里的一些在commons里的基類,我們會放在模塊中的MVC一節去講解,看完了整體的一個需要改動的結構,我們再來看看配置文件的改動吧。

配置相關

在Yii系列基礎框架中我們提到過一些基礎的配置,至於如何實施,在那一章節中我們沒有細講,今天,在這一節中,我們來好好看下應用配置有哪些是必要的,哪些是不必要的。

上一節講到,哪些配置是需要區分環境的,下面來講的是通用配置,不需要區分環境的配置。

首先,我們打開配置文件,web.php。

<?php
$params = require(__DIR__ . '/params.php');

之前的章節中提到過,如果配置項中有太多的屬性,需要列舉到一個文件中,使整個代碼結構更清晰。

這邊,我們有幾個配置項需要寫到文件中。

在這段代碼后新增

$rules = require(__DIR__ . '/rules.php');
$aliases = require(__DIR__ . '/aliases.php');
$modules = require(__DIR__.'/modules.php');

順帶在當前目錄中【config】新增幾個php文件:rules.php,aliases.php,modules.php

配置rules:

在Yii系列請求處理那一章中我們講到一個路由規則,在具體的配置中,解析規則一節中我們提到一個rules配置項,使用正則去解析。

'<module:\w+>/<controller:\w+>/<action:\w+>' => '<module>/<controller>/<action>', //模塊相關規則

前面使用戶的URL,后面是解析到對應的路徑,后面是路徑喲,分別是modules、controller、action。

這邊涉及到一個概念,接口版本的區分,比方說之前的老接口不能支持現在的新業務了,建議在接口action名稱后面新增一個版本號,沒有版本號的為默認版本,並在注釋中使用注明,關於接口文檔的修改,我覺得並沒有那么麻煩,使用swagger自動生成在線文檔即可,在修改接口版本的時候,去舊版本注釋里面將舊街口標識為過期即可。

關於swagger的相關內容,我會在后面,Yii系列,第三方工具中詳細講解。

這條規則能滿足大部分的情況,如果每個module下面有很多的子文件夾,就需要來重新定義一些規則啦。具體的看我到時候發布到github的源碼吧。

aliases.php用於配置路徑別名,這邊我們先放一放,以后需要用到的時候再講,這邊暫時用不到。

modules.php文件用於配置各個業務模塊,用以區分業務模塊的代碼區域。

<?php
/**
 * 配置業務模塊
 */
return [
    // 用戶模塊
    'user' => [
        'class' => 'app\modules\user\User',
    ],
    // 商品模塊
    'goods' => [
        'class' => 'app\modules\goods\Goods',
    ],
    // 訂單模塊
    'order' => [
        'class' => 'app\modules\order\Order',
    ],
    // 庫存模塊
    'stock' => [
        'class' => 'app\modules\stock\Stock',
    ],
    // 支付模塊
    'pay' => [
        'class' => 'app\modules\pay\Pay',
    ],
    // 消息模塊
    'message' => [
        'class' => 'app\modules\message\Message',
    ],
];

這是全局配置,如果后面有新增模塊,再往這里面加即可,新增了這幾個文件,我們需要先完善這些代碼。

首先,rules.php文件里面的配置項並無需要新增的代碼。

modules里面定義了每個module的class,這邊需要新增所有模塊的基礎模塊類。

在modules文件夾里面新增定義好的幾個module,並采用mvc結構初始化models,views,controllers,以及模塊內的配置文件configs。

這邊以Goods為例,我們建立商品模塊。

第一步,在modules下面建立goods文件夾。並在goods目錄下面創建對應的文件和mvc文件夾。

Goods.php文件為上面modules.php配置文件中goods模塊的基類。用以引導goods模塊,具體代碼如下:

<?php

namespace app\modules\goods;

use Yii;

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

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

        Yii::configure($this, require(__DIR__ . '/config.php'));
    }
}

兩個功能,指定controller namespace,加載配置文件。

config.php文件代碼如下:

<?php
return [
    'components' => [
        // list of component configurations
    ],
    'params' => [
        // list of goods params
    ],
];

用以配置goods模塊需要用到的配置項。

其他模塊類似goods可以都創建一套相應的模板。

到此為止,相應的modules配置大功告成,以后擼代碼就經常在這里面了。

回到配置文件,我們繼續往下講。加載了這么多文件,如何配置進去呢,不急,慢慢來。

首先,我們配置一下appid

這邊我們是這么去配置的

'id' => Config('app.name'),

Config方法來源於Common.php文件定義的全局函數。

設置語言

'language' => 'zh-CN',

配置modules

'modules' => $modules,

配置別名

'aliases' => $aliases,

配置components,記得,這邊已經到components里面啦。

配置urlManager,將上面的規則引到這邊的配置項中

'urlManager' => [
            'showScriptName' => false,
            'enablePrettyUrl' => true,
            'rules' => $rules
        ],

配置log,按照我們上節講到的區分環境配置。

'log' => [
            'traceLevel' => Config('app.log.traceLevel'),
            'targets' => Config('app.log.targets'),
        ],

關於cache和db的配置,我們會到對應的章節中再做詳解。

最后,需要將web/assets文件夾的權限設為可寫,將runtime文件夾的權限設為可寫。

至此,所有關於入口腳本的配置文件項和基礎框架均已搭建完畢。

再次訪問你的那個遠程ip地址,出現下面這個頁面表示成功。

創建接口

搭好了上面的框架,下面我們就先來創建一個接口試驗一下吧。

首先,在User這個module下面的controller里面新建一個InfoController.php,用以獲取用戶的基本信息。

在InfoController.php里面,我們新建一個action,叫actionBaseInfo()。

具體代碼如下:

<?php
namespace app\modules\user\controllers;

use Yii;
use yii\web\Controller;

class InfoController extends Controller
{
    public function actionBaseInfo()
    {
        echo 'hello world!';
    }
}

Nginx虛擬主機配置

到這邊,所有的准備工作都完成啦,現在,我們需要在Nginx里面配置一個可供遠程訪問的host。

首先,我們來到nginx的安裝目錄

#cd /usr/www/nginx/

進入配置文件夾

#cd conf

新建一個文件夾,用以存放vhost虛擬主機配置文件。

#mkdir vhosts

進入vhosts目錄,新增sit.fengye.conf虛擬主機配置文件。

編輯一下內容到該文件里。

server {
        charset utf-8;
        client_max_body_size 128M;

        listen       80;
        server_name  www.sit.fengye.com;

        index index.php;
        root /usr/www/app/yii-basic/web;
        location / {
                # 如果找不到真實存在的文件,把請求分發至 index.php
                try_files $uri $uri/ /index.php?$args;
        }

        location ~ \.php$ {
                include fastcgi.conf;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_param ENV 'sit';
                include fastcgi_params;
                #fastcgi_pass unix:/var/run/php5-fpm.sock;
                try_files $uri =404;
        }

        location ~ /\.(ht|svn|git) {
                deny all;
        }

        access_log  /var/log/nginx/sit.fengye.access.log;
        error_log  /var/log/nginx/sit.fengye.error.log;
}

這些行代表什么意思,我會在Nginx的后續章節給大伙詳解。

保存退出,需要讓nginx在啟動的時候加載虛擬主機配置,我們需要在剛才的conf目錄下面的nginx.conf文件里面加一行。

include /usr/local/nginx/conf/vhosts/*.conf;

添加到http屬性的最后一行即可。

保存退出,重啟Nginx。

#service nginx restart

編輯你遠程服務器的hosts和本地的hosts,讓www.sit.fengye.com進入到hosts中,以便你順暢的訪問。

遠程服務器編輯/etc/hosts,新增下一行

127.0.0.1   www.sit.fengye.com

本地編輯/etc/hosts【OS X】,新增下一行

服務器IP   www.sit.fengye.com

至此,在瀏覽器中輸入下面的鏈接,看到hello world,你就成功啦!!!

http://www.sit.fengye.com/user/info/base-info

結束語

好了,到此為止,證明之前的配置沒有任何問題,路由規則也是能夠搞通的,perfect!

關於數據庫和緩存還有后續的框架內容,我還是會按照之前的方式,先講概念,再講實踐。

關於本章的代碼,以及后續的代碼,楓爺都已發布到github上,供大伙下載,感興趣的朋友別忘了Fork和Star一下我哈~感謝。

github地址:https://github.com/ifengye/yii-basic


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM