J'ai ce formulaire où l'utilisateur ne doit taper du texte qu'à l'intérieur d'une zone de texte:
<form action="#" v-on:submit="postStatus">{{-- Name of the method in Vue.js --}}
<div class="form-group">
<textarea class="form-control" rows="5" maxlength="140" autofocus placeholder="What are you upto?" required v-model="post"></textarea>
</div>
<input type="submit" value="Post" class="form-control btn btn-info">
{{ csrf_field() }}
</form>
Ensuite, j'ai ce code de script où j'utilise vue.js avec ajax afin de passer ce texte à un contrôleur et éventuellement de l'enregistrer dans la base de données:
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
},
http : {
headers: {
'X-CSRF-Token': $('meta[name=_token]').attr('content')
}
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
}
});
}
},
});
Cependant, cela ne fonctionne pas jusqu'à présent, car il existe cette exception d'incompatibilité de jeton. Je ne sais pas comment le faire fonctionner. Comment transmettre cette valeur de jeton au contrôleur. J'ai essayé ce qui suit:
1) dans le formulaire, j'ai ajouté un nom de vue au jeton:
<input type="hidden" name="_token" value="YzXAnwBñC7qPK9kg7MGGIUzznEOCi2dTnG9h9çpB" v-model="token">
2) J'ai essayé de passer cette valeur de jeton dans la vue:
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
token : '',
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
'_token': this.token,
}
});
}
},
});
... mais dans la console, la vue ne l'attrape même pas :(
Cela me conduit à l'erreur suivante:
TokenMismatchException dans la ligne VerifyCsrfToken.php 68:
Comment je le répare? Des idées?
Very Easy Solution
Ajoutez simplement un champ masqué à l'intérieur du formulaire. Un exemple
<form id="logout-form" action="/logout" method="POST" style="display: none;">
<input type="hidden" name="_token" :value="csrf">
</form>
Ajoutez maintenant la variable csrf
dans script au fichier de vue, comme ceci. (Rappelez-vous, il doit être dans data ).
<script>
export default {
data: () => ({
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
}),
}
</script>
N.B. Vous verrez une balise meta dans votre fichier blade.php
comme ceci.
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
S'il n'y a rien de tel, vous devez le placer là.
Simplement, je suggérerais de mettre ceci dans votre fichier PHP:
<script>
window.Laravel = <?php echo json_encode(['csrfToken' => csrf_token()]); ?>
</script>
De cette façon, vous pourrez facilement importer votre csrfToken à partir de la partie JS (Vue dans ce cas).
De plus, si vous insérez ce code dans votre fichier de mise en page PHP, vous pouvez utiliser le jeton de tout composant de votre application, car window
est une variable globale JS.
Source: J'ai eu le truc de this post.
Une meilleure solution consiste simplement à faire passer le jeton csrf via un emplacement dans le composant vue.
Dans le fichier blade.php:
@extends('layouts.app')
@section('content')
<my-vue-component>
{{ csrf_field() }}
</my-vue-component>
@endsection
Dans MyVueComponent.vue
<form role="form">
<slot>
<!-- CSRF gets injected into this slot -->
</slot>
<!-- form fields here -->
</form>
Ma solution à cela est que tous les composants vue obtiennent le jeton csrf juste avant qu'une demande soit faite. Je mets cela dans mon fichier bootstrap.js.
Vue.http.interceptors.Push((request, next) => {
request.headers.set('X-CSRF-TOKEN', CoolApp.csrfToken);
next();
});
Puis avoir une classe CoolApp.php
public function getScriptVariables()
{
return json_encode([
'csrfToken' => csrf_token(),
]);
}