Laravel8 给不同邮箱发送对应专属内容邮件的错误排查求助
问题排查与修复方案
基础信息
现有邮箱数组
array:2 [ 0 => array:2 [ 0 => "email1@gmail.com" 1 => "email2@gmail.com" ] 1 => array:1 [ 0 => "email3@gmail.com" ] ]
分公司表存储结构
| id_filiale | adm_emails |
|---|---|
| 1 | ["email1@gmail.com","email2@gmail.com"] |
| 2 | ["email3@gmail.com"] |
需求
遍历邮箱列表,给每个邮箱发送对应关联的id_filiale下的待续约合同数据。
原有代码问题分析
第一版代码问题
Mail::send([], [], function ($m){ $today_date = Carbon::now()->addDays(60); foreach ($emails as $key3 => $value) { $filiale = Filiale::where('adm_email', json_encode($value)) ->select('filiales.id_filiale') ->value('filiales.id_filiale'); $contras = Projet_Casting::join('contrats','contrats.id_contrat','=','projets_castings.id_contrat') ->leftjoin('projets','projets.id_projet','=','projets_castings.id_projet') ->join('castings','castings.id_casting','=','contrats.id_casting') ->where('contrats.actif',1) ->where('contrats.date_fin_contrat', '<=', $today_date) ->where('projets.id_filiale',$filiale) ->get(); foreach($value as $val =>$v){ $m->to($v,'Notify')->subject('Contrats à renouveler')->setBody($contras); } } });
所有逻辑写在同一个Mail::send的闭包内,全程复用同一个邮件实例$m,每次调用to()和setBody()都会覆盖之前的设置,最终所有收件人收到的都是最后一次设置的内容。
第二版代码问题
$today_date = Carbon::now()->addDays(60); $contrat_email = Projet_Casting::join('contrats','contrats.id_contrat','=','projets_castings.id_contrat')->leftjoin('projets','projets.id_projet','=','projets_castings.id_projet')->join('castings','castings.id_casting','=','contrats.id_casting')->join('filiales','projets.id_filiale','=','filiales.id_filiale')->where('contrats.actif',1)->where('contrats.date_fin_contrat', '<=', $today_date)->distinct('filiales.id_filiale')->get(); $emails = array(); foreach($contrat_email as $key) { $emails[] = json_decode($key->adm_email); } $email_send = array(); foreach ($emails as $key3 => $value) { $filiale =Filiale::where('adm_email', json_encode($value))->select('filiales.id_filiale')->value('filiales.id_filiale'); $contras = Projet_Casting::join('contrats','contrats.id_contrat','=','projets_castings.id_contrat')->leftjoin('projets','projets.id_projet','=','projets_castings.id_projet')->join('castings','castings.id_casting','=','contrats.id_casting')->where('contrats.actif',1)->where('contrats.date_fin_contrat', '<=', $today_date)->where('projets.id_filiale',$filiale)->get(); foreach($value as $val =>$v){ $ema = $v; } Mail::send([],[], function ($m){ $m->to($ema,'Notify')->subject('Contrats à renouveler')->setBody($contras); }); }
- 闭包作用域问题:PHP匿名函数默认无法直接访问外部变量,没有用
use将$ema和$contras传入闭包,所以报Undefined variable: ema错误。 - 邮箱赋值逻辑错误:遍历邮箱数组时只把最后一个邮箱赋值给
$ema,同一个分公司下的多个邮箱只有最后一个能收到邮件。 - 冗余查询:已经从
$contrat_email中拿到了分公司数据,不需要再次查询id_filiale。
修复后的实现代码
$today_date = Carbon::now()->addDays(60); // 先查出所有有待续约合同的分公司 $filiales = Filiale::whereHas('projets.contrats', function ($query) use ($today_date) { $query->where('actif', 1) ->where('date_fin_contrat', '<=', $today_date); })->get(); foreach ($filiales as $filiale) { // 解析当前分公司的管理员邮箱列表 $emails = json_decode($filiale->adm_email, true); // 查询当前分公司对应的待续约合同 $contras = Projet_Casting::join('contrats','contrats.id_contrat','=','projets_castings.id_contrat') ->leftjoin('projets','projets.id_projet','=','projets_castings.id_projet') ->join('castings','castings.id_casting','=','contrats.id_casting') ->where('contrats.actif',1) ->where('contrats.date_fin_contrat', '<=', $today_date) ->where('projets.id_filiale', $filiale->id_filiale) ->get(); // 给每个管理员单独发送对应内容的邮件 foreach ($emails as $email) { Mail::send([], [], function ($m) use ($email, $contras) { // 注意:setBody不能直接传入集合对象,需要转成字符串/HTML/JSON,正式使用建议渲染邮件视图 $m->to($email, 'Notify') ->subject('Contrats à renouveler') ->setBody($contras->toJson()); }); } }
补充说明:如果需要发送格式化的合同内容,建议创建专属的邮件视图,把合同数据传入视图渲染后再作为邮件内容,可读性更强。
内容的提问来源于stack exchange,提问作者saadia
相关产品推荐
相关产品推荐

