Laravel 7 Mailable 附加多文件报错"The path cannot be empty"如何解决
Laravel 7 Mailable 多附件附加时“The path cannot be empty”问题修复
问题根源
直接触发路径报错的核心原因有三个:
- 数组嵌套层级错误:初始化附件数据时写了
$data[] = [ ... ],相当于给$data追加了一个数组元素,最终传给Mailable的$data最外层只有一个键为0的元素,值是实际想传的附件集合。在build方法里执行foreach遍历的时候,第一次循环拿到的$filePath就是整数0,根本不是合法的文件路径,直接触发“The path cannot be empty”报错。 - 附件结构不匹配attach要求:Laravel的
attach方法需要传入「合法文件字符串路径为键、附件配置数组为值」的成对键值对,但原本的内层数组把路径字符串、配置数组交替平铺存放,完全没有做键值对匹配,就算去掉外层的嵌套,遍历到配置数组元素的时候,依然会因为拿不到合法路径报错。 - 执行顺序错误:先提取临时文件路径存入附件配置,之后才调用
imageSave把临时文件移动到uploads目录,等邮件发送流程执行时,之前存的PHP临时上传路径已经因为文件被移走而失效,即使不触发路径为空的报错,也会出现附件损坏的问题。
修复方案
- 重新构造符合要求的附件数组
去掉多余的外层数组包裹,把每个文件的「临时路径-配置」做成成对的键值对,构造操作一定要在imageSave移动文件之前执行:// 先构造附件数组,此时临时文件还存在于PHP上传目录 $attachments = [ $request->filep->getRealPath() => [ 'mime' => $request->filep->getClientMimeType(), 'as' => $request->filep->getClientOriginalName() ], $request->rip->getRealPath() => [ 'mime' => $request->rip->getClientMimeType(), 'as' => $request->rip->getClientOriginalName() ], $request->fishea->getRealPath() => [ 'mime' => $request->fishea->getClientMimeType(), 'as' => $request->fishea->getClientOriginalName() ] ]; - 保持文件存储逻辑的执行顺序
构造完附件数组之后,再调用原来的imageSave方法把文件移到uploads目录做永久存储,这步操作不会影响已经拿到的临时路径(因为临时路径在文件被读取附加到邮件时是有效的,只要在发送前没有被删除/移动即可):$filep = $this->imageSave($request->filep,'uploads/cin/'); $rip = $this->imageSave($request->rip,'uploads/rip/'); $fishea = $this->imageSave($request->fishea,'uploads/anthropo/'); // 后续数据库存储逻辑和原有代码保持一致 - 调整Mailable类的接收与遍历逻辑
把上面构造的$attachments数组直接传给SendMailP,不要多套数组:
在SendMailP类中定义公开属性接收附件数据,修正build方法的遍历逻辑:Mail::to($admin_email)->send(new SendMailP($attachments));// 类属性定义 public $attachments; public function __construct(array $attachments) { $this->attachments = $attachments; } public function build() { $mail = $this->subject('[organisation] Sujet ') ->markdown('frontend.contact.mail.contact-form'); // 遍历 路径=>配置 的结构,逐个附加文件 foreach ($this->attachments as $filePath => $fileConfig) { $mail->attach($filePath, $fileConfig); } return $mail; }
常见踩坑提醒
- 不要在文件被
move、store方法处理之后再调用getRealPath()拿临时路径,这些操作会把文件从PHP的临时上传目录移走,临时路径对应的文件就不存在了,会出现找不到文件的错误。 - 如果要给邮件模板传业务数据,可以在
markdown方法的第二个参数里单独传值,不要把附件数组和业务数据混在同一个结构里,避免遍历逻辑混乱。
内容的提问来源于stack exchange,提问作者idr phone
相关产品推荐
相关产品推荐

