You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:10:28