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

hjortur17's avatar

When I submit a reply form it created duplication of the reply.

Hello, I have form on my website to update,delete and create a reply. And if I create a reply I get two of the same reply in my server.

My Controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Reply;
use App\Thread;

class RepliesController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function store($channelId, Thread $thread)
    {
        $this->validate(request(), ['body' => 'required']);

        $thread->addReply([
            'user_id' => auth()->id(),
            'body' => request('body')
        ]);

        return back()->with('flash', 'Ummælin þín hafa verið birt');
    }

    public function update(Reply $reply)
    {
        $this->authorize('update', $reply);
        
        $reply->update(request(['body']));
    }

    public function destroy(Reply $reply)
    {
        $this->authorize('update', $reply);

        $reply->delete();

        if (request()->expectsJson()) {
            return response(['status' => 'Reply deleted']);
        }

        return back();
    }
}

My route:

Route::post('/fréttir/{channel}/{thread}/athugasemdir', 'RepliesController@store');
Route::delete('/athugasemdir/{reply}', 'RepliesController@destroy');
Route::patch('/athugasemdir/{reply}', 'RepliesController@update');

Route::post('/athugasemdir/{reply}/líka-við', 'FavoritesController@store');
Route::delete('/athugasemdir/{reply}/líka-við', 'FavoritesController@destroy');

My blade:

<div class="container mt-6">
    <div class="bg-white shadow rounded-lg p-4">
        <div class="flex flex-col">
            @if ($thread->replyCount) === 0)
    
            @else
                @foreach ($replies as $reply)
                    <reply :attributes="{{ $reply }}" inline-template v-cloak>
                        <div id="reply-{{ $reply->id }}" class="w-full bg-grey-lightest p-3 rounded mb-3">
                            <div class="flex">
                                <div class="w-16 self-start">
                                    <img src="/css/img/test_avatar.jpg" class="w-10 h-10 border border-grey-light rounded-full mx-auto">
                                </div>
                                <div class="w-full">
                                    <div class="flex flex-col">
                                        <div class="w-full">
                                            <div class="flex">
                                                <div class="flex-1">
                                                    <h4 class="text-blue-darkest"><a href="/notendur/{{ $reply->owner->username }}" class="no-underline text-blue hover:text-blue-dark transition">{{ $reply->owner->name }}</a></h4>
                                                    <small class="font-light text-xs text-grey-dark">{{ $reply->updated_at->diffForHumans() }}</small>
                                                </div>
                                                <div class="w-20">
                                                    <div class="w-full flex justify-between">
                                                        @if (Auth::check())
                                                            <favorite :reply="{{ $reply }}"></favorite>
                                                        @endif
                                                        @can ('update', $reply)
                                                            <div class="w-auto mr-1">
                                                                <button @click="editing = true">
                                                                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="13px" width="13px"><path d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z" fill="#3490dc"/></svg>
                                                                </button>
                                                            </div>
                                                            <div class="w-auto">
                                                                <button @click="destroy">
                                                                    <svg height="13px" width="13px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M32 464a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128H32zm272-256a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zM432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z" fill="#ef5753"/></svg>
                                                                </button>
                                                            </div>
                                                        @endcan
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="w-full">
                                            <div v-if="editing" class="mt-2">
                                                <textarea class="w-full text-sm p-2 border-2 border-grey bg-white outline-none resize-none focus:border-blue transition rounded leading-normal" v-model="body"></textarea>

                                                <div class="flex w-32 float-right mt-2">
                                                    <div class="flex-1 text-right">
                                                        <button class="bg-blue border-2 border-blue rounded-full text-xs text-center text-white px-2 py-1" @click="update">Uppfæra</button>
                                                    </div>
                                                    <div class="flex-1 text-right self-center">
                                                        <button class="text-sm text-grey-darker hover:text-red-light transition" @click="editing = false">Hætta</button>
                                                    </div>
                                                </div>
                                            </div>

                                            <div v-else>
                                                <p class="text-sm leading-normal mt-2" v-text="body"></p>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </reply>
                @endforeach
            @endif

            {{ $replies->links() }}

            @if (auth()->check())
                <div class="w-full mt-4">
                    <div class="flex">
                        <div class="w-16 self-start">
                            <img src="/css/img/test_avatar.jpg" class="w-10 h-10 border border-grey-light rounded-full float-right mx-auto">
                        </div>
                        <div class="w-full pl-4">
                            <form action="{{ $thread->path().'/athugasemdir'}}" method="POST">
                                @csrf

                                <div class="flex flex-col">
                                    <div class="w-full">
                                        <textarea class="w-full p-2 text-grey-darkest text-sm border-2 border-grey-light rounded-lg focus:border-blue transition-md outline-none resize-none" rows="3" name="body" id="body" placeholder="Hvað liggur þér á hjarta í dag?"></textarea>
                                    </div>

                                    <div class="w-full">
                                        <button class="px-4 py-2 mt-1 float-right text-grey-darkest text-sm border-2 border-grey-light rounded-full hover:border-blue hover:bg-blue hover:text-white transition-md" type="submit">Pósta</button>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            @else 
                <p class="text-grey-darker text-center my-2">Þarft að vera <a href="/login" class="no-underline text-blue">skráð/ur inn</a> til þess að taka þátt í umræðuni!</p>
            @endif
        </div>
    </div>
</div>

0 likes
4 replies
Snapey's avatar

When you CREATE a reply you get two replies, or WHEN you EDIT a reply you get a new reply and the original?

Have you some Vue code also?

hjortur17's avatar

@snapey - When I CREATE a reply I get two replies.

Here is Reply.vue

<script>
    import Favorite from './Favorite.vue';

    export default {
        props: ['attributes'],

        components: { Favorite },

        data() {
            return {
                editing: false,
                body: this.attributes.body
            };
        },

        methods: {
            update() {
                axios.patch('/athugasemdir/' + this.attributes.id, {
                    body: this.body
                });

                this.editing = false;

                flash('Ummælin þín hafa verið uppfærð');
            },
            
            destroy: function destroy() {
                axios.delete('/athugasemdir/' + this.attributes.id);

                $(this.$el).fadeOut(300, function () {
                    flash('Ummælunum þínum hefur verið eytt.');
                });
            }
        }
    }
</script>

Here is the app.js

require('./bootstrap');

window.Vue = require('vue');

import Flash from './components/Flash.vue';
import Reply from './components/Reply.vue';
import Favorite from './components/Favorite.vue';

const app = new Vue({
    el: '#app',
    components: {Flash, Reply, Favorite}
});

And the Favorite.php

<template>
    <button class="flex-1" @click="toggle">
        <span v-text="count" class="text-grey-darker text-sm"></span>

        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="13px" width="13px" v-if="active"><path d="M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z" fill="#ef5753"/></svg>
        <svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" height="13px" width="13px" v-else><path d="m462.3 62.7c-54.5-46.4-136-38.7-186.6 13.5l-19.7 20.4-19.7-20.3c-40.8-42.2-123.1-67.6-186.6-13.6-62.8 53.6-66.1 149.8-9.9 207.8l193.5 199.8c6.2 6.4 14.4 9.7 22.6 9.7s16.4-3.2 22.6-9.7l193.5-199.8c56.4-58 53.1-154.2-9.7-207.8zm-13.1 185.6-192.8 199.8-193.6-199.8c-38.4-39.6-46.4-115.1 7.7-161.2 54.8-46.8 119.2-12.9 142.8 11.5l42.7 44.1 42.7-44.1c23.2-24 88.2-58 142.8-11.5 54 46 46.1 121.5 7.7 161.2z" fill="#8795a1"/></svg>
    </button>
</template>

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

        data() {
            return {
                count: this.reply.favoritesCount,
                active: this.reply.isFavorited
            }
        },

        computed: {
            classes() {
                return [this.active ? 'bg-white' : 'bg-blue'];
            },

            endpoint() {
                return '/athugasemdir/' + this.reply.id + '/líka-við';
            }
        },

        methods: {
            toggle() {
                this.active ? this.destroy() : this.create();
            },

            create() {
                axios.post(this.endpoint);

                this.active = true;
                this.count++;
            },

            destroy() {
                axios.delete(this.endpoint);

                this.active = false;
                this.count--;
            }
        }
    }
</script>
Snapey's avatar

Sounds like you are sending Vue ajax form submission and also allowing the form to be submitted

Check what network requests are being sent from your browser using network browser tools

hjortur17's avatar
hjortur17
OP
Best Answer
Level 14

I have not found out what was causing this to happen but I tried to clear cache and clear route and restart the computer and it stopped. Wondering if something was wrong in the browser...

Please or to participate in this conversation.