如何在 ajax 调用时从 laravel 控制器函数返回视图?
Posted
技术标签:
【中文标题】如何在 ajax 调用时从 laravel 控制器函数返回视图?【英文标题】:How to return a view from laravel controller function upon ajax call? 【发布时间】:2020-11-24 19:53:08 【问题描述】:我正在做一个书店项目,可以将书籍添加到购物车,用户可以选择许多书籍将它们添加到购物车。当用户点击Add to Cart
按钮时,我将所选书籍的ID 添加到一个名为cart
的JS 数组中。当所有选定的书籍都添加到购物车时,我想将 <a>
标记与 ajax 调用链接,该调用将访问控制器函数的 url,并将 JS cart
数组对象发送到控制器函数,然后在控制器中函数,我想将视图返回给浏览器,我不希望控制器函数将响应返回给 ajax 调用,而是我想将视图返回给浏览器。
这里是把选中书籍的ID添加到cart
JS数组中的JS函数:
function addToCart(id)
if(! cart.includes(id) ) cart.push(id);
cartLength.html(cart.length);
$('#successCart'+id).html('Book added to cart.');
这里是调用ajax函数的<a>
标签,函数名是showCart():
<a href="#" onclick="event.preventDefault(); showCart();">
<i class="fa fa-shopping-cart"></i>
<span id="cartLength"></span>
</a>
这里是具有 ajax 代码的 showCart()
函数:
function showCart()
$.ajaxSetup(
headers:
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
);
$.ajax(
url:"cart",
method:'post',
data:cart:cart,
dataType: 'html'
)
.done(function(msg)
);
.fail(function(msg)
alert(msg.responseJSON.errors);
);
这是控制器函数 - 我希望这个函数直接将视图返回给浏览器,而不将其发送回 ajax 调用:
public function showCart(Request $request)
return view('cart', ['cart' => $request->cart ]); // this should be returned to the browser and not to the ajax call
这是控制器功能的路由:
Route::post('/cart', 'HomeController@showCart')->name('home.cart');
编辑:
我已经通过以下技巧暂时解决了这个问题,但这不是永久解决方案:
在从ajax
调用showCart()
函数将cart
数组变量从js
发送到laravel
控制器后,我使用以下逻辑将书籍存储在会话变量中,其ids
是存储在cart
数组中:
public function showCart(Request $request)
session()->put('cart_books', Book::whereIn('id', $request->cart)->get());
session()->save();
return "success";
将查询结果存储在会话变量中后,我为/cart
创建了另一个GET
路由,如下所示:
Route::get('/cart', 'HomeController@viewCart');
然后在post
ajax 调用成功后,我使用get
方法调用/cart
,如下所示:
.done(function(msg)
console.log('calling cart');
location.href = "cart"; // Here I call the `/cart` with `get` method which will hit the `viewCart()` function of HomeController which will return the view back to the browser along with the results that were stored in the session variable.
)
这是viewCart()
控制器函数,它将视图返回给浏览器并将会话变量的数据发送给视图:
public function viewCart()
$random_books = Book::all()->random(4);
$categories = Category::all();
return view('cart', ['cart_books' => session()->get('cart_books'),
'random_books' => $random_books, 'categories' => $categories]);
我希望控制器函数将视图返回给浏览器而不将其返回给 ajax 调用,提前感谢任何帮助。
【问题讨论】:
【参考方案1】:您可以通过在控制器中渲染和返回视图来从 ajax 调用返回 Raw html,
return view('cart', ['cart' => $request->cart])->render();
这将返回原始 HTML,您可以进一步使用它。但是从ajax返回HTML并不是一个好办法,你可以从控制器返回JSON,并根据JSON数据在前端渲染视图。
【讨论】:
【参考方案2】:在控制器函数中只需添加如下行的渲染方法
public function showCart(Request $request)
return view('cart', ['cart' => $request->cart ])->render();
对于js:
$.ajax(
method: 'POST', // Type of response and matches what we said in the route
url: ' route('home.cart') ', // This is the url we gave in the route
data: 'cart' : cart, // <-- this is your POST data
success: function(response) // What to do if we succeed
console.log(response);
,
error: function(jqXHR, textStatus, errorThrown) // What to do if we fail
console.log(JSON.stringify(jqXHR));
console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
);
【讨论】:
上面写着Internal Server Error
。
jquery.min.js:5 POST localhost:8080/wisdom2/public/cart500(内部服务器错误)发送@jquery.min.js:5 ajax @jquery.min.js:5 showCart @main.js:84 onclick @(索引):64
The GET method is not supported for this route.
这意味着您将其称为 get 而不是 GET 路由,请从此处的路由文件中复制路由
当异常发生时你能显示来自 laravel 日志文件的日志吗?也许我们错过了什么【参考方案3】:
你正在做一个 XHR,所以你不应该从你的控制器返回整个 HTML view 除非你打算用返回的 HTML 替换你现有的元素,就像你正在做的那样addToCart
。您在这里需要的是 POST 之后的重定向,而您的临时解决方案实际上并不是一个糟糕的解决方案 :) 这是一个 similar question 与您的答案相同。事实上,我强烈推荐您的临时解决方案,而不是下面的替代解决方案。
由于您希望使用从控制器返回的视图而不将其返回到您的 ajax,一个相当非正统的方法是通过 <form>
进行 POST。您可以使用您的数据的<input>
s 动态创建<form>
,然后提交。
function postData(actionUrl, method, data)
var mapForm = $('<form id="mapform" action="' + actionUrl + '" method="' + method.toLowerCase() + '"></form>');
for (var key in data)
if (data.hasOwnProperty(key))
mapForm.append('<input type="hidden" name="' + key + '" id="' + key + '" value="' + data[key] + '" />');
$('body').append(mapForm);
mapForm.submit();
function showCart()
postData('cart', 'post', cart);
我从here借用了上面的代码。你也可以使用same with vanilla JS。
【讨论】:
【参考方案4】:正如其他人所说,您可以使用
return view('cart', ['cart' => $request->cart])->render();
在你的 jQuery 中做
.done(function(response)
document.write(response);
);
或者您可以返回其内容应显示给用户的链接,并在您的 done 方法中重定向用户。所以在你的后端你会有
return route('cart', ['cart' => $request->cart]);
在您的前端,您将拥有
.done(function(response)
location.href = response;
);
【讨论】:
以上是关于如何在 ajax 调用时从 laravel 控制器函数返回视图?的主要内容,如果未能解决你的问题,请参考以下文章
从一个控制器 LARAVEL 使用 AJAX 调用不同的函数