49

我正在尝试重新学习一些 PHP 基础知识来制作一个简单的登录脚本,但是我收到了一个我以前没有收到过的错误(我一年多前制作了相同的脚本并且从未出现过这个错误。我将代码简化为我可以测试一下哪个区域有问题,这是问题所在:

<?php
$user = $_POST["username"];
if($user != null)
{
    echo $user;
    echo " is your username";
}
else
{
    echo "no username supplied";
}
?>

现在,当我将变量发送到脚本时,这段代码可以正常工作,但是当没有提供变量时,它会吐出一个错误。理论上这会很好,因为如果没有提供用户名/密码,那么就会出现错误。在将代码发送到脚本之前,我会检查以确保这一点,但是我担心一个空白字符串可能会以某种方式泄漏并吐出一些未知的错误。这是我得到的错误:

( ! ) Notice: Undefined index: username in C:\wamp\www\verify_login.php on line 2

Call Stack

    Time    Memory  Function    Location
1   0.0003  668576  {main}( )   ..\verify_login.php:0

未提供用户名

正如您所看到的,代码寄存器没有提供任何变量,但它给出了错误,我认为这意味着没有找到一个变量是预期的或类似的东西。有人可以为我澄清一下吗?

4

10 回答 10

73

在 PHP 中,从未设置过的变量或数组元素与值为null;的变量或数组元素不同。试图访问这样一个未设置的值是一个运行时错误。

这就是您遇到的问题:该数组$_POST在 key 处没有任何元素"username",因此解释器会在您的程序进入无效测试之前中止您的程序。

幸运的是,您可以测试变量或数组元素的存在,而无需实际尝试访问它;这就是特殊运算符的isset作用:

if (isset($_POST["username"]))
{
  $user = $_POST["username"];
  echo $user;
  echo " is your username";
} 
else 
{
  $user = null;
  echo "no username supplied";
}

$_POST["username"]当 PHP 尝试获取 的值作为参数传递给函数时,这看起来会以与您的代码完全相同的方式爆炸isset()。然而,isset()它根本不是一个真正的函数,而是在评估阶段之前识别的特殊语法,因此 PHP 解释器检查该值是否存在而不实际尝试检索它。

还值得一提的是,随着运行时错误的发生,缺少的数组元素被视为次要元素(分配了E_NOTICE级别)。如果您更改error_reporting级别以忽略通知,您的原始代码实际上将按照编写的方式工作,尝试的数组访问返回null. 但这被认为是不好的做法,尤其是对于生产代码。

旁注:PHP 会进行字符串插值,因此块中的echo语句if可以合并为一个:

echo "$user is your username";
于 2012-05-30T04:23:29.397 回答
7

采用:

if (isset($_POST['user'])) {
   //do something
}

但是您可能应该使用一些更适当的验证。尝试使用 Zend Framework 或 Symfony 的简单正则表达式或坚如磐石的实现。

http://framework.zend.com/manual/en/zend.validate.introduction.html

http://symfony.com/doc/current/book/validation.html

甚至是内置的过滤器扩展:

http://php.net/manual/en/function.filter-var.php

永远不要相信用户输入,要聪明。不要相信任何东西。始终确保您收到的确实是您所期望的。如果它应该是一个数字,请确保它是一个数字。

大大改进的代码:

$user = filter_var($_POST['user'], FILTER_SANITIZE_STRING);
$isValid = filter_var($user, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => "/^[a-zA-Z0-9]+$/")));

if ($isValid) {
    // do something
}

消毒和验证。

于 2012-05-30T04:22:47.417 回答
5

而不是isset()你可以使用更短的东西来消除错误,它是@$_POST['field']. 然后,如果未设置该字段,您将不会在页面上打印任何错误。

于 2014-12-23T22:29:47.200 回答
5

在 PHP 5.2.0 及更高版本之前,您应该使用filter_input()专门为此创建的它来获取特定的外部用户输入,例如按名称获取、发布或 cookie 变量,并可选择过滤它以避免对您的站点进行任何 XSS/注入攻击。例如:

$user = filter_input(INPUT_POST, 'username');

您可以使用 INPUT_GET、INPUT_POST、INPUT_COOKIE、INPUT_SERVER 或 INPUT_ENV 之一。

通过使用可选的第三个参数,您可以通过各种过滤器(用于验证消毒过滤其他)对其进行扩展,例如FILTER_SANITIZE_SPECIAL_CHARS,FILTER_SANITIZE_ENCODED等。

例如:

<?php
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
$search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED);
echo "You have searched for $search_html.\n";
echo "<a href='?search=$search_url'>Search again.</a>";
?>

语法是:

混合filter_input( int $type , string $variable_name [, int $filter = FILTER_DEFAULT [, mixed $options ]] )

(PHP 5 >= 5.2.0,PHP 7)

另请参阅:为什么使用 filter_input() 更好?

于 2016-03-22T08:06:20.433 回答
3

您的代码假定存在某些东西:

$user = $_POST["username"];

$_POSTPHP 让您知道数组中没有“用户名” 。isset()在这种情况下,在尝试访问它之前检查该值是否会更安全:

if ( isset( $_POST["username"] ) ) {
    /* ... proceed ... */
}

或者,您可以劫持||操作员以分配默认值:

$user = $_POST["username"] || "visitor" ;

只要用户名不是虚假值,您就可以认为这种方法非常可靠。一个更安全的默认分配方法是使用三元运算符:

$user = isset( $_POST["username"] ) ? $_POST["username"] : "visitor" ;
于 2012-05-30T04:25:08.117 回答
2

试试这个:

我在有 $_POST 请求的任何地方都使用它。

$username=isset($_POST['username']) ? $_POST['username'] : "";

这只是一个简短的布尔值,如果 isset 会将其设置为 $_POST['username'],否则会将其设置为空字符串。

使用示例:

if($username===""){ echo "Field is blank" } else { echo "Success" };
于 2015-10-04T09:42:24.533 回答
2

我知道这是旧帖子,但有人可以提供帮助:

function POST($index, $default=NULL){
        if(isset($_POST[$index]))
        {
            if(!empty(trim($_POST[$index])))    
                return $_POST[$index];
        }
        return $default;
    }

上面的这段代码是我在任何地方使用的基本 POST 函数。在这里可以放过滤器、正则表达式等,更快更干净。我的高级 POST 函数在接受和检查数组、字符串类型、默认值等方面更加复杂。让你的想象力在这里发挥作用。

您可以像这样轻松检查用户名:

$username = POST("username");
if($username!==null){
    echo "{$username} is in the house.";
}

我还添加了$default字符串,如果 POST 未激活或内容不存在,您可以定义一些默认值。

echo "<h1>".POST("title", "Stack Overflow")."</h1>";

玩它。

于 2016-03-23T16:10:37.557 回答
1

当你说:

$user = $_POST["username"];

您要求 PHP 解释器分配$user$_POST(或索引)为username. 如果它不存在,PHP 就会出错。

用于isset($_POST['user'])检查该变量是否存在:

if (isset($_POST['user'])) {
  $user = $_POST["username"];
  ...
于 2012-05-30T04:23:52.323 回答
0

尝试

if(isset($_POST['username']))
    echo $_POST['username']." is your username";
else
    echo "no username supplied";
于 2012-05-30T04:25:15.677 回答
-2

相关问题: 在不生成 PHP 通知的情况下访问未知数组元素的最佳方法是什么?

使用上述问题的答案,如果密钥不存在,您可以安全地从 $_POST 获取值,而不会生成 PHP 通知。

echo _arr($_POST, 'username', 'no username supplied');  
// will print $_POST['username'] or 'no username supplied'
于 2012-05-30T04:25:27.920 回答