
在Laravel应用开发中,一个常见的挑战是在不同的控制器方法之间,或者从控制器方法到视图之间传递数据。原始代码中,$newOrder 对象在 token 方法中被创建并保存,但当视图 orders.success 尝试访问它时,却提示 $newOrder 未定义。这通常是由于以下原因:
为了解决这个问题,我们需要根据具体的业务场景和请求流程,选择合适的数据传递策略。
这是最直接、最常用的方法,适用于控制器方法直接负责渲染最终视图,且没有发生HTTP重定向的场景。
当一个控制器方法完成所有业务逻辑后,立即渲染一个Blade视图,并将该方法中生成的数据(如 $newOrder)提供给视图使用。
在 return view() 语句中,通过第二个参数(一个关联数组)将变量传递给视图。数组的键将作为视图中可访问的变量名。
控制器 (BraintreeController.php)
use App\Models\Order; // 确保引入 Order 模型
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\PaymentConfirmationMail;
use App\Models\Dish; // 确保引入 Dish 模型
use Braintree\Gateway; // 确保引入 Braintree Gateway
class BraintreeController extends Controller
{
public function token(Request $request)
{
$gateway = new Gateway([
'environment' => 'sandbox',
'merchantId' => 'jgvy755pfvwdcjzx',
'publicKey' => 'qqpm93srfgwtx6dp',
'privateKey' => 'd13ce21a7642606db73b12bb1300d3fd'
]);
$clientToken = $gateway->clientToken()->generate();
if ($request->input('nonce') != null) {
$request->validate([
'name' => 'required',
'last_name' => 'required',
'phone' => 'required',
'address' => 'required',
'email' => 'email:rfc',
]);
// ... (省略创建 $newOrder 对象之前的业务逻辑) ...
$name = $request->input('name');
$last_name = $request->input('last_name');
$address = $request->input('address');
$phone = $request->input('phone');
$email = $request->input('email');
$arr_id = $request->input('arr_id');
$arr_quant = $request->input('arr_quant');
$delivery_fee = $request->input('delivery_fee');
$dishes = Dish::findMany($arr_id);
$arrayLength = count($arr_id);
$amount = 0;
for ($i = 0; $i < $arrayLength; $i++) {
$amount += $dishes[$i]->price * $arr_quant[$i];
}
$amount += $delivery_fee;
$newOrder = new Order();
$newOrder->status = 1;
$newOrder->address = $address;
$newOrder->user_name = $name;
$newOrder->user_surname = $last_name;
$newOrder->phone = $phone;
$newOrder->email = $email;
$newOrder->total = $amount;
$newOrder->save();
for ($i = 0; $i < $arrayLength; $i++) {
$dish_id = $arr_id[$i];
$newOrder->dishes()->attach([$dish_id => ['quantity' => $arr_quant[$i]]]);
}
$nonceFromTheClient = $request->input('nonce');
$gateway->transaction()->sale([
'amount' => $amount,
'paymentMethodNonce' => $nonceFromTheClient,
'options' => [
'submitForSettlement' => True
]
]);
Mail::to($email)->send(new PaymentConfirmationMail());
// 关键修改:直接将 $newOrder 传递给 'orders.success' 视图
return view('orders.success', ['newOrder' => $newOrder]);
}
return view('orders.braintree', ['token' => $clientToken]);
}
// success 方法在此方案中可能不再需要,除非有其他用途
// public function success(Request $request)
// {
// return view('orders.success');
// }
}视图 (resources/views/orders/success.blade.php)
<body>
<div class="container mt-5 mb-5 text-center">
<h1>Pagamento avvenuto con successo</h1>
<h2 class="mb-5">il tuo ordine è stato preso in carico</h2>
<a href="{{route('restaurants.index')}}">Ritorna ai ristoranti</a>
{{-- 现在 $newOrder 变量可以直接访问 --}}
<h1>订单地址:{{ $newOrder->address }}</h1>
{{-- 还可以访问其他属性,例如: --}}
{{-- <p>订单总价:{{ $newOrder->total }}</p> --}}
{{-- <p>客户姓名:{{ $newOrder->user_name }} {{ $newOrder->user_surname }}</p> --}}
</div>
</body>此方案适用于一个控制器方法需要调用同控制器内的另一个方法来处理部分逻辑或渲染视图,并且希望将数据从调用方传递给被调用方时。这通常发生在不需要HTTP重定向,而是在同一请求生命周期内进行方法委托的情况下。
当 success 方法并非一个独立的、由路由直接访问的端点,而是作为 token 方法的一个内部辅助方法,负责最终的视图渲染,并且 token 方法需要将它生成的数据传递给 success 方法时。
将变量作为参数直接传递给被调用的方法。被调用的方法需要修改其签名以接收这些参数。
控制器 (BraintreeController.php)
use App\Models\Order; // 确保引入 Order 模型
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\PaymentConfirmationMail;
use App\Models\Dish; // 确保引入 Dish 模型
use Braintree\Gateway; // 确保引入 Braintree Gateway
class BraintreeController extends Controller
{
public function token(Request $request)
{
// ... (创建 $newOrder 对象的业务逻辑,同方案一) ...
$gateway = new Gateway([ /* ... */ ]);
$clientToken = $gateway->clientToken()->generate();
if ($request->input('nonce') != null) {
$request->validate([ /* ... */ ]);
// ... (创建 $newOrder 对象的业务逻辑) ...
$newOrder = new Order();
// ... (填充 $newOrder 属性并保存) ...
$newOrder->save();
// ... (关联 dishes 等) ...
$nonceFromTheClient = $request->input('nonce');
$gateway->transaction()->sale([ /* ... */ ]);
Mail::to($email)->send(new PaymentConfirmationMail());
// 关键修改:调用同控制器内的 success 方法,并传递 $newOrder
return $this->success($newOrder);
}
return view('orders.braintree', ['token' => $clientToken]);
}
// success 方法现在接收一个 Order 类型的参数
// 建议使用类型提示,提高代码健壮性
public function success(Order $newOrder)
{
// 直接将接收到的 $newOrder 传递给视图
return view('orders.success', ['newOrder' => $newOrder]);
}
}视图 (resources/views/orders/success.blade.php)
<body>
<div class="container mt-5 mb-5 text-center">
<h1>Pagamento avvenuto con successo</h1>
<h2 class="mb-5">il tuo ordine è stato preso in carico</h2>
<a href="{{route('restaurants.index')}}">Ritorna ai ristoranti</a>
{{-- $newOrder 变量可以直接访问 --}}
<h1>订单地址:{{ $newOrder->address }}</h1>
</div>
</body>这是在Laravel中处理“Post-Redirect-Get”模式下数据传递的标准和推荐方法。当一个控制器方法处理完请求后,需要重定向到另一个路由,并希望在下一个请求中(通常是重定向后的页面)访问一些临时数据时,会话闪存是最佳选择。
当 token 方法完成订单处理后,不是直接渲染视图,而是重定向到一个新的URL(例如 /orders/success),而这个新的URL由 success 方法处理并渲染视图。在这种情况下,由于发生了重定向,前一个请求的局部变量会丢失,需要通过会话来传递数据。
使用 redirect()->route('route_name')->with('key', $value) 方法将数据存入会话。这些数据只在下一个请求中可用,之后会自动从会话中删除。
路由 (routes/web.php)
首先,确保你的 success 方法有一个对应的路由名称。
// ... 其他路由 ...
Route::get('/orders/success', [App\Http\Controllers\BraintreeController::class, 'success'])->name('orders.success_route_name');
// ...控制器 (BraintreeController.php)
use App\Models\Order; // 确保引入 Order 模型 use Illuminate\Http\Request; use Illuminate
以上就是Laravel控制器中变量传递与视图数据共享的策略的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号