Symfony 5: непредвиденное значение не может быть нормализовано: ресурс потока
Код
Класс сущности
use Doctrine\ORM\Mapping as ORM;
/**
* Device
*
* @ORM\Table(name="device", uniqueConstraints={@ORM\UniqueConstraint(name="uid", columns={"uid"})}, indexes={@ORM\Index(name="device__visitor_id", columns={"visitor_id"})})
* @ORM\Entity
*/
class Device
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var binary|null
*
* @ORM\Column(name="uid", type="binary", nullable=true, options={"comment"="Agent cookie ID (Cross-site tracking)"})
*/
private $uid;
/**
* @var string
*
* @ORM\Column(name="ua", type="string", length=511, nullable=false, options={"comment"="HTTP User agent"})
*/
private $ua;
/**
* @var string|null
*
* @ORM\Column(name="os", type="string", length=128, nullable=true, options={"comment"="User operating system (from WhichBrowser)"})
*/
private $os;
/**
* @var string|null
*
* @ORM\Column(name="browser_name", type="string", length=128, nullable=true, options={"comment"="Browser name (from WhichBrowser)"})
*/
private $browserName;
/**
* @var string|null
*
* @ORM\Column(name="browser", type="string", length=255, nullable=true, options={"comment"="Full browser name (from WhichBrowser)"})
*/
private $browser;
/**
* @var string|null
*
* @ORM\Column(name="device_type", type="string", length=32, nullable=true, options={"comment"="Device type (from WhichBrowser)"})
*/
private $deviceType;
/**
* @var string|null
*
* @ORM\Column(name="device", type="string", length=128, nullable=true, options={"comment"="Full device name (from WhichBrowser)"})
*/
private $device;
/**
* @var int|null
*
* @ORM\Column(name="width", type="integer", nullable=true, options={"comment"="User screen width"})
*/
private $width;
/**
* @var int|null
*
* @ORM\Column(name="height", type="integer", nullable=true, options={"comment"="User screen height"})
*/
private $height;
/**
* @var int
*
* @ORM\Column(name="c_utime", type="integer", nullable=false, options={"comment"=" Unix time in GMT"})
*/
private $cUtime;
public function getId(): ?int
{
return $this->id;
}
public function getUid()
{
return $this->uid;
}
public function setUid($uid): self
{
$this->uid = $uid;
return $this;
}
public function getUa(): ?string
{
return $this->ua;
}
public function setUa(string $ua): self
{
$this->ua = $ua;
return $this;
}
public function getOs(): ?string
{
return $this->os;
}
public function setOs(?string $os): self
{
$this->os = $os;
return $this;
}
public function getBrowserName(): ?string
{
return $this->browserName;
}
public function setBrowserName(?string $browserName): self
{
$this->browserName = $browserName;
return $this;
}
public function getBrowser(): ?string
{
return $this->browser;
}
public function setBrowser(?string $browser): self
{
$this->browser = $browser;
return $this;
}
public function getDeviceType(): ?string
{
return $this->deviceType;
}
public function setDeviceType(?string $deviceType): self
{
$this->deviceType = $deviceType;
return $this;
}
public function getDevice(): ?string
{
return $this->device;
}
public function setDevice(?string $device): self
{
$this->device = $device;
return $this;
}
public function getWidth(): ?int
{
return $this->width;
}
public function setWidth(?int $width): self
{
$this->width = $width;
return $this;
}
public function getHeight(): ?int
{
return $this->height;
}
public function setHeight(?int $height): self
{
$this->height = $height;
return $this;
}
public function getCUtime(): ?int
{
return $this->cUtime;
}
public function setCUtime(int $cUtime): self
{
$this->cUtime = $cUtime;
return $this;
}
}
Класс репозитория
namespace App\Repository;
use App\Entity\Device;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class DeviceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Device::class);
}
}
Класс контроллера
use App\Repository\DeviceRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class DashboardController extends AbstractController
{
/**
* @var DeviceRepository
*/
private $deviceRepository;
/**
* DashboardController constructor.
* @param DeviceRepository $deviceRepository
*/
public function __construct(
DeviceRepository $deviceRepository
) {
$this->deviceRepository = $deviceRepository;
}
/**
* @Route("device/{device_id}/details", name="device.details")
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function getDevice(Request $request)
{
$id = $request->get('device_id');
$device = $this->deviceRepository->find($id);
return $this->json($device);
}
}
Ожидаемый результат
{
id: 1,
uid: "<<some string here>>"
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 127.0.0.22.119 (iPhone11,6; iOS 13_3; en_US; en-US; scale=3.00; 1242x2688; 196215991)"
os: "iOS 13.3"
browserName: "Instagram"
browser: "Instagram 127.0.0.22"
deviceType: "mobile"
device: "Apple iPhone XS Max"
width: "414"
height: "896"
cUtime: 1581304156
}
ошибка
500 (внутренняя ошибка сервера) Не удалось нормализовать непредвиденное значение: ресурс потока
Трассировка стека в Chrome DevTool
{
type: "https://tools.ietf.org/html/rfc2616#section-10",
title: "An error occurred",
status: 500,
detail: "An unexpected value could not be normalized: stream resource",
class: "Symfony\Component\Serializer\Exception\NotNormalizableValueException",
trace: {
{
namespace: ""
short_class: ""
class: ""
type: ""
function: ""
file: "/var/www/html/awtracker/vendor/symfony/serializer/Serializer.php"
line: 170
}, {
namespace: "Symfony\Component\Serializer"
short_class: "Serializer"
class: "Symfony\Component\Serializer\Serializer"
type: "->"
function: "normalize"
file: "/var/www/html/awtracker/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php"
line: 201
}, {
namespace: "Symfony\Component\Serializer\Normalizer"
short_class: "AbstractObjectNormalizer"
class: "Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer"
type: "->"
function: "normalize"
file: "/var/www/html/awtracker/vendor/symfony/serializer/Serializer.php"
line: 146
}, {
namespace: "Symfony\Component\Serializer"
short_class: "Serializer"
class: "Symfony\Component\Serializer\Serializer"
type: "->"
function: "normalize"
file: "/var/www/html/awtracker/vendor/symfony/serializer/Serializer.php"
line: 119
}, {
namespace: "Symfony\Component\Serializer"
short_class: "Serializer"
class: "Symfony\Component\Serializer\Serializer"
type: "->"
function: "serialize"
file: "/var/www/html/awtracker/vendor/symfony/framework-bundle/Controller/AbstractController.php"
line: 174
}, {
namespace: "Symfony\Bundle\FrameworkBundle\Controller"
short_class: "AbstractController"
class: "Symfony\Bundle\FrameworkBundle\Controller\AbstractController"
type: "->"
function: "json"
file: "/var/www/html/awtracker/src/Controller/DashboardController.php"
line: 32
}, {
short_class: "DashboardController"
class: "App\Controller\DashboardController"
type: "->"
function: "paginate"
file: "/var/www/html/awtracker/vendor/symfony/http-kernel/HttpKernel.php"
line: 145
}, {
namespace: "Symfony\Component\HttpKernel"
short_class: "HttpKernel"
class: "Symfony\Component\HttpKernel\HttpKernel"
type: "->"
function: "handleRaw"
file: "/var/www/html/awtracker/vendor/symfony/http-kernel/HttpKernel.php"
line: 67
}, {
namespace: "Symfony\Component\HttpKernel"
short_class: "HttpKernel"
class: "Symfony\Component\HttpKernel\HttpKernel"
type: "->"
function: "handle"
file: "/var/www/html/awtracker/vendor/symfony/http-kernel/Kernel.php"
line: 191
}, {
namespace: "Symfony\Component\HttpKernel"
short_class: "Kernel"
class: "Symfony\Component\HttpKernel\Kernel"
type: "->"
function: "handle"
file: "/var/www/html/awtracker/public/index.php"
line: 25
}
}
}
Код написан на Symfony 5 и php 7.2.5. Это код API, и возвращаемые данные должны быть в формате JSON. Это уникальная ошибка, и я не смог найти достаточно информации для ее решения.
1 ответ
У меня такая же проблема, от бинарного типа. Вот что говорится об этом типе в документации Doctrine:
Сопоставляет и преобразует двоичные строковые данные с максимальной длиной. Если вы знаете, что сохраняемые данные всегда соответствуют указанной длине, вам следует подумать об использовании этого типа. Значения, полученные из базы данных, всегда преобразуются в тип ресурса PHP или в null, если данные отсутствуют.
В моем случае я изменил type="binary" на type="boolean", и он работает.
В вашем случае вы можете подумать об использовании типа данных guid или о приведении в свой геттер следующим образом:
public function getUid()
{
return (string) $this->uid;
}
Получателю требуется обновление:
public function getUid(): ?string
{
return is_resource($this->uid) ? stream_get_contents($this->uid) : $this->uid;
}
В дополнение к этому вам может потребоваться добавить в свой код некоторые хитрости, например:
$device->setUid($device->getUid());
После прочтения строки из таблицы устройств у вас может быть сущность, у которой тип свойства uid - "stream_resource". Вызов установщика с возвращаемым значением получателя сделает его строкой.