我遇到了一个问题,我需要能够在mysql数据库中放置一个NULL 值。因此,我从前端发送一个基本的javascript对象:
{
"Info": {
"Name": "Michelangelo",
"Date" : null
}
}
在我的PHP文件中,我确实正确获取了请求并对其进行了解码:
if(isset($postdata) && !empty($postdata)) {
// Extract the data.
$request = json_decode($postdata);
}
它适用于字符串、布尔值、整数,但不适用于null
值。解码后,它将在PHP中输出,例如null
而不是NULL
。据我所知,PHP 中唯一正确的值是 NULL:https://www.php.net/manual/en/language.types.null.php
我把这样的值放在数据库中。日期列的类型为 date,它接受NULL
值。但是,使用null
它将转换为 0000-00-00;
$sql = "UPDATE `users` SET
`Username`='$request->Info->Name',
`Date`='$request->Info->Date' //DB accepts NULL but not null (tested)
WHERE `id` = '{$id}' LIMIT 1";
那么为什么它不能正确转换呢?我知道我可以遍历对象并用NULL
值替换所有null
,但由于对象具有嵌套,这将是一个令人头疼的问题。我该如何解决这个问题,为什么会发生这种情况?我更愿意用PHP而不是在sql查询中做到这一点。
问题是因为你把"null"放在单引号之间!
`Date`='$request->Info->Date'
解决方案:在预准备语句中使用绑定参数。 https://www.php.net/manual/en/pdo.prepare.php
$pdo = new PDO($dsn, $user, $pass, $options);
$sth = $pdo->prepare("UPDATE `users` SET
`Username`=:username, `Date`=:date
WHERE `id` = :id LIMIT 1");
$sth->bindParam(':username', $request->Info->Name, PDO::PARAM_STR);
$sth->bindParam(':date', $request->Info->Date);
$sth->bindParam(':id', $id);
$sth->execute();
您应该构建一些验证类,它将从您将在查询中使用的请求中返回正确的(净化(值。
考虑创建一些类/逻辑,例如
final class InfoRequest
{
/** @var array */
private $info;
public function __construct($request)
{
$this->info = $request->Info;
}
public function date(): ?string
{
$date = $this->info['Date'];
if (!$this->isValidDate($date)) {
throw NotValidDateException();
}
if (!$date) {
return null;
}
$dateTime = new DateTime($this->info['Date']);
return $dateTime->format('Y-m-d');
}
private function isValidDate($date): bool
{
return true; // TODO: Not implemented yet
}
public function name(): string
{
$name = $this->info['Name'];
if (!$this->isValidName($name)) {
throw NotValidNameException();
}
return $name;
}
private function isValidName($name): bool
{
return true; // TODO: Not implemented yet
}
}
用法:
$info = new InfoRequest($request);
$sth->bindParam(':username', $info->name(), PDO::PARAM_STR);
除此之外,切勿将请求中的直接输入传递到原始查询中到数据库。
通常,最好不要直接从用户输入中获取值(无论您认为应该多么信任源(。 另见强制性的xkcd。
由于您现在在构建查询时映射和清理数据(可能使用预准备语句(,因此将值null
映射到字符串"NULL"
(或者只是让准备好的语句库处理它(应该是微不足道的。
该问题与NULL 或 null 的变化无关。 在PHP中,它们是一回事。
您可能在MySQL NO_ZERO_DATE模式下运行,该模式用零填充空日期。以下命令更改了 MySQL 处理空日期的方式。
SET sql_mode = 'NO_ZERO_DATE';
更多信息在这里。