symfony serialize() 作为成员变量从 __sleep() 返回但不存在
symfony serialize() returned as member variable from __sleep() but does not exist
在做了一些与此操作无关的实体更改后,我突然开始收到此错误
Notice: serialize(): "questionPools" returned as member variable from __sleep() but does not exist
操作看起来像这样:
/**
* @param UserProvider $userProvider
* @param Exam $exam
* @param ExamService $examService
* @Route("/start/{id}", name="/start")
*/
public function startAction(UserProvider $userProvider, Exam $exam, ExamService $examService)
{
try {
$userExam = $examService->startExam($exam);
$userExam->setUser($userProvider->getUser());
$this->db()->persist($userExam);
$this->db()->flush();
} catch (RuntimeException $exception) {
$this->addFlash('danger', $exception->getMessage());
return $this->redirectToRoute('userExam/available');
} catch (Exception $exception) {
$this->addFlash('danger', $exception->getMessage());
return $this->redirectToRoute('userExam/available');
}
return $this->redirectToRoute('userExam/fill', ['hash' => $userExam->getHash()]);
}
堆栈跟踪指向供应商,因为错误发生在重定向期间。
“questionPools”是 Exam
实体的 属性:
/**
* Class Exam
* @package App\Entity
* @ORM\Entity(repositoryClass="App\Repository\ExamRepository")
* @ORM\Table(name="exam",indexes={@ORM\Index(name="search_idx", columns={"start", "stop"})})
*/
class Exam implements EntityInterface
{
// Time in minutes
const DEFAULT_TIME = 30;
const DEFAULT_THRESHOLD = 80;
use IdTrait;
/**
* @var Collection|QuestionPool[]
* @ORM\OneToMany(targetEntity="App\Entity\QuestionPool",
* mappedBy="exam",
* cascade={"persist", "remove"},
* orphanRemoval=true,
* )
*/
private Collection $questionPools;
startExam(Exam $exam)
ExamService
class 的方法不会改变这个集合,只会基于它创建一个 UserExam
对象。它应该传递这个对象,我不明白为什么会抛出一些序列化错误。
我认为它与缓存有关,但我什至手动删除了 /var/cache/dev 目录以确保它不是那个。
为了清楚起见,这里是堆栈跟踪:
ErrorException:
Notice: serialize(): "questionPools" returned as member variable from __sleep() but does not exist
at W:\wamp64\www\exams\vendor\symfony\security-http\Firewall\ContextListener.php:178
at Symfony\Component\Security\Http\Firewall\ContextListener->onKernelResponse(object(ResponseEvent), 'kernel.response', object(TraceableEventDispatcher))
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\Debug\WrappedListener.php:117)
at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(ResponseEvent), 'kernel.response', object(TraceableEventDispatcher))
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\EventDispatcher.php:230)
at Symfony\Component\EventDispatcher\EventDispatcher->callListeners(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.response', object(ResponseEvent))
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\EventDispatcher.php:59)
at Symfony\Component\EventDispatcher\EventDispatcher->dispatch(object(ResponseEvent), 'kernel.response')
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\Debug\TraceableEventDispatcher.php:151)
at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(object(ResponseEvent), 'kernel.response')
(W:\wamp64\www\exams\vendor\symfony\http-kernel\HttpKernel.php:190)
at Symfony\Component\HttpKernel\HttpKernel->filterResponse(object(RedirectResponse), object(Request), 1)
(W:\wamp64\www\exams\vendor\symfony\http-kernel\HttpKernel.php:178)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(W:\wamp64\www\exams\vendor\symfony\http-kernel\HttpKernel.php:79)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(W:\wamp64\www\exams\vendor\symfony\http-kernel\Kernel.php:195)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(W:\wamp64\www\exams\public\index.php:20)
请指教,我真的迷路了。谢谢。
EntityInterface 看起来像这样:
interface EntityInterface
{
public function getId(): ?int;
}
而 IdTrait 是:
use Doctrine\ORM\Mapping as ORM;
trait IdTrait
{
/**
* @var int
* @ORM\Column(type="integer")
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
*/
private int $id;
/**
* @return int
*/
public function getId(): ?int
{
if (empty($this->id)) {
return null;
}
return $this->id;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
}
此外,导致问题的重定向导致的操作:
/**
* @param UserProvider $userProvider
* @param Request $request
* @param ExamService $examService
* @param string $hash
* @return JsonResponse|RedirectResponse|Response
* @Route("/fill/{hash}", name="/fill")
*/
public function fillAction(
UserProvider $userProvider,
Request $request,
ExamService $examService,
string $hash
)
{
/** @var UserExam $userExam */
$userExam = $this->getRepo(UserExam::class)->findOneBy(['hash' => $hash]);
if (!$userProvider->checkUser($userExam->getUser())) {
throw $this->createNotFoundException('Exam belongs to someone else.');
}
if (!$userExam->isOngoing()) {
return $this->redirectToRoute('userExam/show', ['id' => $userExam->getId()]);
}
$form = $this->createForm(UserExamFormType::class, $userExam);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$exam = $examService->checkExam($userExam, $form->get('finish')->isClicked());
$this->db()->persist($exam);
$this->db()->flush();
$this->db()->refresh($userExam);
if (!$userExam->isOngoing()) {
return $this->redirectToRoute('userExam/show', ['id' => $userExam->getId()]);
}
} catch (Exception $exception) {
$this->addFlash('danger', $exception->getMessage());
}
}
return $this->response(
[
'form' => $form->createView(),
'pageName' => $userExam->getExam()->getName()
]
);
}
我正在使用当前版本的 Symfony (5.2.4) 和 Doctrine (2.7 ORM)
通过聊天,我们发现根据文档需要有 SerializationInterface - https://symfony.com/doc/current/security/user_provider.html#understanding-how-users-are-refreshed-from-the-session
我为考试实体实现了可序列化接口,方法如下所示:
public function serialize()
{
return json_encode(['id' => $this->id]);
}
public function unserialize($serialized)
{
$data = json_decode($serialized, true);
$this->id = $data['id'];
}
有效,没有错误,但我认为这只是一个丑陋的解决方法。
在做了一些与此操作无关的实体更改后,我突然开始收到此错误
Notice: serialize(): "questionPools" returned as member variable from __sleep() but does not exist
操作看起来像这样:
/**
* @param UserProvider $userProvider
* @param Exam $exam
* @param ExamService $examService
* @Route("/start/{id}", name="/start")
*/
public function startAction(UserProvider $userProvider, Exam $exam, ExamService $examService)
{
try {
$userExam = $examService->startExam($exam);
$userExam->setUser($userProvider->getUser());
$this->db()->persist($userExam);
$this->db()->flush();
} catch (RuntimeException $exception) {
$this->addFlash('danger', $exception->getMessage());
return $this->redirectToRoute('userExam/available');
} catch (Exception $exception) {
$this->addFlash('danger', $exception->getMessage());
return $this->redirectToRoute('userExam/available');
}
return $this->redirectToRoute('userExam/fill', ['hash' => $userExam->getHash()]);
}
堆栈跟踪指向供应商,因为错误发生在重定向期间。
“questionPools”是 Exam
实体的 属性:
/**
* Class Exam
* @package App\Entity
* @ORM\Entity(repositoryClass="App\Repository\ExamRepository")
* @ORM\Table(name="exam",indexes={@ORM\Index(name="search_idx", columns={"start", "stop"})})
*/
class Exam implements EntityInterface
{
// Time in minutes
const DEFAULT_TIME = 30;
const DEFAULT_THRESHOLD = 80;
use IdTrait;
/**
* @var Collection|QuestionPool[]
* @ORM\OneToMany(targetEntity="App\Entity\QuestionPool",
* mappedBy="exam",
* cascade={"persist", "remove"},
* orphanRemoval=true,
* )
*/
private Collection $questionPools;
startExam(Exam $exam)
ExamService
class 的方法不会改变这个集合,只会基于它创建一个 UserExam
对象。它应该传递这个对象,我不明白为什么会抛出一些序列化错误。
我认为它与缓存有关,但我什至手动删除了 /var/cache/dev 目录以确保它不是那个。
为了清楚起见,这里是堆栈跟踪:
ErrorException:
Notice: serialize(): "questionPools" returned as member variable from __sleep() but does not exist
at W:\wamp64\www\exams\vendor\symfony\security-http\Firewall\ContextListener.php:178
at Symfony\Component\Security\Http\Firewall\ContextListener->onKernelResponse(object(ResponseEvent), 'kernel.response', object(TraceableEventDispatcher))
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\Debug\WrappedListener.php:117)
at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(ResponseEvent), 'kernel.response', object(TraceableEventDispatcher))
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\EventDispatcher.php:230)
at Symfony\Component\EventDispatcher\EventDispatcher->callListeners(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.response', object(ResponseEvent))
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\EventDispatcher.php:59)
at Symfony\Component\EventDispatcher\EventDispatcher->dispatch(object(ResponseEvent), 'kernel.response')
(W:\wamp64\www\exams\vendor\symfony\event-dispatcher\Debug\TraceableEventDispatcher.php:151)
at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(object(ResponseEvent), 'kernel.response')
(W:\wamp64\www\exams\vendor\symfony\http-kernel\HttpKernel.php:190)
at Symfony\Component\HttpKernel\HttpKernel->filterResponse(object(RedirectResponse), object(Request), 1)
(W:\wamp64\www\exams\vendor\symfony\http-kernel\HttpKernel.php:178)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(W:\wamp64\www\exams\vendor\symfony\http-kernel\HttpKernel.php:79)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(W:\wamp64\www\exams\vendor\symfony\http-kernel\Kernel.php:195)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(W:\wamp64\www\exams\public\index.php:20)
请指教,我真的迷路了。谢谢。
EntityInterface 看起来像这样:
interface EntityInterface
{
public function getId(): ?int;
}
而 IdTrait 是:
use Doctrine\ORM\Mapping as ORM;
trait IdTrait
{
/**
* @var int
* @ORM\Column(type="integer")
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
*/
private int $id;
/**
* @return int
*/
public function getId(): ?int
{
if (empty($this->id)) {
return null;
}
return $this->id;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
}
此外,导致问题的重定向导致的操作:
/**
* @param UserProvider $userProvider
* @param Request $request
* @param ExamService $examService
* @param string $hash
* @return JsonResponse|RedirectResponse|Response
* @Route("/fill/{hash}", name="/fill")
*/
public function fillAction(
UserProvider $userProvider,
Request $request,
ExamService $examService,
string $hash
)
{
/** @var UserExam $userExam */
$userExam = $this->getRepo(UserExam::class)->findOneBy(['hash' => $hash]);
if (!$userProvider->checkUser($userExam->getUser())) {
throw $this->createNotFoundException('Exam belongs to someone else.');
}
if (!$userExam->isOngoing()) {
return $this->redirectToRoute('userExam/show', ['id' => $userExam->getId()]);
}
$form = $this->createForm(UserExamFormType::class, $userExam);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$exam = $examService->checkExam($userExam, $form->get('finish')->isClicked());
$this->db()->persist($exam);
$this->db()->flush();
$this->db()->refresh($userExam);
if (!$userExam->isOngoing()) {
return $this->redirectToRoute('userExam/show', ['id' => $userExam->getId()]);
}
} catch (Exception $exception) {
$this->addFlash('danger', $exception->getMessage());
}
}
return $this->response(
[
'form' => $form->createView(),
'pageName' => $userExam->getExam()->getName()
]
);
}
我正在使用当前版本的 Symfony (5.2.4) 和 Doctrine (2.7 ORM)
通过聊天,我们发现根据文档需要有 SerializationInterface - https://symfony.com/doc/current/security/user_provider.html#understanding-how-users-are-refreshed-from-the-session
我为考试实体实现了可序列化接口,方法如下所示:
public function serialize()
{
return json_encode(['id' => $this->id]);
}
public function unserialize($serialized)
{
$data = json_decode($serialized, true);
$this->id = $data['id'];
}
有效,没有错误,但我认为这只是一个丑陋的解决方法。