How this can be explained?
Clean install Laravel
Using redis for session and cache
The problem occur only if I start the server on windows and only shows on Chrome.
Using a simple js function for ajax call:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {
_token: $('meta[name="csrf-token"]').attr('content')
}
});
for(var i = 0; i < 5; i++){
getUsers();
}
function getUsers() {
$.ajax({
url: '/users',
type: 'POST',
success: function(data) {
console.log(data);
}
});
}
Setting CSRF in meta <meta name="csrf-token" content="{{ csrf_token() }}" />
Returning a JSON with data:
public function users() {
$users = User::all();
return response()->json([
'users' => $users,
]);
}
At the final of the video you can see RANDOM TokenMismatchException even the token never change but sometime error occur.
https://www.youtube.com/watch?v=QDucHoP647g
I know this problem has been discussed from years but why does not exist a solution for this?
I also posted on laravel github but none of solutions did not solved my problem.
Why do you send the token twice? remove that data part from $.ajaxSetup()
And why are you using POST for getting users? use GET instead.
Related
This question already has answers here:
How can I get useful error messages in PHP?
(41 answers)
Closed 8 months ago.
I'm trying to make a sortable table in my laravel app where the order also needs to be updated in the database, I'm trying to do it with jquery, ajax.
I tried to figure it out with this pieces of code:
JQuery/Ajax
$(document).ready(function () {
$('table tbody').sortable({
update: function (event, ui) {
$(this).children().each(function (index) {
if ($(this).attr('data-position') != (index + 1)) {
$(this).attr('data-position', (index + 1)).addClass('updated');
}
});
saveNewPositions();
}
});
});
function saveNewPositions() {
var positions = [];
$('updated').each(function () {
position.push([$(this).attr('data-index'), $(this).attr('data-position')]);
$(this).removeClass('updated');
});
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: 'cursos',
method: 'POST',
dataType: 'text',
data: {
'updated': 1,
'positions': positions,
'_token': '{{ csrf_token() }}'
},
})
Then in my web.php I created a post route:
Route::post('/cursos', function (Request $request){
return SectionCourseController::updateOrder($request);})->name('post');
In my controller I created this function:
public static function updateOrder(Request $request)
{
var_dump($request->positions);
foreach ($request->positions as $position) {
$index = $position[0];
$newPosition = $position[1];
$seccion = SectionCourse::findOrFail($index);
$seccion->order = $newPosition;
$seccion->save();
}
return response('success', 200);
}
When I'm trying to update the order, I'm having an error on the console of 500 (Internal Server Error).
[2022-06-14 14:16:18] local.ERROR: foreach() argument must be of type array|object, null given {"userId":1,"exception":"[object] (ErrorException(code: 0): foreach() argument must be of type array|object, null given
Sorry if I'm doing something bad on Ajax, this is the first time I try to do something on it.
I've done something very similar to this, so as I see it right now you are firstly missing a csrf token, so in the view add this below the code where you declare the $('updated') each.
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'POST',
dataType: 'json',
url: 'cursos', // No {{}} needed here
data: {
update: 1,
orders: orders,
_token: '{{ csrf_token() }}'
},
});
Next your controller is a mess. So rewrite it to fit at least some of laravels writing standards. Something like this
public function updateOrder(Request $request)
{
foreach ($request->positions as $position) {
$index = $position[0];
$newPosition = $position[1];
$seccion = SectionCourse::findOrFail($index);
$seccion->order = $newPosition;
$seccion->save();
}
return response('success', 200);
}
Also add the following when declaring .sortable
axis: 'y',
containment: 'parent',
update: ...
Add a meta-tag to each page, or master layout
<meta name="csrf-token" content="{{ csrf_token() }}"> and add to your js page
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Dont forget to add data inside
$.ajax({
url: "test",
type:"POST",
data: { '_token': token, 'someOtherData': someOtherData },
There is 2 cases for 500 internal server error
you had not put the {csrf} token there when sending request through ajax.
Use new FormData() object while sending response through ajax and use these params with processData: false,contentType: false,type: 'POST'
I'm having some problems passing from my blade file with an ajax request, to my Laravel controller. As far as I can tell I have set up my routes appropriately.
Route
Route::post('/aquarium/{id}/parameters', 'AquariumController#paramUpdate')->name('paramUpdate');
Laravel Function
use App\Aquarium;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
public function paramUpdate($id)
{
$params = $_POST['parameters'];
$aquarium = Aquarium::find($id);
$aquarium->parameters = $params;
$aquarium->save();
return "test";
//return redirect('/aquarium/'.$id);
}
Ajax request
var jsonParams = JSON.stringify(params);
$.ajax({
type: "POST",
url: "{{ route('paramUpdate', $aquarium->id) }}",
data: { parameters: jsonParams },
success: function(response) {
console.log(response);
},
error: function() {
console.log("Ajax error");
}
});
The goal is to pass the jsonParams variable to the controller, and then save it to the parameters field in the database. The database is configured and a record exists.
Fixed it - I added
<meta name="csrf-token" content="{{ csrf_token() }}">
to the header, and then
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
to the script. Figured it out by using the network tab to see the error being returned, and then some googling from there.
I need to send data via JS to a Laravel controller on a button click. I'm not using any form because the data is being created dynamically.
Every time i try to send the data, i get an Internal Server Error (500), but unable to catch that exception in the controller or the laravel.log file.
Here's what i'm doing:
Route:
Route::post('section/saveContactItems', 'SectionController#saveContactItems');
Controller:
public function saveContactItems($id, $type, $items, $languageID = "PT"){ ... }
JS:
$('button').on("click", function (evt) {
evt.preventDefault();
var items = [];
var id = $("#id").val();
var languageID = $("#languageID").val();
var data = { id: id, type: type, items: JSON.stringify(items), languageID: languageID };
$.ajax({
url: "/section/saveContactItems",
type: "POST",
data: data,
cache: false,
contentType: 'application/json; charset=utf-8',
processData: false,
success: function (response)
{
console.log(response);
}
});
});
What am i doing wrong? How can i accomplish this?
UPDATE: Thanks to #ShaktiPhartiyal's answer (and #Sanchit's help) i was able to solve my issue. In case some else comes into a similar problem, after following #Shakti's answer i wasn't able to access the data in the controller. So, i had to stringify the data before sending it to the server:
data: JSON.stringify(data),
You do not need to use
public function saveContactItems($id, $type, $items, $languageID = "PT"){ ... }
You have to do the following:
public function saveContactItems()
{
$id = Input::get('id');
$type = Input::get('type');
$items = Input::get('items');
$languageID = Input::get('languageID');
}
and yes as #Sanchit Gupta suggested you need to send the CSRF token with the request:
Methods to send CSRF token in AJAX:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
If you use this approach you need to set a meta tag like so:
<meta name="csrf-token" content="{{csrf_token()}}">
or
data: {
"_token": "{{ csrf_token() }}",
"id": id
}
UPDATE
as #Sanchit Gupta pointed out use the Input facade like so:
use Input;
index.html
<form id="my-form">
<select id="my-select">
<option value="1">Tom</option>
<option value="2">Jerry</option>
</select>
<input type="submit" value="send data!">
</form>
Controller.php
public function getValue(Request $request)
{
return User::find($request->input('select_id'));
}
ajax.js
$(function () {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var showUser = $('#show-user');
$('#my-form').on('submit', function () {
var select_id = $('#my-select').val();
$.ajax({
method: "POST",
url: "ajax",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {
"select_id": select_id
},
error: function (data) {
//something went wrong with the request
alert("Error");
},
success: function (data) {
inner = "";
data.forEach(function (el, i, array) {
inner += "<div>" + el.name + "</div>";
});
showUser.html(inner);
}
});
event.preventDefault();
});
});
web.php
Route::post('ajax','Controller#getValue');
Update:
#Mahdi Youseftabar -> Thanks for it, according to the documentation I should use input() to get the request!
Problem 1: Error: 500 (TokenMismatchException);
What I did?
Add meta to :
<meta name="csrf-token" content="{{ csrf_token() }}">
I set the headers:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
...
headers: {
'X-Auth-Token' : token
},
...
});
What I need to do?
Retrieve the id sent in the ajax request from the controller [SOLVED]
Validate the token by the ajax request** Error 505 (Problem 1) [SOLVED]
Return from the controller is Empty [SOLVED]
Output the Users into the <div class="showUser"></div> [SOLVED]
Github Documentation of my project:
(Many to many relationships - Laravel 5.3, Ajax)
https://github.com/39ro/StudentSchoolProject
your problem is in route :
Route:post('ajax','Controller#getValue');
you use post method in your jQuery but in route you define that route method 'get' ...
in this case when you request with ajax, laravel respond you a empty response
another issue is in getting your user_id from request, you should use this in your controller:
return User::find($request->input('user_id');
Two things check
In js
data: {"userid" : userid}
method: "POST",
in controller
$value_select = User::where($request->userid)->first();
return $value_select;
Now check the response and tell me if it works
If you don't get an error, and the result is null then you probably missing something.
Remember that find() function you use in your controller is searching for primary key only.
And its an ajax request so you wont see it in the browser. To see the return value you should look in the
Developer tools > Network > and then find the request to see the
preview and response
Add relationship to Controller.php
My problem was the relationship with the other two table.
I update my main Question with the link to my GitHub Project, where I applied all your suggestions! Thanks everyone, I solved it!
For the token I solved adding what I showed in Ajax.js.
And to retrieve the data from the relationship I just make it:
public function getValue(Request $request)
{
return User::find($request->input('select_id'))->relationship_table;
}
This is my test ajax in laravel 5 (refer below)
$("#try").click(function(){
var url = $(this).attr("data-link");
$.ajax({
url: "test",
type:"POST",
data: { testdata : 'testdatacontent' },
success:function(data){
alert(data);
},error:function(){
alert("error!!!!");
}
}); //end of ajax
});
and the trigger link
Try
and my route
Route::post('test', function()
{
return 'Success! ajax in laravel 5';
});
but it gives me an error when I run the console in google chrome and it doesn't return the expected response "return 'Success! ajax in laravel 5';"
POST http://juliver.laravel.com/test 500 (Internal Server Error)
whats wrong/problem to my code? anything I'm missing?
While this question exists for a while, but no accepted answer is given I'd like to point you towards the solution. Because you're sending with ajax, and presumably still use the CSRF middleware, you need to provide an additional header with your request.
Add a meta-tag to each page (or master layout): <meta name="csrf-token" content="{{ csrf_token() }}">
And add to your javascript-file (or section within the page):
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
See https://laravel.com/docs/master/csrf#csrf-x-csrf-token for more details.
90% of the laravel ajax internal server error is due to missing CSRF token. other reasons can inlucde:
Wrong Request Type (e.g sending post to get)
Wrong data type recived (e.g ajax is expecting JSON and app returns string)
Your .htaccess is misconfigured
Missing Route
Code Error
You can read further about this in details here: https://abbasharoon.me/how-to-fix-laravel-ajax-500-internal-server-error/
I guess this has been solved by now but still the best thing to do here is to send the token with your form
{!! csrf_field() !!}
and then in your ajax
$("#try").click(function(){
var url = $(this).attr("data-link");
$.ajax({
url: "test",
type:"POST",
data: { '_token': token, 'someOtherData': someOtherData },
success:function(data){
alert(data);
},error:function(){
alert("error!!!!");
}
}); //end of ajax
});
You can add your URLs to VerifyCsrfToken.php middleware. The URLs will be excluded from CSRF verification.
protected $except = [
"your url",
"your url/abc"
];
In App\Http\Middleware\VerifyCsrfToken.php you could try updating the file to something like:
class VerifyCsrfToken extends BaseVerifier {
private $openRoutes =
[
...excluded routes
];
public function handle($request, Closure $next)
{
foreach($this->openRoutes as $route)
{
if ($request->is($route))
{
return $next($request);
}
}
return parent::handle($request, $next);
}
};
This allows you to explicitly bypass specific routes that you do not want verified without disabling csrf validation globally.
Laravel 7.X
In bootstrap.js, in axios related code, add:
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = $('meta[name="csrf-token"]').attr('content');
Solved lot of unexplained 500 ajax errors.
Of course it's for those who use axios
By default Laravel comes with CSRF middleware.
You have 2 options:
Send token in you request
Disable CSRF middleware (not recomended): in app\Http\Kernel.php remove VerifyCsrfToken from $middleware array
for me this error cause of different stuff.
i have two ajax call in my page.
first one for save comment and another one for save like.
in my routes.php i had this:
Route::post('posts/show','PostController#save_comment');
Route::post('posts/show','PostController#save_like');
and i got 500 internal server error for my save like ajax call.
so i change second line http request type to PUT and error goes away.
you can use PATCH too.
maybe it helps.
you have to pass the csrf field through ajax please look at the code here
$.ajax({
type: "POST",
url:'{{URL::to("/delete-specialist")}}',
data: {
id: id,
_token: $('#signup-token').val()
},
datatype: 'html',
success: function (response) {
if(response=="deleted"){
$("#"+id).hide();
$("#message").html("successfully deleted");
}
}
});
and you also need to write this input field before this
<input id="signup-token" name="_token" type="hidden" value="{{csrf_token()}}">
still if you do not understand please enjoy this video
https://www.youtube.com/watch?v=ykXL8o0slJA&t=20s
do not forget add "use Illuminate\Http\Request;" on your controller
Short and Simple Solution
e.preventDefault();
var value = $('#id').val();
var id = $('#some_id').val();
url="{{url('office/service/requirement/rule_delete/')}}" +"/"+ id;
console.log(url);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
/* the route pointing to the post function */
url: url,
type: 'DELETE',
/* send the csrf-token and the input to the controller */
data: {message:value},
dataType: 'JSON',
/* remind that 'data' is the response of the AjaxController */
success: function (data) {
console.log(data)
//$('.writeinfo').append(data.msg);
//$('#ruleRow'+id).remove();
}
});
return false;
Using post jquery instead helped me to solve this problem
$.post('url', data, function(response) {
console.log(response);
});
I had same problem. In my case, issue arise because my id field of table (in database) was not set to auto increment. When I set it to auto increment then it started working.