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

jeroenvanrensen's avatar

Axios sends two requests

Hi everyone,

I've got this code:

axios.delete('/notes/' + this.note.id + '/favorite');

But if I inspect my network tab, I see these two requests:

delete: http://notes.local/notes/4/favorite
delete: http://notes.local/notes/4

So, my note will be deleted too. What can I do about this?

Thank you! Jeroen

Note: by the favorite post request I do have the same problem, but then I get a 404 error, so it's not a problem.

0 likes
28 replies
bobbybouwmann's avatar

Well, you probably do two requests somehow... Axios is not suddenly firing two calls. Can you show more of your code?

1 like
jeroenvanrensen's avatar

@bobbybouwmann yes, of course!

Here's my full FavoriteButtonComponent:

<template>
    <div>
        <button v-if="favorited" @click="unfavorite"><i class="fas fa-star"></i></button>
        <button v-else @click="favorite"><i class="far fa-star"></i></button>
    </div>
</template>

<script>
    export default {
        props: [
            'note'
        ],

        data() {
            return {
                favorited: false
            }
        },

        methods: {
            favorite() {
                this.favorited = true;

                axios.post('/notes/' + this.note.id + '/favorite');
            },

            unfavorite() {
                this.favorited = false;

                axios.delete('/notes/' + this.note.id + '/favorite');
            }
        },

        mounted() {
            this.favorited = this.note.is_favorited;
        }
    }
</script>
bobbybouwmann's avatar

This does look correct. I don't see a reason why it would fire two calls and especially not two different URLs.

Do you have more components that use this component? Can you show the component that uses this URL http://notes.local/notes/4?

1 like
jeroenvanrensen's avatar

@bobbybouwmann this is the only one, DeleteButtonComponent, but I do not see any reason why it would happen.

<template>
    <div>
        <button @click="deleteNote"><i class="fas fa-trash-alt"></i></button>
    </div>
</template>

<script>
    export default {
        props: [
            'id'
        ],

        methods: {
            deleteNote() {
                axios.delete('/notes/' + this.id)
                    .then(function() {
                        this.$root.$emit('emptyNote');
                        this.$root.$emit('refresh');
                    }.bind(this));
            }
        }
    }
</script>
jlrdw's avatar

Check the naming in the code.

MaverickChan's avatar

if you are buliding a SPA with vue-router , pay attention to the wildcard route model binding , don't use the same name , vue-router will transform request for example laravel route

post '/notes/{note}/favorate'

vue-router

path:  '/notes/:note' ,  //this is vue router path , a get request

so , change laravel route name to notestest and try again

jeroenvanrensen's avatar

Hi @jlrdw how do you mean check the naming?

@maverickchan I don't use Vue Routing, but Laravel Routing.

These are my routes:

Route::get('/', function () {
    return view('welcome');
});

Route::get('/notes', 'NoteController@show');
Route::post('/notes', 'NoteController@store');
Route::patch('/notes/{note}', 'NoteController@update');
Route::delete('/notes/{note}', 'NoteController@destroy');

Route::post('/notes/{note}/favorite', 'NoteFavoritesController@store');
Route::delete('/notes/{note}/favorite', 'NoteFavoritesController@destroy');

Route::get('/api/notes', 'NoteController@index');
Route::get('/api/notes/{note}', 'NoteController@edit');

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
jeroenvanrensen's avatar

Note: If I remove the axios delete request from the FavoriteButtonComponent, the note does not get deleted. So the problem is some where in that component.

MaverickChan's avatar

these are in your web.php file right? what is in your api.php? did you change anything.

as far as i can tell you provide 2 conflict route

post and delete at the same route name rename delete

Route::delete('/notes/{note}/unfavorite','NoteFavoritesController@destroy');
jeroenvanrensen's avatar

Hi @maverickchan,

I do not use the api.php, because I don't know how it works.

You said you saw a conflicting route? Can you tell me more about that?

Thank you! Jeroen

MaverickChan's avatar
Route::post('/notes/{note}/favorite', 'NoteFavoritesController@store');
Route::delete('/notes/{note}/favorite', 'NoteFavoritesController@destroy');

these 2 routes are the same change delete to unfavorite

jeroenvanrensen's avatar

Hi @maverickchan,

I changed it but it doesn't fix it, which makes sense actually, because Laravel makes difference between post and delete requests.

However, thanks for trying to help me!

MaverickChan's avatar

npm run dev or watch again and give the browser a hard refresh check your other component again

jeroenvanrensen's avatar

@bobbybouwmann sure here you have it.

FavoriteButtonComponent.vue

<template>
    <div>
        <button v-if="favorited" @click="unfavorite"><i class="fas fa-star"></i></button>
        <button v-else @click="favorite"><i class="far fa-star"></i></button>
    </div>
</template>

<script>
    export default {
        props: [
            'note'
        ],

        data() {
            return {
                favorited: false
            }
        },

        methods: {
            favorite() {
                this.favorited = true;

                axios.post('/notes/' + this.note.id + '/favorite');

                this.$root.$emit('refresh');
            },

            unfavorite() {
                this.favorited = false;

                axios.delete('/notes/' + this.note.id + '/favorite');

                this.$root.$emit('refresh');
            }
        },

        mounted() {
            this.favorited = this.note.is_favorited;
        }
    }
</script>

routes/web.php

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/notes', 'NoteController@show');
Route::post('/notes', 'NoteController@store');
Route::patch('/notes/{note}', 'NoteController@update');
Route::delete('/notes/{note}', 'NoteController@destroy');

Route::post('/notes/{note}/favorite', 'NoteFavoritesController@store');
Route::delete('/notes/{note}/favorite', 'NoteFavoritesController@destroy');

Route::get('/api/notes', 'NoteController@index');
Route::get('/api/notes/{note}', 'NoteController@edit');

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

NoteController.php

<?php

namespace App\Http\Controllers;

use App\Note;
use Carbon\Carbon;

class NoteController extends Controller
{
    /**
     * Only authenticated users can use this controller
     *
     * @return  void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Returns all the notes of the authenticated user
     *
     * @return  array
     */
    public function index()
    {
        $notes = \App\Note::where('user_id', auth()->id());

        if(request()->has('favorites')) {
            $notes = $notes->where('is_favorited', true);
        }
        
        if(request()->has('trash')) {
            $notes = $notes->onlyTrashed();
        }

        if(request()->has('query')) {
            $notes = $notes->where('title', 'like', '%' . request('query') . '%');
        }

        $notes = $notes->orderBy('updated_at', 'desc')->get();

        return $notes;
    }

    /**
     * Returns an empty page
     *
     * @return  view
     */
    public function show()
    {
        $this->permanentlyDeleteNotes();

        return view('notes.show');
    }

    /**
     * Creates a new note
     *
     * @return  void
     */
    public function store()
    {
        $note = Note::create([
            'title' => $this->setTitle(''),
            'user_id' => auth()->id()
        ]);

        return $note->id;
    }

    /**
     * Returns the note in an edit form
     *
     * @param   Note  $note
     *
     * @return  view
     */
    public function edit(Note $note)
    {
        $this->authorize('update', $note);

        if($note->trashed()) {
            $note->restore();
        }

        return $note;
    }

    /**
     * Saves the edited note
     *
     * @param   Note  $note
     *
     * @return  void
     */
    public function update(Note $note)
    {
        $this->authorize('update', $note);

        $note->update([
            'title' => $this->setTitle(request('body')),
            'body' => request('body')
        ]);
    }

    /**
     * Deletes a note
     *
     * @param   Note  $note
     *
     * @return  void
     */
    public function destroy(Note $note)
    {
        $this->authorize('update', $note);

        $note->delete();
    }

    /**
     * Generates a title based on the body
     *
     * @param   string  $body
     *
     * @return  string
     */
    protected function setTitle($body)
    {
        if($title = strtok($body, "\n")) {
            return preg_replace('/^[ #]+/', '', $title);
        }
        
        return 'Untitled';
    }

    protected function permanentlyDeleteNotes()
    {
        Note::withTrashed()
            ->where('deleted_at', '<', Carbon::now()->subMonth())
            ->forceDelete();
    }
}
MaverickChan's avatar

in your controller , destroy () function , you authorize a 'update' instead of 'delete'

that could be the problem?

jeroenvanrensen's avatar

Hi @maverickchan,

It's working! Now Axios also sends a patch request, but that returns in a 404 error. So the client doesn't notice. It's not perfect, but it works!

Thank you very much! Jeroen

MaverickChan's avatar

you can try my previous suggestion ,change delete route to /unfavorite

MaverickChan's avatar

maybe you should see Jeffery's tutorial of Building a forum with TDD , i remember he has a favorite unfaoverite example, and pay attention to the controller

jeroenvanrensen's avatar
Level 15

@bobbybouwmann @jlrdw @maverickchan

I finally found the problem

This is my controller code:

<?php

namespace App\Http\Controllers;

use App\Note;

class NoteFavoritesController extends Controller
{
    /**
     * Saves a favorite
     *
     * @param   Note  $note
     *
     * @return  redirect
     */
    public function store(Note $note)
    {
        $this->authorize('update', $note);

        $note->favorite();

        return redirect('/notes/' . $note->id);
    }

    /**
     * Removes a favorite
     *
     * @param   Note  $note
     *
     * @return  redirect
     */
    public function destroy(Note $note)
    {
        $this->authorize('update', $note);
        
        $note->unfavorite();

        return redirect('/notes/' . $note->id);
    }
}

But because of the redirects at the end it does not work. So if I remove them, it does work!

1 like
bobbybouwmann's avatar

Aah yeah, that makes sense. You can't redirect to a note you just deleted. In your case, you should never return a redirect in an ajax request ;)

Please or to participate in this conversation.