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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:19:01