Symfony EasyAdminBundle自定义CRUD动作:saveUsersToCsv方法未触发问题
问题描述
我正在遵循EasyAdminBundle官方教程,想要创建一个导出User类数据为CSV文件的自定义CRUD动作。目前自定义按钮已正常显示,但点击后saveUsersToCsv方法并未被调用,按钮点击后无任何反应。
我的UserCrudController代码如下:
<?php namespace App\Controller\Admin; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; use App\Entity\User; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField; class UserCrudController extends AbstractCrudController { public static function getEntityFqcn(): string { return User::class; } // 配置显示字段 public function configureFields(string $pageName): iterable { return [ TextField::new("username"), EmailField::new('email'), ArrayField::new('roles'), ]; } public function configureActions(Actions $actions): Actions { $saveCsv = Action::new('saveCsv','Save as Csv', 'fa fa-save-as-csv') ->displayAsButton() ->linkToCrudAction('saveUsersToCsv'); return $actions ->add(Crud::PAGE_DETAIL,$saveCsv); } // 生成CSV并触发下载 public function saveUsersToCsv(AdminContext $context){ // $instance = $context->getEntity()->getInstance(); $fileName = "test"; $filePath = $_SERVER["DOCUMENT_ROOT"] . $fileName . '.csv'; $output = fopen($filePath,'w+'); fputcsv($output,array("Number","Description","test")); fputcsv($output,array("100","TestDescription","10")); // 设置响应头 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename ="'.$fileName.".csv'"'); header('Content-Length: ' .filesize($filePath)); echo readfile($filePath); } }
按钮显示效果:
解决方案
1. 让按钮发起非AJAX请求
EasyAdmin默认会用AJAX处理自定义动作的请求,但下载类操作需要浏览器直接处理响应,因此必须给动作禁用AJAX:
修改configureActions方法中的动作定义:
$saveCsv = Action::new('saveCsv','Save as Csv', 'fa fa-save-as-csv') ->displayAsButton() ->linkToCrudAction('saveUsersToCsv') ->addCssClass('no-ajax'); // 关键:禁用AJAX请求
也可以设置在新窗口打开请求,避免干扰当前页面状态:
->setHtmlAttributes(['target' => '_blank'])
2. 改用Symfony标准响应处理下载
直接使用原生header()和echo会和Symfony的内核响应机制冲突,必须使用框架提供的响应类处理下载逻辑,下面提供两种方案:
方案一:使用StreamedResponse(无需生成临时文件)
直接输出CSV内容到浏览器,不需要在服务器生成临时文件:
use Symfony\Component\HttpFoundation\StreamedResponse; public function saveUsersToCsv(AdminContext $context): StreamedResponse { // 获取当前详情页的用户实例 $user = $context->getEntity()->getInstance(); $response = new StreamedResponse(function () use ($user) { $output = fopen('php://output', 'w'); // 写入CSV表头 fputcsv($output, ['Username', 'Email', 'Roles']); // 写入用户数据,将角色数组转为字符串 fputcsv($output, [ $user->getUsername(), $user->getEmail(), implode(', ', $user->getRoles()) ]); fclose($output); }); $response->headers->set('Content-Type', 'text/csv'); $response->headers->set('Content-Disposition', 'attachment; filename="user_'.$user->getId().'.csv"'); return $response; }
方案二:使用BinaryFileResponse(需生成临时文件)
如果需要在服务器保留CSV文件,可以用这个方案:
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\ResponseHeaderBag; public function saveUsersToCsv(AdminContext $context): BinaryFileResponse { $user = $context->getEntity()->getInstance(); $fileName = "user_{$user->getId()}.csv"; // 使用Symfony内置参数获取项目根目录,兼容性更强 $filePath = $this->getParameter('kernel.project_dir').'/public/'.$fileName; $output = fopen($filePath,'w+'); fputcsv($output, ['Username', 'Email', 'Roles']); fputcsv($output, [ $user->getUsername(), $user->getEmail(), implode(', ', $user->getRoles()) ]); fclose($output); $response = new BinaryFileResponse($filePath); $response->setContentDisposition( ResponseHeaderBag::DISPOSITION_ATTACHMENT, $fileName ); // 可选:下载完成后自动删除临时文件 // $response->deleteFileAfterSend(true); return $response; }
3. 额外优化:权限控制(可选)
如果需要限制特定权限用户使用导出功能,可添加权限校验:
$saveCsv = Action::new('saveCsv','Save as Csv', 'fa fa-save-as-csv') ->displayAsButton() ->linkToCrudAction('saveUsersToCsv') ->addCssClass('no-ajax') ->setPermission('EXPORT_USER'); // 对应你的权限配置
内容的提问来源于stack exchange,提问作者Steak
相关产品推荐
相关产品推荐

