so I've got this weird problem where if I make a Put request through axios in Vue, it's sending it to the wrong route.
It's part of a simple CRUD through a Laravel APIresource. Get and post work fine.
This is the form:
<form #submit.prevent="editType" method="post" class="mb-4">
<label v-if="user.gender === 'man'" for="single_male">Enkel<input type="checkbox" name="type" :id="single_male" :value="types.single_male" v-model="checkedType" #change="showSaveButton = true"></label>
<label v-if="user.gender === 'vrouw'" for="single_female">Enkel<input type="checkbox" name="type" :id="single_female" :value="types.single_female" v-model="checkedType" #change="showSaveButton = true"></label>
<label v-if="user.gender === 'man'" for="double_male">Dubbel mannen<input type="checkbox" name="type" :id="double_male" :value="types.double_male" v-model="checkedType" #change="showSaveButton = true"></label>
<label v-if="user.gender === 'vrouw'" for="double_female">Dubbel vrouwen<input type="checkbox" name="type" :id="double_female" :value="types.double_female" v-model="checkedType" #change="showSaveButton = true"></label>
<label for="double_mix">Dubbel gemengd<input type="checkbox" name="type" :id="double_mix" :value="types.double_mix" v-model="checkedType" #change="showSaveButton"></label>
<button type="submit" v-if="showSaveButton">Opslaan</button>
</form>
My update function:
public function update(Request $request, $id)
{
$user_id = auth('api')->user()->id;
$type = Type::where('user_id' ,'=', $user_id)->first();
$type->single_male = $request->input('single_male');
$type->single_female = $request->input('single_female');
$type->double_male = $request->input('double_male');
$type->double_female = $request->input('double_female');
$type->double_mix = $request->input('double_mix');
$type->save();
return redirect()->back();
}
my method:
editType() {
let types = this.types;
let data = {
single_male: this.single_male,
single_female: this.single_female,
double_male: this.double_male,
double_female: this.double_female,
double_mix: this.double_mix,
};
axios.put('/types/'+types.id, data)
.then(request => this.successfulEdit(request))
.catch(() => this.failed())
},
successfulEdit() {
alert("Voorkeuren succesvol bijgewerkt!");
}
and my route:
Route::apiresource('types','TypeController');
When I make a put request, I can see in the Developer Tools that it tries to make the request to the current url, which of course gives a 405 method not allowed error.
When I change the axios request to just ('/types', data), it does follow the specified route but of course gives the 405 error too since the put method requires an id. Hardcoding to e.g. '/types/4/' also leads to using the current url.
Am I missing somethng or what's wrong? Thanks in advance guys!
Found the problem. The return redirect()->back(); was the culprit. Thanks y'all!
From Laravel docs. https://laravel.com/docs/5.8/routing
Routes defined in the routes/api.php file are nested within a route
group by the RouteServiceProvider. Within this group, the /api URI
prefix is automatically applied
So try to add /api before your current request URL like
axios.put('/api/types/'+types.id, data)
Related
I try to learn Laravel (v.9) from scratch but fail to do a simple basic task:
I just want to send "post_var" by POST request and display the var.
My form (blade template):
<form action="/post_and_show" method="POST">
#csrf
#method('post')
<input type="text" name="post_var">
<input type="submit" value="send">
</form>
My Route (in web.php) with some dd() i tried to find the problem
Route::post('/post_and_show', function (Request $request) {
dd($request->method()); // returns GET ?? !!
// chrome debugger network tab show clearly its a POST request...
dd($request->all()); // returns empty Array
dd($request->post_var); // returns null
dd($request->getContent()); // returns string but i want param only
// "_token=yBBYpQ303a1tSiGtQF6zFCF6p6S7qadVfHMk4W7Q&_method=post&post_var=12345"
});
What am i doing wrong here?
Tried several methods i found in the documentation but non worked so far.
EDIT: I removed "#method('post')"
Btw.: My initial version that did not work either had no "#method('post')". I added it later on in the hope it might help...
<form action="/post_and_show" method="POST">
#csrf
<input type="text" name="post_var">
<input type="submit" value="send">
</form>
But have still the same problems:
Route::post('/post_and_show', function (Request $request) {
dd($request->method()); // returns GET ?? !! but chrome says its a post request
dd($request->post_var); // returns null
dd($request->get('post_var'));// returns null
dd($request->getContent()); // returns complete body and header in one string
dd($request->all()); // return empty Array
});
EDIT 2:
Googleing i found "createFromGlobals":
use Illuminate\HTTP\Request; // just added this to show which class i use here...
use Illuminate\Support\Facades\Route;
Route::post('/post_and_show', function () {
dd(Request::createFromGlobals()->get('post_var')); // returning expected value
});
This works for me, but i can't find this method in documentation. Sorry, i am new to laravel and even php, so this seems all completely crazy to me.. ;-)
EDIT 3:
If i use a simple Controller it works too...
Controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class FormController extends Controller
{
public function show(Request $request)
{
dd($request->post_var); // returns expected value...
}
}
Route:
Route::post('post_and_show', [FormController::class, 'show']);
So only in case i use the $request immediatly in the callback it does not work as expected. ( Either by design or bug??)
I have following code in route web.php file.
Route::resource('dailyrevenue', DailyRevenueController::class)->middleware('auth');
Then in my DailyRevenueController.php
public function destroy(DailyRevenue $revenue)
{
$revenue->delete();
return redirect()->back();
}
And in my vue3 code:
const submit = function (id) {
const check = confirm("Are you sure to delete ?")
if (check) {
Inertia.delete(route('dailyrevenue.destroy',id), {
id: id,
method: 'delete',
forceFormData: true
})
}
}
Finally in the template:
<template #cell(actions)="{item: tax}">
<form method="delete" #submit.prevent="submit(tax.id)">
<input type="hidden" name="_method" value="delete"/>
<button type="submit">Delete</button>
</form>
</template>
Now request reaches to the method. But nothing is deleted. The request sent is DELETE request. Instead of 302 response it sends back 303 (See others).
Community help is appreciated.
Thanks.
I found the solution. The reson behind it was the variable name. In url endpoint the variable name was decleared as dailyrevenue and in the method as $revenue.
You can find your url variable by typing php artisan route:list.
I found that the url variable name must match with variable name in method.
Hope this helps others too.
I am not getting any error, it's just refreshing on that page. The controller method is not called where I have given the path for redirection.
My code is:
blade-file
<form action="{{route('validate-promocode')}}" method="post">
#csrf
<input class="promo-input" id="code" type="text" onkeyup="this.value = this.value.toUpperCase();" name="code" placeholder="EG. APPLY HERE"><br>
<input type="hidden" name="_token" value="{!!csrf_token()!!}">
<button id="save" type="submit" class="apply-promo">Apply Promo Code</button>
</form>
Route file
Route::post('/validade-code', 'PromoController#validateCode')->name('validate-promocode');
Controller file
public function validateCode(Request $request){
if (Gate::allows('isUser')) {
$ip = $request->input('code');
dd($promo);
$promo = Promo::where('code','=', trim($ip))->first();
if(!empty($promo)){
$dataamountMonthly = 40000 - (($promo->discount_percentage * 40000) / 100);
$dataamountYearly = 300000 - (($promo->discount_percentage * 300000) / 100);
if($dataamountMonthly == 0 || $dataamountYearly == 0){
return view('paymet.subscription-success');
}
$data = array(
'dataamountMonthly' => $dataamountMonthly ,
'dataamountYearly' => $dataamountYearly,
'code' => $ip
);
return view('payment.startPromoCode',$data);
}else{
$data = array(
'error' => 'Something went wrong, please try again'
);
return redirect()->back()->with($data);
}
}
}
I don't know what I am missing , any help will be appriciated.
Solved
Sometimes you may wish to redirect the user to their previous location, such as when a submitted form is invalid. You may do so by using the global back helper function. Since this feature utilizes the session, make sure the route calling the back function is using the web middleware group or has all of the session middleware applied
I think according to your code
$promo = Promo::where('code','=', trim($ip))->first();
the value of $promo can be null/ empty
and instead of executing your expected code it is redirecting back the page, and it seems the refresh for you. rest your code is correct.
Did an upgrade from 5.4 to 5.7, after that every ajax post request is 419 with:
{message: "", exception: "Symfony\Component\HttpKernel\Exception\HttpException",…}
exception: "Symfony\Component\HttpKernel\Exception\HttpException"
file: "pathto/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
line: 204
message: ""
trace: [{,…}, {file: "pathto/public_html/app/Exceptions/Handler.php", line: 47, function: "render",…},…]
0: {,…}
class: "Illuminate\Foundation\Exceptions\Handler"
file: "pathto/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
function: "prepareException"
line: 176
type: "->"
Followed the upgrade instructions which especially mentioned about Cookie Serialization:
protected static $serialize = true;
Cleared cache, checked the file permissions are ok. Went down to 5.6, then to 5.5 laravel versions but no help. Changed the cookie name, tried incognito. Tried to even bypass all:
protected $except = [
"*"
];
But no change. What on earth could go wrong here?
Edit:
Ajax call:
var $_token = $('#token').val();
var url = '/delete';
$.ajax({
headers: {'X-XSRF-TOKEN': $_token},
type: "POST",
url: url,
data: ({data: data}), // set up earlier
success: function (data) {
}
});
Controller:
public function delete(Request $request)
{
$id = $request->input('data);
Post::where('id', $id)->delete();
}
Also tried with $('meta[name="csrf-token"]').attr('content')
This gave me:
payload is invalid
id token is taken from:
<?php
$encrypter = app('Illuminate\Encryption\Encrypter');
$encrypted_token = $encrypter->encrypt(csrf_token());
?>
<input id="token" type="hidden" value="{{$encrypted_token}}">
just add
{{ csrf_field() }}
to your blade template
something like
<form method="POST" action="/projects">
{{ csrf_field() }}
<div class="form-group">
<label for="title">Title</label>
<input id="title" class="form-control" type="text" name="title" placeholder="Project Title" required />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">
Create Project
</button>
</div>
</form>
Hard to tell without your controller and the actual ajax call... but I've had similar problems with this 419 error. There were two causes for me:
1) Failed token verification. To check, add this to your ajax call:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Though... your having tried to except everything should have allowed this through (assuming you had that line in the right place).
EDIT: If you are passing your X-XSRF-TOKEN from JavaScript, decode it using decodeURIComponent()
2) It's possible that your controller is trying to render the view without all the information it needs. Any chance you need to send a variable through to the view in the ajax controller function and it is missing? I realize this worked before, but there were some big changes to 5.5 (including the way CSRF was handled as above).
3) Just a general error that I've had, but it might be possible that the data is not transferring in the same way as it did with 5.4. Just check to see if the way the data is coming in to the controller is not error-ing out. IE do a dump from the controller before it gets back to the view and see what your browser reports is transferring
Old topic but I just got back to it now and figured it out.
Reason was that I was passing: XSRF-Token in older Laravel instead of CSRF-Token, the never versions don't seem to work with XSRF anymore. Switched to CSRF and that fixed it.
I'm working on integrating 2-factor authentication using https://github.com/ChristianRiesen/otp on a Laravel 4.1.23 site: the secret gets generated fine, the QR code image too, and Google Authenticator is able to scan the image.
However, the code generated on my iPhone inside the Google Authenticator application does not validate. I've followed the example from the README.md.
In my Controller, I have code like the following:
$secret = GoogleAuthenticator::generateRandom();
$url = GoogleAuthenticator::getQrCodeUrl('totp', 'MySite:'.Auth::user()->email, $secret);
// Save the secret with the user's data
if (!Auth::user()->secret) {
Auth::user()->secret = $secret;
Auth::user()->save();
}
return View::make('2fa')->with('secret', $secret)->with('url', $url);
Then in my view (2fa.blade.php), I have code like the following:
<strong>Secret Key:</strong> {{ $secret }}
<strong>QR Code</strong> <br/>
<img src="{{ $url }}" />
<form action="/confirm_key" method="post">
<label for="key">Enter the generated key:</label>
<input type="text" name="key" id="key"/>
<input type="submit" id="submit" value="Confirm Key"/>
</form>
That all appears to be working. The form posts to the following controller function:
public function postTwoFactorAuthentication() {
// Now how to check
$otp = new Otp();
if ($otp->checkTotp(Base32::decode(Auth::user()->secret), Input::get('key'))) {
return 'Verified!';
}
// Wrong key
else {
return 'Invalid key!'
}
}
This is following usage example from the repo pretty closely, but the key (token) never validates. Am I missing something here? Is Laravel screwing with something?
Any help is appreciated.