Symfony5.4集成FullCalendarJS遇404及数据不全问题求助
Symfony5.4集成FullCalendarJS事件更新问题解决
1. 替换XHR为Fetch API
直接用Fetch替代原有XHR代码,同时处理Symfony的CSRF验证和请求格式:
// 从Twig模板获取CSRF令牌 const csrfToken = document.querySelector('meta[name="csrf-token"]').content; // 事件更新请求示例(放在FullCalendar的eventDrop/eventResize回调中) fetch('/calendar/update-event', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken }, body: JSON.stringify({ id: info.event.id, start: info.event.start.toISOString(), end: info.event.end.toISOString(), title: info.event.title }) }) .then(response => { if (!response.ok) { // 更新失败时恢复事件原位置 info.revert(); throw new Error(`HTTP状态码: ${response.status}`); } return response.json(); }) .then(result => console.log('事件更新成功:', result)) .catch(err => alert('事件更新失败: ' + err.message));
2. 修正Symfony控制器路由与逻辑
404错误大概率是路由不匹配,确保控制器路由注解正确,同时处理JSON请求和实体更新:
// src/Controller/CalendarController.php use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Doctrine\ORM\EntityManagerInterface; use App\Entity\CalendarEvent; /** * @Route("/calendar/update-event", name="calendar_update_event", methods={"POST"}) */ public function updateEvent(Request $request, EntityManagerInterface $em) { // 解析JSON请求体 $data = json_decode($request->getContent(), true); // 验证必填字段 if (!isset($data['id'], $data['start'], $data['end'])) { return new JsonResponse(['error' => '缺少必要参数'], 400); } // 查找目标事件 $event = $em->getRepository(CalendarEvent::class)->find($data['id']); if (!$event) { return new JsonResponse(['error' => '事件不存在'], 404); } // 更新事件属性 $event->setStart(new \DateTime($data['start'])); $event->setEnd(new \DateTime($data['end'])); if (isset($data['title'])) { $event->setTitle($data['title']); } $em->flush(); // 返回更新后的事件数据 return new JsonResponse([ 'success' => true, 'event' => [ 'id' => $event->getId(), 'title' => $event->getTitle(), 'start' => $event->getStart()->format('Y-m-d H:i:s'), 'end' => $event->getEnd()->format('Y-m-d H:i:s') ] ]); }
3. Twig模板补充CSRF令牌
在模板中添加CSRF令牌元标签,让JS能获取到:
{# templates/calendar/index.html.twig #} <head> <meta name="csrf-token" content="{{ csrf_token('authenticate') }}"> <!-- 引入FullCalendar的CSS和JS资源 --> </head>
4. 实体类优化建议
给事件实体添加toArray()方法,方便快速返回JSON格式数据:
// src/Entity/CalendarEvent.php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=CalendarEventRepository::class) */ class CalendarEvent { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string", length=255) */ private $title; /** * @ORM\Column(type="datetime") */ private $start; /** * @ORM\Column(type="datetime") */ private $end; // 生成对应的getter和setter方法 // 添加转换数组方法 public function toArray(): array { return [ 'id' => $this->getId(), 'title' => $this->getTitle(), 'start' => $this->getStart()->format('Y-m-d H:i:s'), 'end' => $this->getEnd()->format('Y-m-d H:i:s') ]; } }
5. FullCalendar回调配置
在初始化FullCalendar时,配置eventDrop和eventResize回调,调用上面的Fetch代码:
document.addEventListener('DOMContentLoaded', function() { const calendar = new FullCalendar.Calendar(document.getElementById('calendar'), { editable: true, // 其他配置:header、events数据源等 eventDrop: function(info) { // 调用前面的Fetch更新逻辑 const csrfToken = document.querySelector('meta[name="csrf-token"]').content; fetch('/calendar/update-event', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken }, body: JSON.stringify({ id: info.event.id, start: info.event.start.toISOString(), end: info.event.end.toISOString(), title: info.event.title }) }) .then(response => { if (!response.ok) { info.revert(); throw new Error('更新失败'); } }) .catch(err => alert('事件拖动更新失败: ' + err.message)); }, eventResize: function(info) { // 与eventDrop逻辑一致,处理事件大小调整 const csrfToken = document.querySelector('meta[name="csrf-token"]').content; fetch('/calendar/update-event', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken }, body: JSON.stringify({ id: info.event.id, start: info.event.start.toISOString(), end: info.event.end.toISOString(), title: info.event.title }) }) .then(response => { if (!response.ok) { info.revert(); throw new Error('更新失败'); } }) .catch(err => alert('事件调整大小失败: ' + err.message)); } }); calendar.render(); });
问题排查要点
- 404错误:检查Fetch请求URL与控制器路由注解的URL是否完全一致,注意大小写和路径拼写。
- 数据不完整:确保JSON请求体包含
id、start、end等必填字段,控制器中要做参数校验。 - CSRF验证失败:必须在请求头中携带
X-CSRF-Token,且令牌值正确。 - 日期解析错误:FullCalendar返回的ISO格式日期可直接用Symfony的
\DateTime解析,确保实体字段类型为datetime。
内容的提问来源于stack exchange,提问作者Miguel Ángel
相关产品推荐
相关产品推荐

