Lumen 初體驗

介紹

Lumen:「爲速度而生的 Laravel 框架」。php

Lumen 是 Laravel 的做者(Taylor Otwell)的又一力做。簡單、快速、優雅的它的特色,適合用於構建微服務架構和 API 應用。
官網:http://lumen.laravel.com
介紹:https://phphub.org/topics/701
中文文檔:http://lumen.laravel-china.org/docshtml

安裝

使用 composer 安裝:laravel

bashcomposer create-project laravel/lumen --prefer-dist

配置

Lumen 默認使用 .env 做爲配置文件。.env.example 是官方給出的例子,直接拷貝命名爲 .envbootstrap

bashcd lumen
cp .env.example .env

調試模式

修改 .env 文件:bash

bashAPP_DEBUG=true

若是發現仍是沒有效果,再修改 lumen/bootstrap/app.php 文件,將 Dotenv::load 的註釋移除掉。架構

疑問

1.爲何提示:not be found

訪問:http://127.0.0.1/lumen/public/app

顯示:composer

bashSorry, the page you are looking for could not be found.

NotFoundHttpException in Application.php line 1121:

in Application.php line 1121
at Application->handleDispatcherResponse(array('0')) in Application.php line 1091
at Application->dispatch(null) in Application.php line 1026
at Application->run() in index.php line 28

查看路由文件 lumen/app/Http/routes.php框架

php$app->get('/', function() use ($app) {
    return $app->welcome();
});

感受沒有問題啊,和在 Laravel 中差很少的方式,那是哪裏出了問題了?好的,先無論,嘗試本身新定義一條路由規則試試看:微服務

php$app->get('/test', function() use ($app) {
    return $app->welcome();
});

再訪問:http://127.0.0.1/lumen/public/test

結果和剛纔同樣。

2.爲何會跳轉

再嘗試訪問一下:http://127.0.0.1/lumen/public/test/
結果跳轉到:http://127.0.0.1/test

解惑

我先來解釋一下第 2 個問題,由於這是一個不少 Laravel 新手也常常問的問題。

緣由何在?請看 lumen/public/.htaccess 文件:

bashRewriteRule ^(.*)/$ /$1 [L,R=301]

這是一條 Apache 路由重寫規則(mod_rewrite 開啓的狀況下才有效),當請求的 URI 帶有 /,就會匹配出 $1, 永久重定向(HTTP 狀態碼是 301)到根目錄下的 $1。上面的例子中,匹配到 test(就是$1),就跳轉至 /test 了。

如何來規避上面這個問題?註釋這條 RewriteRule 嗎?不是的。通常來講,咱們應該避免使用末尾帶斜槓的 URI。爲何 URI 末尾不該該帶有斜槓呢?從語義是來講, test/ 表示目錄,test 表示資源。還有,若是在 lumen/public 目錄下真的有一個 test 目錄,那麼訪問 http://127.0.0.1/lumen/public/test/,就會進入到 test 目錄下面來,這不是咱們想要的結果。(其實若是真的存在 test 目錄而且不存在文件 test,那麼,URI 末尾有沒有斜槓都會進入到 test 目錄中來,這是 Apache 決定的。由於它若是找不到文件,就會自動在末尾加個斜槓,嘗試尋找目錄下的 index.html 文件等等,具體是在 httpd.conf 中配置 DirectoryIndex。好吧,扯得太遠了,拽回來)
總之,我仍是建議 URI 末尾不要帶 /,若是你非不聽,那就註釋上面那句 RewriteRule 吧,這樣就不會重定向了。

關於第 1 個問題,咱們也來分析一下發生的緣由,這樣才能對症下藥。
根據錯誤提示,定位到文件 lumen/vendor/laravel/lumen-framework/src/Application.php 中:

php/**
     * Dispatch the incoming request.
     *
     * @param  SymfonyRequest|null  $request
     * @return Response
     */
    public function dispatch($request = null)
    {
        if ($request) {
            $this->instance('Illuminate\Http\Request', $request);
            $this->ranServiceBinders['registerRequestBindings'] = true;

            $method = $request->getMethod();
            $pathInfo = $request->getPathInfo();
        } else {
            $method = $this->getMethod();
            $pathInfo = $this->getPathInfo();
        }        

        try {
            if (isset($this->routes[$method.$pathInfo])) {
                return $this->handleFoundRoute([true, $this->routes[$method.$pathInfo]['action'], []]);
            }

            return $this->handleDispatcherResponse(
                $this->createDispatcher()->dispatch($method, $pathInfo)
            );
        } catch (Exception $e) {
            return $this->sendExceptionToHandler($e);
        }
    }

匹配不到 route 的緣由就在以上代碼中。假設訪問:http://127.0.0.1/lumen/public,那麼 :

phpvar_dump($method);  // string(3) "GET"
var_dump($pathInfo);  // string(14) "/lumen/public/"

根據 lumen/app/Http/routes.php 中的定義,生成 $this->routes

phpvar_dump(array_keys($this->routes));  // array(2) { [0]=> string(4) "GET/" [1]=> string(8) "GET/test" }

由上可知, isset($this->routes[$method.$pathInfo]) 的結果就是 false,因此提示 not be found 了。
既然已經知道了緣由,那問題就好解決了。解決的前提是不要改動框架的源代碼,否則往後升級框架會多麼蛋疼,你都把框架代碼都修改,萬一出了問題你咋辦?你本身拆手機,官方是不保修的哦!固然,若是你是框架開發組的,你提交代碼能被你們接受並被官方合併到主幹代碼中了,那你就改吧。

方案1:修改 DocumentRoot

修改 Apache 的配置文件 httpd.conf,將 DocumentRoot 指向 lumen/public

bashDocumentRoot "/sites/lumen/public"

重啓 Apache。

可是,若是我還有其餘站點也在這個 Apache 下面,改 DocumentRoot 就會致使其餘的站點不能訪問了。怎麼辦?請看方案 2

方案2:配置 Apache 虛擬主機

修改 httpd.conf,將下面這行的註釋移除:

bashInclude etc/extra/httpd-vhosts.conf

修改 httpd-vhosts.conf

bash<VirtualHost *:80>
    DocumentRoot "/sites"
    ServerName 127.0.0.1
</VirtualHost>
<VirtualHost *:80>
    DocumentRoot "/sites/lumen/public"
    ServerName lumen.app
</VirtualHost>

重啓 Apache。

修改主機的 etc/hosts,添加一行:

bash127.0.0.1 lumen.app

其中 127.0.0.1 應該換成你 lumen 應用存放的機器的 ip。

OK,這樣就能夠經過訪問 http://lumen.app 來訪問該 lumen 站點,經過 http://127.0.0.1 來訪問其餘站點。

可是,你壓根不能修改 Apache 的配置,怎麼辦?請看方案 3

方案3.修改路由規則中的路徑

改不了配置,就改代碼嘍(再強調一下,不是修改框架的源代碼)。

修改路由文件 lumen/app/Http/routes.php

php
define('ROUTE_BASE', 'lumen/public'); $app->get(ROUTE_BASE . '/index', function() use ($app) { return $app->welcome(); }); $app->get(ROUTE_BASE . '/test', function() use ($app) { return $app->welcome(); });

這樣,若是之後有變化的話,你只須要修改 define('ROUTE_BASE', 'lumen/public/');就能夠了(固然,把這個寫到應用配置項中是最合適的,部署時修改配置就能夠了)。

至於想以 'lumen/public/' 做爲首頁 URI 顯然是不能夠的,建議使用 'lumen/pulbic/index' 做爲首頁。如同上面代碼定義的路由規則那樣。

由於,不管你在路由規則的字符串末尾加了多少個斜槓, $this->routes 的鍵是不會帶有斜槓的,最終仍是不能匹配的。緣由在框架源代碼中 lumen/vendor/laravel/lumen-framework/src/Application.php

php/**
     * Add a route to the collection.
     *
     * @param  string  $method
     * @param  string  $uri
     * @param  mixed  $action
     */
    protected function addRoute($method, $uri, $action)
    {
        $action = $this->parseAction($action);

        $uri = $uri === '/' ? $uri : '/'.trim($uri, '/');

        if (isset($action['as'])) {
            $this->namedRoutes[$action['as']] = $uri;
        }

        if (isset($this->groupAttributes)) {
            if (isset($this->groupAttributes['prefix'])) {
                $uri = rtrim('/'.trim($this->groupAttributes['prefix'], '/').$uri, '/');
            }

            $action = $this->mergeGroupAttributes($action);
        }

        $this->routes[$method.$uri] = ['method' => $method, 'uri' => $uri, 'action' => $action];
    }

對,就是它:$uri = $uri === '/' ? $uri : '/'.trim($uri, '/');。 全部,URI 末尾仍是不帶斜槓的好。

相關文章
相關標籤/搜索