CodeIgniter 中的表单方法欺骗

Form Method Spoofing in CodeIgniter

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

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

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

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

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

干杯。

我刚刚在 Laravel docs 中注意到这个功能,用谷歌搜索并找到了这个问题。我将在 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/';
$route['(.+)']['POST'] = 'post/';
$route['(.+)']['PUT'] = 'put/';
$route['(.+)']['PATCH'] = 'patch/';
$route['(.+)']['DELETE'] = 'delete/';

文件: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 动词使用相同的控制器名称!
  • 只需使用 $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 控制器!