Laravel 和 Codeception - PUT 表单测试失败
Laravel and Codeception - test fails on PUT forms
我在 laravel 中有一个资源控制器来管理我的用户。这将创建一个更新用户信息的路由,该路由接受使用 HTTP PUT 方法的请求。
这显示 artisan route:list
命令输出:
+--------+--------------------------------+-----------------------------------------------------------+--------------------------------------+--------------------------------------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+--------------------------------+-----------------------------------------------------------+--------------------------------------+--------------------------------------------------------------------------------+------------+
...
| | PUT | users/{users} | users.update | App\Http\Controllers\Users\UsersController@update | auth |
它在我的网络浏览器上工作正常,但是当我尝试 运行 一个带有代码接收的测试并提交表单时,我得到一个方法不允许的异常并且测试失败。
我试着看看为什么会这样,这似乎是 codeception 提出的要求。该请求是使用 POST 而不是 PUT 方法发出的,从而阻止 Laravel 匹配路由。
HTML 表单不支持 PUT 方法,因此 Laravel Form
助手 class 创建如下表单:
<form method="POST" action="https://myapp.dev/users/172" accept-charset="UTF-8">
<input name="_method" value="PUT" type="hidden">
...
但是,codeception 似乎没有读取 _method
值。
我该如何解决这个问题?
编辑:深入查看代码,我发现测试不会覆盖请求方法,因为 Request
class 中的常量称为 Request::$httpMethodParameterOverride
。
/**
* Gets the request "intended" method.
*
* If the X-HTTP-Method-Override header is set, and if the method is a POST,
* then it is used to determine the "real" intended HTTP method.
*
* The _method request parameter can also be used to determine the HTTP method,
* but only if enableHttpMethodParameterOverride() has been called.
*
* The method is always an uppercased string.
*
* @return string The request method
*
* @api
*
* @see getRealMethod()
*/
public function getMethod()
{
if (null === $this->method) {
$this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
if ('POST' === $this->method) {
if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
$this->method = strtoupper($method);
} elseif (self::$httpMethodParameterOverride) {
$this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
}
}
}
return $this->method;
}
之前的常量值应该是true
但是不知怎么的,当我运行测试的时候它的值是false
.
您不能在 HTML 表单标签中使用 PUT
方法。为此,您需要使用 laravel 的 blade 模板格式来定义表单标签。
例如
{!! Form::open(['url' => 'users/{users}','method' => 'put','id' => 'form' ]) !!}
您也可以使用 route
属性来定义路由而不是 url
。
我找到了一个解决方案,但我认为这不是写它的正确位置。
我在 Connector\Laravel5
class.
上添加了一行简单的代码
public function __construct($module)
{
$this->module = $module;
$this->initialize();
$components = parse_url($this->app['config']->get('app.url', 'http://localhost'));
$host = isset($components['host']) ? $components['host'] : 'localhost';
parent::__construct($this->app, ['HTTP_HOST' => $host]);
// Parent constructor defaults to not following redirects
$this->followRedirects(true);
// Added to solve the problem of overriding the request method
Request::enableHttpMethodParameterOverride();
}
这解决了我的问题。
我在 laravel 中有一个资源控制器来管理我的用户。这将创建一个更新用户信息的路由,该路由接受使用 HTTP PUT 方法的请求。
这显示 artisan route:list
命令输出:
+--------+--------------------------------+-----------------------------------------------------------+--------------------------------------+--------------------------------------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+--------------------------------+-----------------------------------------------------------+--------------------------------------+--------------------------------------------------------------------------------+------------+
...
| | PUT | users/{users} | users.update | App\Http\Controllers\Users\UsersController@update | auth |
它在我的网络浏览器上工作正常,但是当我尝试 运行 一个带有代码接收的测试并提交表单时,我得到一个方法不允许的异常并且测试失败。
我试着看看为什么会这样,这似乎是 codeception 提出的要求。该请求是使用 POST 而不是 PUT 方法发出的,从而阻止 Laravel 匹配路由。
HTML 表单不支持 PUT 方法,因此 Laravel Form
助手 class 创建如下表单:
<form method="POST" action="https://myapp.dev/users/172" accept-charset="UTF-8">
<input name="_method" value="PUT" type="hidden">
...
但是,codeception 似乎没有读取 _method
值。
我该如何解决这个问题?
编辑:深入查看代码,我发现测试不会覆盖请求方法,因为 Request
class 中的常量称为 Request::$httpMethodParameterOverride
。
/**
* Gets the request "intended" method.
*
* If the X-HTTP-Method-Override header is set, and if the method is a POST,
* then it is used to determine the "real" intended HTTP method.
*
* The _method request parameter can also be used to determine the HTTP method,
* but only if enableHttpMethodParameterOverride() has been called.
*
* The method is always an uppercased string.
*
* @return string The request method
*
* @api
*
* @see getRealMethod()
*/
public function getMethod()
{
if (null === $this->method) {
$this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
if ('POST' === $this->method) {
if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
$this->method = strtoupper($method);
} elseif (self::$httpMethodParameterOverride) {
$this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
}
}
}
return $this->method;
}
之前的常量值应该是true
但是不知怎么的,当我运行测试的时候它的值是false
.
您不能在 HTML 表单标签中使用 PUT
方法。为此,您需要使用 laravel 的 blade 模板格式来定义表单标签。
例如
{!! Form::open(['url' => 'users/{users}','method' => 'put','id' => 'form' ]) !!}
您也可以使用 route
属性来定义路由而不是 url
。
我找到了一个解决方案,但我认为这不是写它的正确位置。
我在 Connector\Laravel5
class.
public function __construct($module)
{
$this->module = $module;
$this->initialize();
$components = parse_url($this->app['config']->get('app.url', 'http://localhost'));
$host = isset($components['host']) ? $components['host'] : 'localhost';
parent::__construct($this->app, ['HTTP_HOST' => $host]);
// Parent constructor defaults to not following redirects
$this->followRedirects(true);
// Added to solve the problem of overriding the request method
Request::enableHttpMethodParameterOverride();
}
这解决了我的问题。