Мой вопрос очень связан с этот вопрос, но не совсем то же самое. Это дополнительный вопрос к мой предыдущий, если вы его читали, но он не так сильно от него зависит, поэтому чтения только этого вопроса должно быть достаточно. У меня есть этот метод, чтобы сохранить «прикосновение» к «кабине» (я знаю, что это странно). Я (пытаюсь) извлекать информацию из запроса POST и тестировать ее с помощью POSTMAN.
/**
* @param Request $request
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
* @throws \ErrorException
* @return JsonResponse
*/
public function registerTouch(Request $request)
{
$touchService = new TouchService($this->entityManager);
$cabinet = $request->get('cabinet_id');
/**
* @var $touch Touch
*/
$touch = new Touch(
$request->get('time'),
$request->get('toucher'),
$request->get('cabinet_id'),
$request->get('id')
);
if (empty($cabinet)) {
return new JsonResponse(['error' => 'Touch not saved'], 200);
} else {
$touch->setCabinet($cabinet);
$touchService->registerTouch($touch);
return new JsonResponse(['success' => 'Touch saved'], 200);
}
а класс Touch состоит из следующего:
<?php
namespace App\Entity;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass = "App\Repository\TouchRepository")
*/
class Touch implements \JsonSerializable
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\Column(type = "datetime")
*/
private $time;
/**
* @ORM\Column(type = "string", length=255)
*/
private $toucher;
private $accountId;
/**
* @ORM\ManyToOne(targetEntity = "Cabinet")
*/
private $cabinet;
/**
* Touch constructor.
* @param DateTime $time
* @param string $toucher
* @param Cabinet $cabinet
* @param int $id
*/
public function __construct(DateTime $time, string $toucher, Cabinet $cabinet = null, int $id = null)
{
$this->time = $time;
$this->toucher = $toucher;
$this->cabinet = $cabinet;
$this->id = $id;
}
public function getId(): int
{
return $this->id;
}
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
public function getTime(): DateTime
{
return $this->time;
}
public function getToucher(): string
{
return $this->toucher;
}
public function getCabinet(): Cabinet
{
return $this->cabinet;
}
public function setCabinet(Cabinet $cabinet): self
{
$this->cabinet = $cabinet;
$this->accountId = $cabinet->getId();
return $this;
}
public function getAccountId(): int
{
return $this->accountId;
}
public function setAccountId(int $accountId): self
{
$this->accountId = $accountId;
return $this;
}
public function jsonSerialize()
{
return get_object_vars($this);
}
}
Но при запуске этого кода я получаю эту ошибку:
Argument 1 passed to App\Entity\Touch::__construct() must be an instance of DateTime, null given, called in /var/www/learningProject/src/Controller/APITouchController.php on line 89 (500 Internal Server Error)
Я передаю данные с помощью POSTMAN:
[
{
"id": 666,
"cabinet_id": 55,
"time": {
"date": "2018-06-18 11:51:22.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"toucher": "person1",
}
]
Какой правильный макет для объекта DateTime, поэтому я не уверен, почему возникает эта ошибка и как ее решить. Любая помощь будет оценена по достоинству!
@ehymel Не приведет ли это к потере формата и, возможно, данных, таких как часовой пояс? Как это будет работать? Потому что мне нужно сохранить «прикосновение» в базе данных.
@ehymel Я также пробовал вышеописанное time с этим "time": "2018-06-18 11:51:22", и все равно получаю ту же ошибку.
Для вашей Touch::__construct() функции требуется объект php DateTime. но когда вы вызываете $touch = new Touch(...), вы фактически передаете строку, независимо от того, имеет ли строка какой-то определенный формат. Прежде чем звонить new Touch(...), вы должны соответствовать требованиям типа вашего собственного кода. Смотрите мой первый комментарий.
Попробуйте dump($request) и расскажите нам, что у вас есть.




Проблема в том, что вы передаете строку конструктору Touch, но вы указываете тип с помощью DateTime $time, поэтому он ожидает объект DateTime.
Чтобы решить вашу проблему, преобразуйте строку в DateTime, прежде чем передавать ее в конструктор.
/** @var $cabinet Cabinet|null */
$cabinet = $this->entityManager->getRepository(Cabinet::class)->findOneBy([
'id' => $request->get('cabinet_id')
]);
if (null === $cabinet) {
return new JsonResponse(['error' => 'Touch not saved'], 200);
}
/** @var $touch Touch */
$touch = new Touch(
new \DateTime($request->get('time')),
$request->get('toucher'),
$cabinet,
(int)$request->get('id')
);
$touchService->registerTouch($touch);
return new JsonResponse(['success' => 'Touch saved'], 200);
Наконечник: рассмотрите возможность использования DateTimeImmutable вместо DateTime.
Спасибо за ваш ответ! Два небольших вопроса, если вы не возражаете, 1) почему DateTimeImmutable вместо этого? 2) Это действительно решило проблему, но она все еще появляется для остальных элементов Argument 2 passed to App\Entity\Touch::__construct() must be of the type integer, null given, called in /var/www/learningProject/src/Controller/APITouchController.php on line 89 (500 Internal Server Error) Должен ли я также преобразовать это в целое число и аналогичные вещи для остальных? и как это будет работать? Потому что new \int это не вещь iirc
Обновил ответ. О рекомендации DateTime vs DateTimeImmutable. В Интернете есть много статей на эту тему (например, Вот этот). Просто погуглите :)
Еще раз спасибо! И последняя проблема, я получаю это, когда печатаю намек на кабинет: Method call uses 1 parameters, but method signature uses 0 parameters less.... Мой класс кабинета в этом вопросе: stackoverflow.com/questions/56612348/… Любые идеи, что можно было бы сделать по этому поводу?
О, я вижу. тогда вам нужно будет получить объект вашего кабинета из базы данных по заданному идентификатору. Что-то вроде $this->entityManager->getRepository(Cabinet::class)->findOneBy(['id' -> $request->get('cabinet_id')]). Обновил ответ.
Несколько дней спустя, но вы случайно не знаете, почему JsonResponse не возвращается, несмотря ни на что? Все работает и тач регистрируется и все нормально, но POSTMAN дает в ответ это: { "headers": {} }. Я также пытался вернуть ответ и другие типы, но ничего не возвращается, что бы я ни пытался.
Пожалуйста, откройте новый вопрос и добавьте соответствующие части кода и информацию (действие контроллера, полезная нагрузка и т. д.).
Наличие правильного формата не делает его объектом
DateTime, в какой-то момент вам придется преобразовать его. См. этот вопрос.