Reputation:
My question is very related to this question but not quite the same. It's a follow up question on my previous one if you have read it but it doesn't depend on it that much, so reading this question only should be enough. I have this method to save a 'touch' on a 'cabin' (I know it's odd). I (try to) do so be extracting information from a POST request, and test it using 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);
}
and the Touch class consists of the following:
<?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);
}
}
But when running this code I'm getting this error:
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)
I'm passing the data using POSTMAN:
[
{
"id": 666,
"cabinet_id": 55,
"time": {
"date": "2018-06-18 11:51:22.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"toucher": "person1",
}
]
Which is the correct layout for a DateTime object so I'm not sure why this error is happening nor how to solve it. Any help would be appreciated!
Upvotes: 2
Views: 14898
Reputation: 52493
The issue is you're passing a string to the constructor of Touch
but you're type-hinting with DateTime $time
so it expects a DateTime
object.
To fix your issue convert the string to DateTime
before passing it to the constructor.
/** @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);
Tip: Consider using DateTimeImmutable
instead of DateTime
.
Upvotes: 2