调试模式 修改 .env 文件: APP_DEBUG=true 如果发现还是没有效果,再修改 lumen/bootstrap/app.php 文件,将 Dotenv::load 的注释移除掉。 疑问 1.为什么提示:not be found 访问:<http://127.0.0.1/lumen/public/>; 显示: Sorry, 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: $app->get('/', function()use($app){ return$app->welcome(); }); 感觉没有问题啊,和在 Laravel 中差不多的方式,那是哪里出了问题了?好的,先不管,尝试自己新定义一条路由规则试试看: $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 文件: RewriteRule ^(.*)/$ /$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中: /** * * Dispatch the incoming request. * * @param SymfonyRequest|null $request * @return Response */publicfunctiondispatch($request = null){ if ( $request ) { $this->instance('IlluminateHttpRequest', $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>;,那么 : var_dump($method); // string(3) "GET" var_dump($pathInfo); // string(14) "/lumen/public/" 根据lumen/app/Http/routes.php 中的定义,生成 $this->routes: var_dump(array_keys($this->routes)); // array(2) { [0]=> string(4) "GET/" [1]=> string(8) "GET/test" } 由上可知, isset($this->routes[$method.$pathInfo]) 的结果就是 false,所以提示 not befound 了。 既然已经知道了原因,那问题就好解决了。解决的前提是不要改动框架的源代码,不然日后升级框架会多么蛋疼,你都把框架代码都修改,万一出了问题你咋办?你自己 拆手机,官方是不保修的哦!当然,如果你是框架开发组的,你提交代码能被大家接受并被官方合并到主干代码中了,那你就改吧。 方案1:修改 DocumentRoot 修改 Apache 的配置文件 httpd.conf,将 DocumentRoot 指向 lumen/public: DocumentRoot"/sites/lumen/public" 重启 Apache。 但是,如果我还有其他站点也在这个 Apache 下面,改 DocumentRoot 就会导致其他的站点不能访问了。怎么办?请看方案 2。 方案2:配置 Apache 虚拟主机 修改 httpd.conf,将下面这行的注释移除: Include etc/extra/httpd-vhosts.conf 修改 httpd-vhosts.conf: DocumentRoot"/sites"ServerName 127.0.0.1 DocumentRoot"/sites/lumen/public"ServerName lumen.app 重启 Apache。 修改主机的 etc/hosts,添加一行: 127.0.0.1lumen.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: 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: /** * * Add a route to the collection. * * @param string $method * @param string $uri * @param mixed $action */protectedfunctionaddRoute($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 末尾还是不带斜杠的好。
Comments : 0