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
是官方给出的例子,直接拷贝命名为 .env
。bootstrap
bashcd lumen cp .env.example .env
修改 .env
文件:bash
bashAPP_DEBUG=true
若是发现仍是没有效果,再修改 lumen/bootstrap/app.php
文件,将 Dotenv::load
的注释移除掉。架构
访问: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
结果和刚才同样。
再尝试访问一下: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
了。
既然已经知道了缘由,那问题就好解决了。解决的前提是不要改动框架的源代码,否则往后升级框架会多么蛋疼,你都把框架代码都修改,万一出了问题你咋办?你本身拆手机,官方是不保修的哦!固然,若是你是框架开发组的,你提交代码能被你们接受并被官方合并到主干代码中了,那你就改吧。
修改 Apache 的配置文件 httpd.conf
,将 DocumentRoot
指向 lumen/public
:
bashDocumentRoot "/sites/lumen/public"
重启 Apache。
可是,若是我还有其余站点也在这个 Apache 下面,改 DocumentRoot 就会致使其余的站点不能访问了。怎么办?请看方案 2。
修改 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。
改不了配置,就改代码喽(再强调一下,不是修改框架的源代码)。
修改路由文件 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 末尾仍是不带斜杠的好。