i'm working on an laravel vuejs spa. I try to update a post from the admin. I send the form datas on creating a new FromData who are sending with and axios request.
But the controller send me the error:
message: "The given data was invalid."
errors: {name: ["The name field is required."], description: ["The description field is required."]}
- Here is the post/edit.vue
<template>
<div class="post-edit">
<form id="form" @submit.prevent="createPost">
<!-- Title -->
<div class="form-group">
<label for="title" class="form-label">Title</label>
<input id="title" v-model="post.title" :title="post.title" type="text"
name="title" class="form-control"
>
</div>
<!-- Category -->
<div class="form-group">
<label for="category" class="form-label">Category</label>
<select id="category" v-model="post.category" :value="post.category" :category="post.category"
name="category" class="form-control"
>
<option disabled :value="post.category">
Choisir une catégorie
</option>
<option v-for="(category) in categories" :key="category.id" :value="post.category">
{{ category.name }}
</option>
</select>
</div>
<div class="post-edit-image">
<img :src="path + post.image" alt="">
</div>
<!-- Image -->
<div class="form-group post-edit-select-image">
<label for="content" class="form-label">Image</label>
<input type="file" name="image" class="form-control" @change="selectedImage">
</div>
<!-- Content -->
<div class="form-group">
<label for="content" class="form-label">Content</label>
<editor
id="content"
v-model="post.content"
api-key="the-api-key"
:init="{
height: 500,
menubar: false,
plugins: [
'advlist autolink lists link image charmap print preview anchor',
'searchreplace visualblocks code fullscreen',
'insertdatetime media table paste code help wordcount'
],
toolbar:
'undo redo | formatselect | bold italic backcolor | \
alignleft aligncenter alignright alignjustify | \
bullist numlist outdent indent | removeformat | help'
}"
name="content"
:content="post.content"
/>
</div>
<!-- Submit Button -->
<button type="submit" class="btn btn-primary">
Sauvegarder
</button>
</form>
</div>
</template>
<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
import Editor from '@tinymce/tinymce-vue'
export default {
middleware: 'auth',
components: {
'editor': Editor
},
props: ['id'],
data () {
return {
post: {
id: '',
user_id: '',
title: '',
category: '',
image: null,
content: ''
},
path: '/images/post/thumbnail/'
}
},
computed: {
...mapGetters({
user: 'auth/user',
categories: 'categories/categories'
})
},
beforeCreate () {
this.$store.dispatch('categories/fetchCategories')
},
created () {
this.getPostById(this.$route.params.id)
},
methods: {
selectedImage (event) {
this.post.image = event.target.files[0]
},
getPostById (id) {
axios.get('/api/posts/edit/' + id)
.then((response) => {
this.post.id = response.data.id
this.post.user_id = response.data.user_id
this.post.title = response.data.title
this.post.category = response.data.category
this.post.image = response.data.image
this.post.content = response.data.content
})
.catch((error) => {
console.log(error)
})
},
createPost (e) {
this.post.userId = this.user.id
let formData = new FormData(e.target)
let id = this.post.id
formData.append('title', this.post.title)
formData.append('category', this.post.category)
formData.append('image', this.post.image)
formData.append('content', this.post.content)
axios.patch('/api/posts/update/' + id, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response) => {
console.log(response)
this.$store.dispatch('posts/fetchPosts')
})
.catch((error) => {
console.log(error)
})
this.$router.push({ name: 'admin' })
}
}
}
</script>
- And here the laravel controller PostController@update method
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(PostUpdateRequest $request, $id)
{
$post = Post::findOrFail($id);
$post->update($request->getValidRequest());
return response()->json($request, 200);
}
- And the custom validator PostUpdateRequest.php
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|max:250|unique:posts,title',
'category' => 'required',
'image' => 'mimes:jpg,jpeg,png,bmp',
'content' => 'required'
];
}
public function getValidRequest()
{
$image = $this->file('image');
$slug = Str::slug($this->input('title'));
if (isset($image)) {
$imageExt = $image->getClientOriginalExtension();
$currentDate = Carbon::now()->toDateString();
$imageName = $slug . '-' . $currentDate . '-' . uniqid() . '.' . $imageExt;
if (!Storage::disk('public')->exists('post')) {
Storage::disk('public')->makeDirectory('post');
}
if (!Storage::disk('public')->exists('post/thumbnail')) {
Storage::disk('public')->makeDirectory('post/thumbnail');
}
$path = "images/";
$postImage = Image::make($image)->resize(null, 1060, function ($constraint){
$constraint->aspectRatio();
})->save(public_path($path).'post/'.$imageName);
$thumbnail = Image::make($image)->fit(550, 550)
->save(public_path($path).'post/thumbnail/'.$imageName);
}
return [
'user_id' => Auth::user()->getAuthIdentifier(),
'category_id' => $this->input('category'),
'title' => $this->input('title'),
'slug' => $slug,
'content' => $this->input('content'),
'image' => $imageName,
'is_published' => $this->input('is_published') ?? false,
];
}
- The api route in laravel
Route::patch('/update/{id}', 'Backend\PostController@update');
I use practically the same things to store a post, and it work's fine, the only difference is here i pass an id for the post to update and i not use the post method but patch for axios and the route (and i try with put, it's the same error).
thank's for your time !