Lumen 初體驗(二)

jopen 9年前發布 | 75K 次閱讀 Lumen Web框架


最近使用 Lumen 做了 2 個業余項目,特此記錄和分享一下。

Lumen 的介紹

在使用一項新的技術時,了解其應用場景是首要的事情。

Lumen 的口號: 為速度而生的 Laravel 框架

Lumen 的定位: 微框架

Lumen 的應用場景: Lumen 專為微服務或者 API 設計

Lumen 的優點: 構建在 Laravel 之上, 使其具備 Laravel 強大的功能

Lumen 包含了 Laravel 的哪些功能:

  • Blade 模版引擎
  • Caching 緩存系統
  • Command Scheduler 計劃任務
  • Controllers 控制器
  • Eloquent ORM 數據庫操作
  • Error Handling 錯誤處理
  • Database Abstraction 數據庫抽象層
  • Dependency Injection 依賴注入
  • Logging 日志系統
  • Queued Jobs 隊列系統

以上內容來自: Lumen 的介紹 ,建議點擊閱讀詳情。

Lumen 的現狀

目前是1.0 版本,是基于 Laravel 5.x 開發。看 github 上作者更新的很勤快,但是這也導致文檔和實際情況有不一致的情況,變動也比較頻繁。吐個槽:也許,我下面說的一些情況都發生了變化。

和 Laravel 最大的區別

既然是為了快速而生,砍掉功能的必然的,功能的有或無,事先了解到即可,倒不算作最大的區別。我認為可見的最大變化是:

Lumen 沒有使用 Symfony 的路由模塊, 而是采用了速度更加快的 nikic/fast-route。

這個變化也延伸出其他的一些變化,比如和路由相關的一些 helper 函數也少了。

不可見的變化:我猜想框架的初始化機制應該也發生了很大的變化,但是對于使用框架并沒有可見的影響。因為我沒有深入去讀框架源碼,所以也不敢亂說。

Artisan 命令

Lumen 下的 Artisan 命令比 Laravel 的少很多。這個在項目下運行php artisan,和 Laravel 的比較一下就知道了。

但是,有些命令沒有也不影響原有功能的使用,畢竟 Artisan 命令工具只是起到輔助開發和提高效率的作用。

開發自己的 Artisan 命令

在 Laravel 中,要創建一個新的自定義命令,可以使用make:console這個 Artisan 命令。比如:php artisan make:console FooCommand。

但是,在 Lumen 中沒有這個 Artisan 命令。于是,我在 Laravel 下使用該命令,生成了文件app/Console/Commands/FooCommand.php。我將文件復制到 Lumen 項目中的app/Console/Commands/的目錄下,并按照 Laravel 的文檔 Artisan 開發 編寫,成功運行。之后,我使用該方式創建了兩個具有完整功能的 Artisan 命令(一個是爬蟲并和 MySQL 交互,另一個是和 Redis 交互),目前尚沒有發現有任何問題。

入口文件、啟動文件和配置文件

框架的入口文件是public/index.php。里面也只有兩行代碼:

$app = require __DIR__.'/../bootstrap/app.php';
$app->run();

啟動并運行。

閱讀bootstrap/app.php文件還是很重要的,下面的內容幾乎都有涉及這個文件。

Lumen 的配置文件是項目根目錄下的.env文件,官方給出了一個例子文件:.env.example。需要在bootstrap/app.php中將Dotenv::load(__DIR__ . '/../');的注釋去掉才能使用.env,幾乎很多操作都依賴這個,不知道為什么它默認是加上注釋的。

路由定義

在bootstrap/app.php中,最后兩行代碼是:

require __DIR__ . '/../app/Http/routes.php';
return $app;

路由定義在文件app/Http/routes.php中。里面給出了一個例子:
$app->get('/', function() use ($app) {
    return $app->welcome();
});

路由的詳情可以參見文檔 HTTP 路由

這里我想吐個槽,$app->welcome這個 可能 是為了測速而耍的小伎倆,因為welcome這個方法只是單純輸出 HTML 歡迎頁,但是是直接寫在Laravel\Lumen\Application類中的,這不科學。

在路由中指定控制器類 必須寫全命名空間 ,不然會提示找不到類。

$app->get('/test', array(
    'uses' => 'App\Http\Controllers\TestController@getIndex',
));

這個和 Laravel 不同,在 Laravel 中是可以不必指定App\Http\Controllers:
$app->get('/test', array(
    'uses' => 'TestController@getIndex',
));

因為在 Laravel 中,默認控制器的根命名空間為App\Http\Controllers。這個也可以設置:URL::setRootControllerNamespace('App\Http\Controllers');。參見 Laravel 文檔: HTTP 控制器

但是,在 Lumen 中,這些都是沒有的。我只在框架源碼中找到接口UrlGenerator中有setRootControllerNamespace的定義,并沒有找到實現。我猜這個應該也是換路由帶來的影響,不知道后面會不會有修改。

如果實在不想重復寫全命名空間,除了定義一個變量(或常量)外,還有一種旁門左道的方法,使用組路由:

$app->group(array('namespace' => 'App\Http\Controllers'), function () use ($app) {
    $app->get( '/login', array(
        'as' => 'login',
        'uses' => 'PassportController@getLogin',
    ));
});

畢竟是旁門左道,我其實的拒絕的。

Facades

Facades 提供一個靜態接口給在應用程序的服務容器中可以取用的類

比如:

\Cache::put('key', 'value', $minutes);
\DB::getQueryLog()

在 Lumen 中,這個功能默認是沒有開啟的。開啟方式是去掉bootstrap/app.php中$app->withFacades();的注釋。

當然,如果不開啟,也不礙事:

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

Cache::put('key', 'value', $minutes);
DB::getQueryLog();

Lumen 中可以使用的 Facades,查看源代碼,可用清單如下:

public function withFacades()
{
    Facade::setFacadeApplication($this);
    if (! static::$aliasesRegistered) {
  static::$aliasesRegistered = true;
  class_alias('Illuminate\Support\Facades\App', 'App');
  class_alias('Illuminate\Support\Facades\Auth', 'Auth');
  class_alias('Illuminate\Support\Facades\Bus', 'Bus');
  class_alias('Illuminate\Support\Facades\DB', 'DB');
  class_alias('Illuminate\Support\Facades\Cache', 'Cache');
  class_alias('Illuminate\Support\Facades\Cookie', 'Cookie');
  class_alias('Illuminate\Support\Facades\Crypt', 'Crypt');
  class_alias('Illuminate\Support\Facades\Event', 'Event');
  class_alias('Illuminate\Support\Facades\Hash', 'Hash');
  class_alias('Illuminate\Support\Facades\Log', 'Log');
  class_alias('Illuminate\Support\Facades\Mail', 'Mail');
  class_alias('Illuminate\Support\Facades\Queue', 'Queue');
  class_alias('Illuminate\Support\Facades\Request', 'Request');
  class_alias('Illuminate\Support\Facades\Schema', 'Schema');
  class_alias('Illuminate\Support\Facades\Session', 'Session');
  class_alias('Illuminate\Support\Facades\Storage', 'Storage');
  class_alias('Illuminate\Support\Facades\Validator', 'Validator');
    }
}

數據庫和 Eloquent

數據庫相關配置信息在 .env 文件里面, DB_* 開頭。 你可以定義所有的數據庫連接。目前 Lumen 支持四種數據庫系統:MySQL、Postgres、SQLite、以及 SQL Server。

數據庫和 Eloquent ORM 和 Laravel 中的用法一樣,看 Laravel 的相關文檔即可。

數據庫操作日志默認是關閉的,啟動方式:

DB::connection()->enableQueryLog();

詳情參見: 查找日志記錄

在 Lumen 中如果需要使用 Eloquent ORM,應該去掉bootstrap/app.php中$app->withEloquent();的注釋。

詳情參見: 數據庫使用基礎

Session

Session 默認未開啟。

開啟方式:去掉bootstrap/app.php中$app->middleware();的StartSession中間件的注釋。

使用時發生錯誤:Class 'Memcached' not found,因為在.env文件中,Session 的默認驅動是:memcached。修改即可。

目前支持的驅動有:file、cookie、database、memcached、redis、array。詳情參見: 會話

對了,說一句,重定向的功能有依賴于 Session。

Cookie

如果你想讓所有的 Cookie 都加密的話, 你需要把bootstrap/app.php的EncryptCookies中間件去掉注釋. Lumen 所建立的 cookie 會加密并且加上認證記號,這代表著被用戶擅自更改的 cookie 會失效。

一般使用 cookie 都是伴著Response對象返回給客戶端的:

$response->withCookie(cookie('name', 'value', $minutes));
return $response;

如果不喜歡上面那種方式,還有另外一種:
Cookie:
:queue('name', 'value');
return $response;

但是:

你需要在bootstrap/app.php文件里面注釋掉AddQueuedCookiesToResponse這一行來使用此功能.

總結

最后說一下,Lumen 定位是微框架,Laravel 定位是全棧框架。使用一項技術時,得先了解一下它適用的場景。Lumen 的適用場景,官方有介紹: 在什么時候使用 Lumen? 。如果場景不對,那么 Lumen 的優勢(比如:速度、簡單)可能就發揮不出來,而劣勢卻會更加凸顯。如果想用 Lumen 做太多太復雜的事情,還是直接上 Laravel。不然,你可能會覺得 Lumen 怎么這也沒有那也不行的(尤其是用過 Laravel,這種感覺可能更甚)。好在 Lumen 本身和 Laravel 出自同門,Lumen 向 Laravel 遷移是很容易的事情,代碼改動量并不大。

最后的最后,如果熟悉 Laravel,那么學習 Lumen 的成本是極低的。

祝玩的愉快!


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!