Laravel双控制器共享变量:仅生成指定合同PDF的最优方案
Laravel控制器间通信:生成单个合同PDF的解决方案
我来帮你搞定这个问题!你现在的核心需求是把ContractController里刚创建的单个合同传递给PdfGenerateController,而不是用Contract::all()取所有合同。在Laravel里,有几种实用的方式可以实现控制器间的通信,我给你推荐最常用的两种:
方法1:路由传合同ID(最推荐,符合RESTful规范)
这种方式直接通过路由参数传递合同的自增ID,简单可靠,也方便后续扩展。
1. 先修改路由
给生成PDF的路由加上contract_id参数:
// routes/web.php Route::get('generate-pdf/{contract_id}', [PdfGenerateController::class, 'pdfview'])->name('generate-pdf');
2. 调整ContractController的store方法
合同保存成功后,重定向到带ID的PDF路由:
public function store(Request $request) { $contract = new Contract; $contract->buyer_first_name = $request->input('buyer_first_name'); $contract->listing_id = $request->input('listing_id'); $contract->save(); // 把刚创建的合同ID传到路由里 return redirect()->route('generate-pdf', ['contract_id' => $contract->id]); }
3. 修改PdfGenerateController的pdfview方法
通过路由参数拿到ID,查询单个合同,再生成PDF:
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\PDF; use App\Models\Contract; // 记得引入你的Contract模型 public function pdfview(Request $request, $contract_id) { // 用findOrFail确保找不到合同时直接返回404,避免空对象报错 $contract = Contract::findOrFail($contract_id); $users = DB::table("users")->get(); // 把数据共享给视图 view()->share(['users' => $users, 'contract' => $contract]); if($request->has('download')){ PDF::setOptions(['dpi' => 150, 'defaultFont' => 'sans-serif']); $pdf = App::make('dompdf.wrapper'); // 这里用loadView加载你的Blade视图,而不是直接传$contract对象 $pdf->loadView('sell.contract'); // 可以指定下载的文件名 return $pdf->stream('contract-'.$contract->id.'.pdf'); } return view('sell.contract'); }
4. 视图里使用单个合同数据
在sell.contract视图中,直接用$contract变量展示信息就行:
<!-- resources/views/sell/contract.blade.php --> <h2>合同编号:{{ $contract->id }}</h2> <p>买方姓名:{{ $contract->buyer_first_name }}</p> <p>房源ID:{{ $contract->listing_id }}</p> <!-- 其他合同字段按需添加 -->
方法2:用Session暂存合同数据(备选场景)
如果不想修改现有路由结构,也可以用Session临时存储刚创建的合同:
1. 修改ContractController的store方法
把合同存入Session:
public function store(Request $request) { $contract = new Contract; $contract->buyer_first_name = $request->input('buyer_first_name'); $contract->listing_id = $request->input('listing_id'); $contract->save(); // 把合同存入Session session()->put('current_contract', $contract); return redirect()->route('generate-pdf'); }
2. 调整PdfGenerateController的pdfview方法
从Session取出合同,处理后记得清空Session避免重复使用:
public function pdfview(Request $request) { // 从Session取合同,没有的话跳回之前的页面 $contract = session()->get('current_contract'); if(!$contract){ return redirect()->back()->with('error', '未找到有效的合同信息'); } $users = DB::table("users")->get(); view()->share(['users' => $users, 'contract' => $contract]); if($request->has('download')){ PDF::setOptions(['dpi' => 150, 'defaultFont' => 'sans-serif']); $pdf = App::make('dompdf.wrapper'); $pdf->loadView('sell.contract'); // 生成PDF后清空Session,防止用户刷新页面重复生成 session()->forget('current_contract'); return $pdf->stream('contract.pdf'); } return view('sell.contract'); }
一些小提醒
- 优先选路由传ID的方式,Session可能会因为过期、用户开新标签页等情况导致数据丢失,路由参数更稳定。
- 用
findOrFail代替find,可以自动处理合同不存在的情况,不用自己写判断逻辑。 - 生成PDF时用
loadView比loadHTML更方便,因为可以直接用Blade模板渲染数据,维护起来更轻松。
内容的提问来源于stack exchange,提问作者user9820353
相关产品推荐
相关产品推荐

