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

Philword's avatar

Help to find a problem

I have 3 tables users, documents, document_user(pivot table).

I already have attach() method that works great, and trying to figure out detach() method. I created it as I see should work, but it detach() only last record in document_user, but I need to detach exactly $userId that sends from form request. Kind of confused, because my method send exact userId.

So how my method looks:

public function unshare(Request $request, $company_id, $id)
    {
        $document = Document::find($id);
        $userId = $request['id'];
        $user = User::findOrFail($userId);
        $document->users()->detach($userId);
        flash('Document access has been updated!');
        return back();
    }

My form:

<form id="unsahre" method="POST" action="/company/{{ $company->id }}/document/{{ $document->id }}/unshare">
                        {{ csrf_field() }}
       <input type="hidden" name="id" value="{{ $user->id }}">
       <a href="javascript:{}" style="color: #f0506e" onclick="document.getElementById('unsahre').submit(); return false;"><i class="fas fa-times"></i></a>
</form>
0 likes
17 replies
Philword's avatar

@jlrdw The problem is, that my method looks like should work, I have clear understand about 3 tables relationship. I just need tip what's wrong with my code, bc it's shows correct logic

Philword's avatar

@Vilfago I tried it, but it still delate last record in document_user pivot table

Vilfago's avatar

You take a look at the query?

Do you have attached many times the same document to the same user?

Philword's avatar

@Vilfago It's document share function. User upload documents and can share or unshare it with other users. It can be done many times as user wants

Vilfago's avatar

Maybe you should use syncWithoutDetaching instead of attach to avoid duplicate value. Even if I remember well, there is no LIMIT to the detach query, so it should detach everything even if there are duplicate data.

What do you mean by

delete the last record

It delete a record that is not related to the user.

Philword's avatar

@Vifago I have tried syncWithoutDetaching but still same problem.

It's actually work super weird. Example: I have 4 files and 4 users. Every file shared with all 4 users. Screenshot: http://joxi.ru/nAyoE3BHYgDvQm

If I send unshare to the 1st doc in the row, it actually unshare second doc in the list with random user->id

If I send unshare to the any other doc in the list, it unshare only 1st doc in the list with random $user->id http://joxi.ru/D2PGbR4fpqy4Pm

Super weird.

Vilfago's avatar

Do you have different id for all your form in the view? Maybe it's not the right one which is submitted.

Have a look at the data in your method

Philword's avatar

@Vilfago Yes, check the view

<div class="uk-modal-dialog" tabIndex="-1">
    <button class="uk-modal-close-default" type="button" uk-close></button>
    <div class="uk-padding-large">
        <h3>{{ $document->name }}</h3>
        <p>The following users can view this document:</p>
        <div class="uk-grid-small uk-child-width-1-4@s uk-text-center uk-background-muted" uk-grid>
            @foreach($document->users as $user)
                <div class=" uk-padding-small">
                    <form id="unsahre" method="POST" action="/company/{{ $company->id }}/document/{{ $document->id }}/unshare">
                        {{ csrf_field() }}
                        <input type="hidden" name="id" value="{{ $user->id }}">
                        <a href="javascript:{}" style="color: #f0506e" onclick="document.getElementById('unsahre').submit(); return false;"><i class="fas fa-times"></i></a>
                    </form>
                    <div class="uk-flex uk-flex-center uk-width-1-1">
                        <h5>{{ $user->first_name}} {{ $user->last_name}}</h5>
                    </div>
                </div>
            @endforeach
        </div>
    </div>
jlrdw's avatar

Are you clearing the cache and temp views between code changes.

Vilfago's avatar

All your form have the same name and id... as it come from the same loop. So I think it will always take the first form of the loop.

Try


@foreach($document->users as $user)
               <div class=" uk-padding-small">
                   <form id="unsahre{{ $user->id }}" method="POST" action="/company/{{ $company->id }}/document/{{ $document->id }}/unshare">
                       {{ csrf_field() }}
                       <input type="hidden" name="id" value="{{ $user->id }}">
                       <a href="javascript:{}" style="color: #f0506e" onclick="document.getElementById('unsahre{{ $user->id }}').submit(); return false;"><i class="fas fa-times"></i></a>
                   </form>
                   <div class="uk-flex uk-flex-center uk-width-1-1">
                       <h5>{{ $user->first_name}} {{ $user->last_name}}</h5>
                   </div>
               </div>
           @endforeach 
Philword's avatar

@Vilfago Yeah, that looks already more like true, but it doesn't fix the problem :(

Snapey's avatar

you say it 'only detaches the last record'

You should be able to tell then which ids are being removed.

In your posted code you get the $user... what was that for?

If I were you I would

a) experiment in tinker until you understand how it works, or,

b) install debugbar and check the sql

It can be tricky to see what is going on when all your ids are 1,2,3 etc so it might be worth creating extra records so you can easily differentiate the ids

Philword's avatar

@Vilfago

P.S. When its only one document record is docs table, everything works great, when more then 1 everything works bad :)

Snapey's avatar

The docs are clear

// Detach a single role from the user...
$user->roles()->detach($roleId);

but you need to make sure you are passing the right ID

Please or to participate in this conversation.