Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

spook1's avatar

successful post request in VUE to Laravel api, does not add record to database

In Vue I created a crud form to manage 'cards', containing title, description and image. Being new to Vue, combined with laravel, this is difficult for me.

I managed to add the file to the form data, appending them to a formData-object

The addition of cards worked fine, until I tried to add the image file to the formData. Sometimes it worked, then again it fails. I am doing something wrong with the Card model creation from the formdata reuqest. I do not see what however. been fooling around for hours now ...

I hope that someone can see at a glance what my ( probably silly) mistake is...

The Vue component that sends the requests:

<template>
<div>
    <h2>Cards 1</h2>
    <form @submit.prevent="addCard" class="mb-3"> 
        <div class="form-group">
            <input type="text" class="form-control" placeholder="title" v-model="card.title">
        </div>

        <div class="form-group">
            <textarea  class="form-control" placeholder="description" v-model="card.description">
            </textarea>
        </div>

        <div>
		    <input type="file" v-on:change="onFileChange" id="file_picture_input">
        </div>

        <button type="submit" class="btn btn-primary btn-block" style="color:white">Save</button>
    </form>
    <div class="card card-body mb-2" v-for="card in cards" v-bind:key="card.id">   
        <h3> {{card.title}}   </h3>
        <p> {{card.description}}</p>
        <img class="img-circle" style="width:150px" v-bind:src="card.picture" alt="Card Image">
        <button @click="deleteCard(card.id)" class="btn btn-danger m-1" style="width:100px;color:white">  Delete  </button>
        <button @click="editCard(card)" class="btn btn-warning m-1" style="width:100px;color:black">  Edit  </button>

    </div>
</div>
</template>

<script>

export default {
    mounted(){
        console.log('component mounted')
    },
    data() {
        return{
            cards:[],
            card:{
                id:'',
                title:'',
                description:'',
            },
            card_id:'',
            edit:false,
            selectedFile:''
        }

    },
    created(){
        this.fetchCards();
    },
    methods: {
        fetchCards(){
            fetch('api/cards')
                .then(res => res.json())
                .then(res=>{
                   console.log(res);
                   this.cards = res;
                })
        },
        deleteCard(id){
            if(confirm('Are you sure?')){
                fetch(`api/cards/${id}`, {
                    method: 'delete'
                })
                .then(res => res.json())
                .then(data => {
                    alert('Card removed');
                    this.fetchCards();
                } )
                .catch(err => console.log(err));
            }

        },
        addCard(){
            // de informatie voor de card staat inthis.$card, nu omzetten naar FormData om file toe te voegen aan de request zodat api die kan opslaan, api gaat ook naam bedenken voor de card.
            //  via fetchCards() komt die naam dadelijk terug in card.picture
            const formData = new FormData();
            formData.append('title',this.card.title);
            formData.append('description',this.card.description);
            formData.append('picture',this.selectedFile);
            console.log(formData.get('picture').name);
           

            if(this.edit === false){
                //add
                fetch(`api/cards`, {
                    method: 'post',
                    body:formData,
                    headers:{
                        'content-type': 'multipart/form-data',
                    }
                })
                .then(res => console.log(res))
                .then(data => {
                    this.card.title='';
                    this.card.description='';
                    alert('Card added');
                    this.fetchCards();
                })
                .catch(err => console.log(err));
            } else{
                //update
                fetch(`api/cards/${this.card.card_id}`, {
                    method: 'put',
                    body:formData,
                    headers:{
                        'content-type': 'multipart/form-data',
                    }
                })
                .then(res => console.log(res))
                .then(data => {
                    this.card.title='';
                    this.card.description='';
                    alert('Card updated');
                    this.fetchCards();
                })
                .catch(err => console.log(err));
            }
        },
        editCard(card){
            this.edit=true;
            this.card.id=card.id;
            this.card.card_id=card.id;
            this.card.title=card.title;
            this.card.description=card.description;
        },
         onFileChange(e){
               
                this.selectedFile = e.target.files[0];
                console.log(this.selectedFile);
                
            }
    }
}
</script>

The CardController script for the api:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Card;
use Intervention\Image\Facades\Image;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class CardController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
       $cards =  Card::all()->toArray();
       //return $cards;
       return array_reverse($cards);
        //return Card::orderBy('created_at', 'desc')->paginate(2);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {

        //validate data first
        $request->validate([
            'description'=> 'required'
        ]);
        
        $card = $request->all();
        
        if ($request->hasFile('picture')){
        
           // $this->validate($request, ['picture' => 'max:2000'], [__('Maximum file size of 2MB allowed')]);
            
    		$image_name = strval(time().Str::random(5)).'.png'; // voor de zekerheid string van maken..
            
            
            $image = $request->file(); //file_picture_input  is naam van file inputveld in het formulier, de naam die de request aan de file geeft
           
            $path = storage_path('images'.$image_name);
           
            $img = Image::make($image);
            $img->resize(300, 300, function ($constraint) {
                $constraint->aspectRatio();
            })->save($path); 
           
            $card['picture'] = $path;
        }
        else {
            $card['picture'] = 'img/profile/default_avatar.png';
        }
                
        //create a post
        return Card::create($card);

       
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        return Card::find($id);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $card =  Card::find($id); 
        $card->update($request->all());
        return $card;
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        return Card::destroy($id);
    }
}

Console responses in browser show successful request, but no added or edited records. Delete works fine, index shows all existing records.

The response I see in the console from the fetch-post:

Response {type: "basic", url: "http://localhost:8000/", redirected: true, status: 200, ok: true, …}
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: true
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:8000/"
[[Prototype]]: Response

0 likes
21 replies
kossa's avatar

Check your route if it's ok just dd(request()->all()) in store method to see what you send and if the store method is invoked or no.

spook1's avatar

Thnak you for your interest. The dd is a bit tricky to show, since it is an api I am calling.

This is the output in chrome, fetch/headers:


Request URL: http://localhost:8000/api/cards
Request Method: POST
Status Code: 302 Found
Remote Address: 127.0.0.1:8000
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Origin: *
Cache-Control: no-cache, private
Connection: close
Content-Type: text/html; charset=UTF-8
Date: Fri, 13 Aug 2021 18:30:34 GMT
Date: Fri, 13 Aug 2021 18:30:34 GMT
Host: localhost:8000
Location: http://localhost:8000/
X-Powered-By: PHP/7.4.14
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
POST /api/cards HTTP/1.1
Host: localhost:8000
Connection: keep-alive
Content-Length: 1298735
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?1
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36
content-type: multipart/form-data
Accept: */*
Origin: http://localhost:8000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: game_user_auth=eyJpdiI6InhFeGkwVWNYZHRoNDdObmRyRW.....

The application did work when I did not have the file implemented, so the route is ok..

The response shows "failed to load response"for the post fetch...

Can it have something to do with the formData I am sending..

Any ideas how to find the error?

kossa's avatar

You have a redirection status 302, may be the user is not logged

spook1's avatar

Can it be that i should have installed some plugin or someting? It worked without file upload before.

How can I see if a user must be loggged on? I created everything based on a tutorial, essental element may be missing...

kossa's avatar

Use auth()->check() to know if you are logged or now

spook1's avatar

tried after logging in, still same response.. The app did work before I started implementing the formData et all...

frankielee's avatar

Add this to your request header

    headers:{
                        'content-type': 'multipart/form-data',
						'accept':'application/json'
                    }

the issue probably caused by this code

     $request->validate([
            'description'=> 'required'
        ]);
spook1's avatar

the "accept : 'application/json'created a new eroor:

Request URL: http://localhost:8000/api/cards
Request Method: POST
Status Code: 422 Unprocessable Entity
Remote Address: 127.0.0.1:8000
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Origin: *
Cache-Control: no-cache, private
Connection: close
Content-Type: application/json
Date: Fri, 13 Aug 2021 19:15:19 GMT
Date: Fri, 13 Aug 2021 19:15:19 GMT
Host: localhost:8000
X-Powered-By: PHP/7.4.14
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 339102
content-type: multipart/form-data
Cookie: game_user_auth=eyJpdiI6InhFeGkwVWNYZHRoNDdObmRyRWQ4TEE9PSIsInZhbHVlIjoiRC9EbFpQbngxVjZoeWlVNWxib3ByK3VpZnZaNG11R25STEI3V1FvQmVvOG8xbXQxeFYrclFvT1ZsS2VXRmxpLzB1R0RrNmhtZTRKYXVTakJHUkZlZUFEQ1A1NmE2Z2o4UnJ3UDM4QUtQTnZWc3ZaUkp3ek1mNWsvRGUreHVKWkIiLCJtYWMiOiIwYjc5NWE0YTViY2U4YmE4NjI1NDQyYWM2ZjVmYjA2NWQ3YmM0MWVmOTU4NTA4MGFmNWUzZDk0MGY0NGVkOWRlIn0
Host: localhost:8000
Origin: http://localhost:8000
Referer: http://localhost:8000/
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?1
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36
------WebKitFormBoundaryi9P4Wf93z3TpXPAD
Content-Disposition: form-data; name="title"

ooo
------WebKitFormBoundaryi9P4Wf93z3TpXPAD
Content-Disposition: form-data; name="description"

ooo
------WebKitFormBoundaryi9P4Wf93z3TpXPAD
Content-Disposition: form-data; name="imagefile"; filename="spook22.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryi9P4Wf93z3TpXPAD--

app.js:22182 POST http://localhost:8000/api/cards 422 (Unprocessable Entity)
app.js:22190 
Response {type: "basic", url: "http://localhost:8000/api/cards", redirected: false, status: 422, ok: false, …}
app.js:22148 
(4) [{…}, {…}, {…}, {…}]

​
 

after commenting out the validation ( though I did enter a description..) I get this request payload after entering the form to create a new card:

Request payload>>



------WebKitFormBoundaryuy3gGjBJa3IcylE0
Content-Disposition: form-data; name="title"

test text
------WebKitFormBoundaryuy3gGjBJa3IcylE0
Content-Disposition: form-data; name="description"

test desription
------WebKitFormBoundaryuy3gGjBJa3IcylE0
Content-Disposition: form-data; name="imagefile"; filename="IMG_6710.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryuy3gGjBJa3IcylE0--
frankielee's avatar

the "accept : 'application/json'created a new eroor:

no, it's not. by default, the validation error will redirect the user back to the previous webpage, if the user is not login(under web middleware), it will redirect the user to the login page.

after commenting out the validation ( though I did enter a description..) I get this request payload after entering the form to create a new card:

Just make sure the description is included in the request. Log all requests, check your log file after the network request is sent.

		
		logger($request->all());
        //validate data first
        $request->validate([
            'description'=> 'required'
        ]);

spook1's avatar

thank you helping..

The log file shows:

  [2021-08-13 11:18:42] local.ERROR: Call to a member function update() on null {"exception":"[object] (Error(code: 0): Call to a member function update() on null at D:\app\Http\Controllers\CardController.php:120)

seems so strange because it used to work..

frankielee's avatar

Add this line of code before everything, after that check your log file. Probably nothing is sent. Also formData does not work with the PUT method, change it to post instead

Example of log data

public function(Request $request){
				logger($request->all());

}

Example Update request

  fetch(`api/cards/${this.card.card_id}?_method=PUT`, {
                    method: 'post',
                    body:formData,
                    headers:{
                        'content-type': 'multipart/form-data',
                    }
                })

spook1's avatar

srry, not sure what you mean.

here is the whole log after the latest request ( I am noob...)

 [2021-08-13 11:18:42] local.ERROR: Call to a member function update() on null {"exception":"[object] (Error(code: 0): Call to a member function update() on null at 
#38 {main}
"} 
[2021-08-13 19:35:43] local.DEBUG: array (
)  
[2021-08-13 19:41:40] local.DEBUG: array (
)  
[2021-08-13 19:46:15] local.DEBUG: array (
)  
 
frankielee's avatar

[2021-08-13 19:35:43] local.DEBUG: array ()

This is the output of logger($request->all());, it means no data is sent. Please check my previous reply, change the form request method.

spook1's avatar

I am testing the addCards functionality, there I use the post method already.

This is my current store function in the controller:

  public function store(Request $request)
    {

        logger($request->all());
        //validate data first
        $request->validate([
            'description'=> 'required'
        ]);

        //validate data first
         $request->validate([
            'description'=> 'required'
        ]); 
        
        $card = $request->all();
       
        if ($request->hasFile('imagefile')){
        
           // $this->validate($request, ['picture' => 'max:2000'], [__('Maximum file size of 2MB allowed')]);
           
    		
            
            $image = $request->file('picture'); //file_picture_input  is naam van file inputveld in het formulier, de naam die de request aan de file geeft
            $image_name = strval(time().Str::random(5)).$image->extension; // voor de zekerheid string van maken..
          
            $path = storage_path('images'.$image_name);
           
            $img = Image::make($image);
            $img->resize(300, 300, function ($constraint) {
                $constraint->aspectRatio();
            })->save($path); 
           
            $card['picture'] = $path;

        }
        else {
            $card['picture'] = 'img/profile/default_avatar.png';
        }
        dd($card);
        //create a post
        return Card::create($card);

       
    }
spook1's avatar

Thank you very much. I will look into it tomorrow. It is late evening here in Netherlands now...

spook1's avatar

Thanks, now I also got this solved, almost..

The put works in Postman, using: "localhost:8000/api/cards/4?_method=PUT" and Post,

The backend works as well, records are updated as progrmammed in the controller.

but when I issue the same command in the vue-app I get the response: TypeError: Failed to fetch

laravel log after updating, unusccesfull, no record is actually changed

[2021-08-14 12:07:56] local.DEBUG: array (
  'title' => 'test',
  'description' => 'test',
  '_method' => 'PUT',
  'imagefile' => 
  Illuminate\Http\UploadedFile::__set_state(array(
     'test' => false,
     'originalName' => 'IMG_6736.jpg',
     'mimeType' => 'image/jpeg',
     'error' => 0,
     'hashName' => NULL,
  )),
)  

spook1's avatar

No, in postman it is, in the laravel-vue it is not. Will read the link tomorrow

spook1's avatar

Excuse me, just saw that the update IS SUCCESFULL. The record in the database is changed.

I think it was because I still had

.then(res => res.formData()) 

in the fetch method

spook1's avatar

Now my next problem is that, whenever I use the appende file in the controller, I run into errors like:

  Error: Call to a member function getClientOriginalName() on null in file D:ijsbreker_memory\app\Http\Controllers\CardController.php on line 50

But, thanks to the logger you asked me to add I nknow from the laravel.logs that the request entering the Controller is:


[2021-08-15 08:34:04] local.DEBUG: array (
  'title' => 'test_werkt nu??',
  'description' => 'test',
  '_method' => 'PUT',
  'imagefile' => 
  Illuminate\Http\UploadedFile::__set_state(array(
     'test' => false,
     'originalName' => 'klein.png',
     'mimeType' => 'image/png',
     'error' => 0,
     'hashName' => NULL,
  )), 

Please or to participate in this conversation.