CodeIgniter中的表单方法欺骗

时间:2016-10-09 17:24:47

标签: codeigniter codeigniter-3

所以我想删除数据时在路由上使用HTTP DELETE。

是否可以在CodeIgniter中使用方法欺骗?

也许像Laravel一样使用隐藏输入“_method”?

<input type="hidden" name="_method" value="DELETE">

有没有建议如何在CodeIgniter中执行此操作?

干杯。

1 个答案:

答案 0 :(得分:2)

我刚刚注意到Laravel docs中的这个功能,用Google搜索并找到了这个问题。我将在 CI 3.0+ (可能是2.0 +) 中分享我的实施。

文件:application / helpers / MY_form_helper.php

<?php defined('BASEPATH') OR exit('No direct script access allowed');

if ( ! function_exists('method_field')) {
    function method_field($method)
    {
        return '<input type="hidden" name="__method" value="'.$method.'">';
    }
}

文件:application / config / routes.php

<?php defined('BASEPATH') OR exit('No direct script access allowed');

$route['default_controller'] = 'home';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;

// seperate controllers in HTTP VERB sub-folders
$route['(.+)']['GET'] = 'get/$1';
$route['(.+)']['POST'] = 'post/$1';
$route['(.+)']['PUT'] = 'put/$1';
$route['(.+)']['PATCH'] = 'patch/$1';
$route['(.+)']['DELETE'] = 'delete/$1';

文件:application / core / MY_Router.php

<?php defined('BASEPATH') OR exit('No direct script access allowed');

protected function _parse_routes()
{
    // Turn the segment array into a URI string
    $uri = implode('/', $this->uri->segments);

    // Get HTTP verb
    $http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';

    // ::: START EDIT (Form Method Spoofing) :::
    $_request_method = strtolower(isset($_POST['__method']) ? $_POST['__method'] : isset($_GET['__method']) ? $_GET['__method'] : NULL);
    if ( ! empty($_request_method) && in_array($_request_method, ['get', 'post', 'put', 'patch', 'delete'])) {
        $http_verb = $_request_method;
    }
    // ::: END EDIT (Form Method Spoofing) :::

    // Loop through the route array looking for wildcards
    foreach ($this->routes as $key => $val)
    {
        // Check if route format is using HTTP verbs
        if (is_array($val))
        {
            $val = array_change_key_case($val, CASE_LOWER);
            if (isset($val[$http_verb]))
            {
                $val = $val[$http_verb];
            }
            else
            {
                continue;
            }
        }

        // Convert wildcards to RegEx
        $key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);

        // Does the RegEx match?
        if (preg_match('#^'.$key.'$#', $uri, $matches))
        {
            // Are we using callbacks to process back-references?
            if ( ! is_string($val) && is_callable($val))
            {
                // Remove the original string from the matches array.
                array_shift($matches);

                // Execute the callback using the values in matches as its parameters.
                $val = call_user_func_array($val, $matches);
            }
            // Are we using the default routing method for back-references?
            elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
            {
                $val = preg_replace('#^'.$key.'$#', $val, $uri);
            }

            $this->_set_request(explode('/', $val));
            return;
        }
    }

    // If we got this far it means we didn't encounter a
    // matching route so we'll set the site default route
    $this->_set_request(array_values($this->uri->segments));
}

注意:

  • 使用application/config/routes.php中的路由结构,您可以为所有HTTP VERB设置相同的控制器名称!
  • 只需使用$this->load->helper('form')加载表单助手即可使用视图中的<?= method_field('PUT') ?>或使用<input type="hidden" name="__method" value="PUT">
  • 我使用了隐藏的表单字段名称__method而不是Laravel的_method,因为可以使用这样的字段名称​​(+双下划线是CodeIgniter-ish)
  • EDIT 也可以欺骗GET请求。 EG:http://project-name/controller/action?__method=PATCH将启动PATCH控制器!