json_decode возвращает NULL вместо NULL при запросе на запись, не позволяет мне установить NULL в БД - PullRequest
0 голосов
/ 24 сентября 2019

У меня проблема с тем, что мне нужно иметь возможность поместить значение NULL в базу данных mysql.Поэтому из внешнего интерфейса я отправляю базовый объект 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.

Ответы [ 3 ]

5 голосов
/ 24 сентября 2019

Проблема в том, что вы помещаете «ноль» между одинарными кавычками!

`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);

Кроме того, вы никогда не должны передавать прямой ввод из запроса в необработанный запрос к БД.

1 голос
/ 24 сентября 2019

Обычно хорошей идеей является не брать значения непосредственно из пользовательского ввода (независимо от того, насколько вы думаете, что вы должны доверять источнику).См. Также обязательный xkcd .

Поскольку теперь вы отображаете и очищаете данные при построении запроса (возможно, с использованием подготовленных операторов), сопоставление значения null должно быть тривиальнымв строку "NULL" (или просто разрешите обработанной библиотеке операторов).

0 голосов
/ 24 сентября 2019

Проблема не связана с вариациями NULL или NULL.В PHP это одно и то же.

Вы, вероятно, работаете в режиме MySQL NO_ZERO_DATE, который заполняет нулевые даты нулями.Команда ниже изменяет способ обработки нулевых дат MySQL.

SET sql_mode = 'NO_ZERO_DATE';

Дополнительная информация здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...