laravel吐槽系列之一

laravel吐槽系列之一


最近項目中經常使用到了laravel框架,對於這個框架之前只是弱弱地接觸了一點,沒有深入接觸,這下有時間好好研究它了(主要是不得不研究了)。說實話,laravel讓我打開眼界了,之前對框架的使用一直停留在yii1.X階段。總之那句話說的對,剛接觸laravel的phper就只有兩個反應,一個是撿到寶了,一個是覺得它是垃圾。我能,就屬於後者,所以現在在努力讓自己愛上laravel。但是一切總是有那麼硌人的地方,我就想寫寫一些東西來吐槽laravel。

吐槽點:laravel的vendor引用的組件過多 

laravel是遵循composer來寫的一個框架,問題是這個框架又引入了其他的幾個組件,然後其他的組件又引入了一些組件,反正下面是我composer create的時候需要引入的組件,自己看看吧。。。
複製代碼
➜  laravel  composer create-project laravel/laravel test --prefer-dist
Installing laravel/laravel (v4.2.0)
  - Installing laravel/laravel (v4.2.0)
    Downloading: 100%

Created project in test
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing symfony/translation (v2.5.4)
    Downloading: 100%

  - Installing psr/log (1.0.0)
    Downloading: 100%

  - Installing symfony/security-core (v2.5.4)
    Downloading: 100%

  - Installing symfony/debug (v2.5.4)
    Downloading: 100%

  - Installing symfony/http-foundation (v2.5.4)
    Downloading: 100%

  - Installing symfony/event-dispatcher (v2.5.4)
    Downloading: 100%

  - Installing symfony/http-kernel (v2.5.4)
    Downloading: 100%

  - Installing symfony/routing (v2.5.4)
    Downloading: 100%

  - Installing symfony/process (v2.5.4)
    Downloading: 100%

  - Installing symfony/finder (v2.5.4)
    Downloading: 100%

  - Installing symfony/console (v2.5.4)
    Downloading: 100%

  - Installing symfony/filesystem (v2.5.4)
    Downloading: 100%

  - Installing symfony/dom-crawler (v2.5.4)
    Downloading: 100%

  - Installing symfony/css-selector (v2.5.4)
    Downloading: 100%

  - Installing symfony/browser-kit (v2.5.4)
    Downloading: 100%

  - Installing swiftmailer/swiftmailer (v5.2.2)
    Downloading: 100%

  - Installing stack/builder (v1.0.2)
    Downloading: 100%

  - Installing predis/predis (v0.8.7)
    Downloading: 100%

  - Installing phpseclib/phpseclib (0.3.8)
    Downloading: 100%

  - Installing patchwork/utf8 (v1.1.25)
    Downloading: 100%

  - Installing nesbot/carbon (1.13.0)
    Downloading: 100%

  - Installing monolog/monolog (1.10.0)
    Downloading: 100%

  - Installing nikic/php-parser (v0.9.5)
    Downloading: 100%

  - Installing jeremeamia/superclosure (1.0.1)
    Downloading: 100%

  - Installing ircmaxell/password-compat (1.0.3)
    Downloading: 100%

  - Installing d11wtq/boris (v1.0.8)
    Downloading: 100%

  - Installing classpreloader/classpreloader (1.0.2)
    Downloading: 100%

  - Installing filp/whoops (1.1.2)
    Downloading: 100%

  - Installing laravel/framework (v4.2.9)
    Downloading: 100%

symfony/translation suggests installing symfony/config ()
symfony/translation suggests installing symfony/yaml ()
symfony/security-core suggests installing symfony/validator (For using the user password constraint)
symfony/security-core suggests installing symfony/expression-language (For using the expression voter)
symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/http-kernel suggests installing symfony/class-loader ()
symfony/http-kernel suggests installing symfony/config ()
symfony/http-kernel suggests installing symfony/dependency-injection ()
symfony/routing suggests installing symfony/config (For using the all-in-one router or any loader)
symfony/routing suggests installing symfony/yaml (For using the YAML loader)
symfony/routing suggests installing symfony/expression-language (For using expression matching)
symfony/routing suggests installing doctrine/annotations (For using the annotation loader)
predis/predis suggests installing ext-phpiredis (Allows faster serialization and deserialization of the Redis protocol)
phpseclib/phpseclib suggests installing ext-mcrypt (Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.)
phpseclib/phpseclib suggests installing ext-gmp (Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.)
phpseclib/phpseclib suggests installing pear-pear/PHP_Compat (Install PHP_Compat to get phpseclib working on PHP < 4.3.3.)
monolog/monolog suggests installing graylog2/gelf-php (Allow sending log messages to a GrayLog2 server)
monolog/monolog suggests installing raven/raven (Allow sending log messages to a Sentry server)
monolog/monolog suggests installing doctrine/couchdb (Allow sending log messages to a CouchDB server)
monolog/monolog suggests installing ruflin/elastica (Allow sending log messages to an Elastic Search server)
monolog/monolog suggests installing ext-amqp (Allow sending log messages to an AMQP server (1.0+ required))
monolog/monolog suggests installing ext-mongo (Allow sending log messages to a MongoDB server)
monolog/monolog suggests installing aws/aws-sdk-php (Allow sending log messages to AWS services like DynamoDB)
monolog/monolog suggests installing rollbar/rollbar (Allow sending log messages to Rollbar)
laravel/framework suggests installing doctrine/dbal (Allow renaming columns and dropping SQLite columns.)
Writing lock file
Generating autoload files
Mcrypt PHP extension required.
Script php artisan clear-compiled handling the post-install-cmd event returned with an error
複製代碼

 

一共有28個需要Install的,這個導致的結果是初始化可運行的項目大小有25M之大。
這麼bigger than bigger的玩意,首先會帶來部署上的不便利。
部署laravel項目的時候會有兩種方式,一種是隻發佈除了vendor之外的項目相關的文件,然後運行composer進行vender的更新,另外一種是直接將vendor進入版本庫,使用版本庫的發佈將所有代碼發佈到線上機器去。我個人傾向第二種,能把代碼庫中的文件直接放到服務器上就能運行的多牛逼。但是這樣子,代碼庫就變得超大了,不大便利了。
 
其次,這麼多的vendor導致的是文檔查閱的不方便。
一個框架好用不好用,文檔是一個至關重要的環節。但是引用的第三方庫一多了,很多使用文檔官方就沒有足夠詳細的文檔說明了,然後美其名告訴你,這個是引用第三方庫的,給你個鏈接,你去第三方庫的說明文檔中看把。但是你要知道,在開發過程中,文檔是需要有統一性的,每一個說明文檔的展示和查詢規則都是有慣性的。你給個鏈接讓我去一個不一樣佈局的網頁,我的思維還需要進行跳躍和查找。

解決辦法:忍 

吐槽點:laravel的路由可以寫function

laravel的路由非常強大,強大到無敵了。比如說呢,什麼controller,action啥的都是浮雲,哥可以在app/route.php裏面直接寫上路由對應的funciton,啥controller都不用寫了,一個文件可以do everything。但是,什麼都能做的框架就是把規則的制定推給使用者。比如在route中可以允許寫function,我第一次看到的時候覺得渾身都不對了,一個制定路由的文件,你就制定哪個路由到哪個action就好,幹毛在一個叫route.php的文件裏面,制定具體的執行方法。我估摸很多團隊都會約定不允許在route裏面寫funciton,因爲這樣就個路由的設置就很雞肋了。

解決辦法:團隊自行做一些規定來限制路由的功能。

吐槽點:laravel沒有默認路由 

我這裏說的是比如yii中有默認路由的方式controller/action。比如user/index 默認就對應到userController 的IndexAction中去。但是在laravel中,它將這種名稱依賴的默認路由去掉了。所有laravel中使用的路由都需要手動在route.php中制定諸如這樣的命令:
Route::get('login', ['as' => 'login', 'uses' => 'UserController@login']);
但是特別在做後臺開發的時候真是特別無法忍受,每次增加一個路由都需要在route中加入這麼一條玩意。
 
最後我取折衷的辦法,在後臺開發的時候,多使用這樣的語句:
Route::controller('series', 'SeriesController’);
這樣,在controller中定義的getXXX和postXXX就能自動解析了,就不需要那麼繁雜的寫route路徑了。 

解決辦法:多使用Route::controller 

吐槽點:日誌記錄信息太多了

看看默認的laravel.log中的一個錯誤:
 
我能罵髒話麼,laravel中由於使用了大量的組件,導致laravel的堆棧非常長,然後呢,錯誤日誌中就把堆棧打印出來了,汗,上面那麼多的錯誤信息,竟然沒有記錄當前的請求URL和請求參數。看着這麼多錯誤信息的日誌,我竟然無言以對,我應該看哪裏,去哪裏找出這個錯誤呢?
 
對於日誌存儲,laravel使用monlog,雖然說是很強大了,但是它還有個問題,就是如果你想要讓日誌記錄到不同日誌文件實現起來比較複雜。首先你可能會想到使用useFiles或者useDailyFiles來記錄到不同的文件,但是Log是Facade模式的,一旦修改了useFile,你就要修改回來才行。其次,你可能會想到使用這個文章中的方法:
http://laravel.io/forum/02-09-2014-laraverl-custom-logs,new一個,再Info,好吧,實際後來我也是用類似的方法封裝了下。最後,你的方法可能就是寫個log的ServiceProvider,覆蓋或者重寫原先的哪個Log。
 
總之達成目的的方法一定不止一個,but,總之,原先的哪個Log還是不爽。 

解決方法:自定義日誌編輯類

首先自定義了日誌編輯類:
複製代碼
<?php
namespace Yejiafneng\Helpers;
 
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Illuminate\Log\Writer;
 
class BLogger
{
    // 所有的LOG都要求在這裏註冊
    const LOG_ERROR = 'error';
    const LOG_SHOP = 'shop';
    const LOG_QUERY = 'query';
    const LOG_LOGIN = 'login';
 
    private static $loggers = array();
 
    // 獲取一個實例
    public static function getLogger($type = self::LOG_ERROR, $day = 30)
    {
        if (empty(self::$loggers[$type])) {
            self::$loggers[$type] = new Writer(new Logger($type));
        }
        $log = self::$loggers[$type];
        $log->useDailyFiles(storage_path().'/logs/'. $type .'.log', $day);
        return $log;
    }
}
複製代碼

 然後在app/start/global.php中修改錯誤日誌回調函數爲:

複製代碼
// 錯誤日誌信息
App::error(function(Exception $exception, $code)
{
    // 如果沒有路徑就直接跳轉到登錄頁面
    if ($exception instanceof NotFoundHttpException) {
        return Redirect::route('login');
    }
 
     Log::error($exception);
 
    $err = [
        'message' => $exception->getMessage(),
        'file' => $exception->getFile(),
        'line' => $exception->getLine(),
        'code' => $exception->getCode(),
        'url' => Request::url(),
        'input' => Input::all(),
    ];
    BLogger::getLogger(BLogger::LOG_ERROR)->error($err);
});
複製代碼

 

這裏沒有修改laravel自身的錯誤日誌記錄,因爲保留一個全集的錯誤應該還是有必要的,但是實際上我使用過程中只要看自己定義的error.log就足夠了
 
 
 

吐槽點:ORM的where太弱 

laravel的ORM使用的是Eloquent ORM。如果你要獲取出Student表中female=1 並且 teacher_id爲4 並且class_id爲3的所有學生,你需要這麼寫:
Student::where('female', 1)
->where('teacher_id', 4)
->where('class_id', 3)
->get();
好難受,如果一個還行,要是多個呢?。。。難道就不能在一個where中使用個數組麼?

解決辦法:在基類中擴展一個multiwhere 

於是我就在BaseModel中定義了:
複製代碼
    // 多where
    public function scopeMultiwhere($query, $arr)
    {
        if (!is_array($arr)) {
            return $query;
        }
 
        foreach ($arr as $key => $value) {
            $query = $query->where($key, $value);
        }
        return $query;
    }
複製代碼

 

這樣子,上面的語句就可以這麼使用:
Student::multiwhere([‘female’=>1, ’teacher_id’ => 4, ‘class_id’ => 3])->get();

 一下子腰也不酸了,頭也不疼了。。。

後記

laravel還是能讓一個phper學習到很多的,我努力着愛之深責之切的原則,後續使用laravel中使用不爽的地方再繼續吐槽和討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章