【问题标题】:Laravel 4 : Best Practice to Trim Input before ValidationLaravel 4:验证前修剪输入的最佳实践
【发布时间】:2014-04-19 09:49:30
【问题描述】:

现在,我分别对每个输入进行修剪,如下面的代码:

$username = trim(Input::get('username'));
$password = trim(Input::get('password'));
$email    = trim(Input::get('email'));

$validator = Validator::make(array('username' => $username, 
                                   'password' => $password, 
                                   'email'    => $email), 
                             array('username' => 'required|min:6', 
                                   'password' => 'required|min:6', 
                                   'email'    => 'email'));

是否有任何方法可以同时进行修剪

Input::all()Input::only('username', 'password', 'email')?

这样做的最佳做法是什么?

【问题讨论】:

标签: php laravel laravel-4


【解决方案1】:

注意:如果您的任何输入是数组(例如“data[]”),此解决方案将不起作用。

你可以试试这个,在验证前使用这行代码修剪:

Input::merge(array_map('trim', Input::all()));

现在完成其余的编码

$username = Input::get('username'); // it's trimed 
// ...
Validator::make(...);

如果你想从修剪中排除一些输入,那么你可以使用以下来代替all()

Input::except('password');

或者你可以使用

Input::only(array('username'));

更新:由于Laravel 5.4.* 输入因新的TrimStringsmiddleware 而被修剪。因此,无需担心,因为该中间件会在每个请求上执行,并且它还处理数组输入。

【讨论】:

  • input::merge() 到底是做什么的?我在官方文档中找不到。 laravel.com/docs/requests
  • 它将新输入与旧输入合并。
  • 但是在这里,它用修剪过的输入替换了输入,因为 arra_map 返回另一个修剪过的输入数组。
  • 不错的答案。添加一行,就像在前端修剪它一样!谢谢~
  • 在使用<input name="data[]">等数组参数时不起作用
【解决方案2】:

根据您的项目,以下内容可能过于侵入/笼统/等等,无法满足您的需求;按需定制。

  • 我正在使用 this 小递归数组映射函数来处理输入数组而不会出错。
  • 任何名为 password(及其确认)的字段都被排除在外,因为人们可能希望使用空格来进一步隐藏密码。
  • 空格在某些类型的文本中具有特殊含义。例如在 Markdown 中,two or more spaces at the end of a line inserts <br>。尽管您可能在 blob 的开始或结束时不需要它。 YMMV。

app/helpers.php

/**
 * @param callable $callback
 * @param array    $array
 *
 * @return mixed
 *
 * @link http://php.net/manual/en/function.array-map.php#112857
 */
function array_map_recursive($callback, $array)
{
    foreach ($array as $key => $value) {
        if (is_array($array[$key])) {
            $array[$key] = array_map_recursive($callback, $array[$key]);
        } else {
            $array[$key] = call_user_func($callback, $array[$key]);
        }
    }

    return $array;
}

app/filters.php

App::before(
    function (\Illuminate\Http\Request $request) {
        // Trim all input
        $request->merge(
            array_map_recursive(
                "trim",
                array_except(
                    $request->all(),
                    ["password", "password_confirmation"]
                )
            )
        );
    }
);

【讨论】:

  • 您还可以通过使用实用程序类(重新运行composer dump-autoload!)来避免使用函数(周围没有对象/类)。例如。将它们放在app\libraries\Arrays.php 中,假设Arrays.php 包含一个用于数组操作的实用程序类。只是多一点 OOP。 :-)
  • 也许考虑添加类型提示。还是 Laravel 4 没有在 PHP 5 及更高版本上运行?
  • @Roland 如果这是针对我的:老实说,我已经多年没有在 Laravel(或 PHP)上工作了。所以;抱歉,不知道当前状态:)
【解决方案3】:

也许你可以使用 php 的 array_map 函数,来修剪你输入数组的内容。

$validator = Validator::make(array_map('trim',Input::all()),
                             array('username' => 'required|min:6', 
                                   'password' => 'required|min:6', 
                                   'email'    => 'email'));

或者如果你想要一个以后可以使用的变量:

$inputs = array_map('trim', Input::only('username', 'password', 'email'))

【讨论】:

  • 很好,但我认为最好分配一个以后可以与User::create()重用的变量。
【解决方案4】:
$attributes = Input::only('username', 'password', 'email');

foreach ($attributes as &$value) {
    $value = trim($value);
    //and any further preprocessing you want
}

$validator = Validator::make($attributes, array(
    'username' => 'required|min:6', 
    'password' => 'required|min:6', 
    'email'    => 'email'
));

//now you may pass preprocessed $attributes to the model create() method,
//still having the original input untouched if you may need it

通常,当它们为空时,我也使用这种方法将可选值替换为null,因为我更喜欢将它们作为NULL 而不是空字符串存储在数据库中。

【讨论】:

    【解决方案5】:

    在模型中而不是在控制器中进行修剪是一种更好的做法,因为这样您就不必在所有控制器中重复代码来一遍又一遍地修剪相同的东西:

    public function setUsernameAttribute($value)
    {
      $this->attributes['username'] = trim($value);
    }
    

    这样,您永远不必记住在控制器中修剪任何模型属性。该模型会处理它,您不必再担心它。

    就一次修剪所有内容与单独修剪所有内容而言,我认为差异是如此之小,以至于没有人会注意到差异。

    【讨论】:

    • 你想把这个因素考虑到模型中,但你为什么要给模型一个控制器的责任呢?我的意思是,在 OP 案例中,他的控制器负责清理输入数据。
    • @Alexandre Martini 控制器应该只负责接受请求和返回响应。
    【解决方案6】:

    以上的组合是最好的。通常,您需要过滤除密码和密码确认字段之外的所有输入。在过滤器中使用单行也很好。

    // app/filters.php

    App::before(function($request)
    {
        // Trim all input
        Input::merge(array_map('trim', Input::except(['password', 'password_confirmation'])));
    
    });
    

    【讨论】:

      【解决方案7】:

      改进了Halil Özgür 代码以删除所有空格、<br><br ><br class="asdasd">&nbsp

      // filters.php
      App::before(function (\Illuminate\Http\Request $request) {
          $request->merge(
              array_map_recursive(
                  "preg_replace",
                  array_except(
                      $request->all(),
                      ["password", "password_confirmation"]
                  )
              )
          );
      });
      
      // helpers.php
      function array_map_recursive($callback, $array)
      {
          foreach ($array as $key => $value) {
              if (is_array($array[$key])) {
                  $array[$key] = array_map_recursive($callback, $array[$key]);
              } else {
                  $array[$key] = call_user_func_array($callback, ['#(( ){0,}<br( {0,})(/{0,1})>){1,}$#i', '', $array[$key]]);
              }
          }
      
          return $array;
      }
      

      【讨论】:

        【解决方案8】:

        只需使用TrimStringsConvertEmptyStringsToNull 中间件。

        你不需要做任何额外的事情,因为这些中间件是 Laravel 5.4 内置的。See this Post

        编辑: What if I am not using Laravel 5.4?

        • 让我们从 Laravel 的 Github 复制代码。你可以从here得到
        • 然后确保 Laravel 知道您在 Kernel.php 中的中间件。

          受保护的 $middleware = [ // 之前的中间件 \App\Http\Middleware\TrimStrings::class, \App\Http\Middleware\ConvertEmptyStringsToNull::class, ];

        【讨论】:

        • 提问者使用的是 Laravel 4.x,而不是 5.4。但是,是的,从 5.4 开始,这是可能的。所以我没有投反对票。那么对于 5.3(大型项目)我必须坚持使用过滤器版本吗?
        • 在 Laravel 4 中,您可以将 TrimStrings 复制到您的中间件目录。并在您的路线中使用。
        • 是的,您可以不应该不要混合来自不同版本的类。 ;-) 也许它“有效”,但由于上述原因,这通常不是一个好主意。
        猜你喜欢
        • 2016-01-09
        • 1970-01-01
        • 1970-01-01
        • 2014-02-07
        • 1970-01-01
        • 2020-05-22
        • 1970-01-01
        • 1970-01-01
        • 2015-10-20
        相关资源
        最近更新 更多