若要解决PDO NULL问题,请在PHPMyAdmin中将字段更改为NULL或在代码中检查NULL,如果是,请设置为空字符串?

若要解决PDO NULL问题,请在PHPMyAdmin中将字段更改为NULL或在代码中检查NULL,如果是,请设置为空字符串?,php,mysql,pdo,phpmyadmin,Php,Mysql,Pdo,Phpmyadmin,我的PHP网站有一个表单,可以使用PDO将数据插入mysql。例如,表单上的一个字段是“email” 这不是必需的。因此,在提交时,我在插入之前使用以下命令设置电子邮件变量: $email=$_POST['email']; 然后我使用PDO准备好的语句插入。以前,当使用mysqli进行插入时,它将作为空白插入,没有问题。但现在对于PDO,如果他们将其留空,则会导致: Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity c

我的PHP网站有一个表单,可以使用PDO将数据插入mysql。例如,表单上的一个字段是“email”

这不是必需的。因此,在提交时,我在插入之前使用以下命令设置电子邮件变量:

$email=$_POST['email'];
然后我使用PDO准备好的语句插入。以前,当使用mysqli进行插入时,它将作为空白插入,没有问题。但现在对于PDO,如果他们将其留空,则会导致:

Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null in...
我研究过,PDO似乎不允许插入空值,除非MySQL被告知可以接收空值。看来我有两个选择

1.  In MySQL (via PHPMyAdmin), check the "Null" checkbox for that column under "Structure"
2.  In the code, add a small snippet like this:

if (empty($email)) {
$email="";  //set it equal to blank, which allows it to get inserted into the database without needing to mark the field as NULL in MySQL
}
我想知道选项1或选项2的优点/缺点是什么?我有时可能有很多表单选项可以留空,因此,在这方面,为所有表单添加
if(empty())
代码段可能需要更多的工作

那么#1是最佳选择吗


还是我缺少了另一个选项?

您得到的错误来自数据库,而不是PDO,PDO只是访问数据库的一种方式

回到您的问题,显而易见的答案是,如果您的应用程序中有一个可选字段,那么应该将其列设置为可空

如果选择其他选项,即:

if (empty($email)) {
   $email="";  
}
我不是说这不好,只是想象一下,在某个时刻,您需要向应用程序添加更多字段,并且大多数字段都是可选的,您是否要对每个字段进行可空性测试


如果我是你,我就不会这么做。

你应该始终验证提交到申请中的每个字段。不仅要确保每个条目符合数据库完整性,还要帮助防止SQL注入(PDO)跨站点脚本甚至数据的有效性。虽然电子邮件地址可能是可选的,但为什么不确保有人提供了格式正确的电子邮件地址,并且输入中没有多余的字符(如空格)

例如:

if( empty( $_POST["email"] ) )
{
    $email = "";
} else
{
    $email = strtolower( cleanInput( $_POST["email"] ) );

    // check if e-mail address syntax is valid or not
    if ( !preg_match( "/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/", $email ) )
    {
        $emailError = "Invalid email format";
    }
}

/*
* Function to clean input prior to processing
*/
function cleanInput( $data )
{
    $data = trim( $data );
    $data = stripslashes( $data );
    $data = htmlspecialchars( $data );
    return $data;
}

选项1:此PDO insert语句应使用空值:

$row = [
    'email' => $_POST['email']
];
$sql = "INSERT INTO users SET email=:email;";
$status = $pdo->prepare($sql)->execute($row);

if ($status) {
    echo "OK";
}
选项2:自动检测正确的PDO数据类型参数

function get_pdo_type($value)
{
    switch (true) {
        case is_bool($value):
            $dataType = PDO::PARAM_BOOL;
            break;
        case is_int($value):
            $dataType = PDO::PARAM_INT;
            break;
        case is_null($value):
            $dataType = PDO::PARAM_NULL;
            break;
        default:
            $dataType = PDO::PARAM_STR;
    }
    return $dataType;
}

// Usage
$email = $_POST['email'];

$pdo = new PDO('dsn', 'username', 'password');
$sql = 'INSERT INTO users SET email=:email;';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':email', $email, get_pdo_type($email));
$stmt->execute();

如果允许空值,则应更改表约束。如果允许空值,则只需将其设置为可空。它不会在输出时打扰您,因为
仍将显示为空字符串消息声明是您的数据库,而不是不允许空值的PDO。在插入电子邮件之前,尝试
var\u dump($email);模具()
查看变量是否设置为null或no。@Anwar Nairi,奇怪的是,在我转换为PDO(使用与ExText相同的数据库结构的mysqli)之前,数据库会接受空的$email字段。所以,也许只是PDO更严格还是什么?不太确定。在“结构”选项卡中编辑字段时,请查找“空”复选框。取消选中时,这相当于NOTNULL语句。谢谢。这是一个普遍的经验法则,即数据库中所有可选字段都应设置为可空?在验证过程中,您不应删除斜杠或转义HTML。相反,请分别使用准备好的语句和仅在输出时转义。@Mikey视情况而定。这只是一个例子
stripslashes()
有助于防止那些仍将该设置为默认设置的系统出现问题,根据字段的不同,
htmlspecialchars()
可以作为防止XSS的一种方法。您还可以根据您的应用程序选择将XSS保护放在输出上。
\one@address.com
不是有效的电子邮件,但将通过您的验证。如果他们在放斜杠和/或HTML代码,那么这是一封糟糕的电子邮件。@Mikey说得对。这就是我从即兴演奏中得到的。使它更准确一点。