php - CakePHP unable to delete associations by cascade or beforeDelete()

355

I'm on CakePHP 2.6

I want to delete several dependent models...

Users             hasMany ConversationsUser (join model)
ConversationsUser belongsTo User
                  belongsTo Conversation
Conversation      hasMany ConversationsUser

All relationships aredependent => TRUE

When I delete a User, I want all ConversationsUser to be deleted, as well as all Conversations.

Currently, only the ConversationsUser get deleted. The Conversations remain.

Theory: Maybe cascade doesn't work recursively, across multiple relationships...

So I add this to ConversationsUser model

public function beforeDelete ( $cascade = true ) {
    $this->log( $this->conversation_id );
    $this->log( $this->ID );

    #delete all conversations
    $this->Conversation->delete( $this->conversation_id );

    return TRUE;
}

This STILL doesn't work... and neither property appears in the logs, although the timestamp DOES (so I know the callback is running).

  1. Why are those properties not defined in thebeforeDelete()
  2. Why isn't my cascading deleted working.

NOTE: In case it's relevant, all my models use the Containable behavior

Update: As there seems to be some confusion about what I'm trying to do, I'll provide some context. The app allows two different users to conduct a "Conversation" which hasMany Messages. The user's membership in the conversation is defined by a hasMany relationship with a ConversationsUser (join table) model. If an administrator deletes one of the users in the conversation, all of that user's messages, conversations, and ConversationsUser(s) need to be deleted... as well as the ConversationsUser of the other participant(s) in the deleted Conversation(s). Otherwise those other users are left having a conversation with no one and things break.

609

Answer

Solution:

Here is an incomplete answer - I can't write and test actual code right now.

In your User model, add a beforeDelete callback. This callback needs to

  1. Get a list of all Conversations for that user (e.g.,$this->ConversationsUser->findAllByUserId($this->id, array('conversation_id')))
  2. Iterate through the array of conversation_id's from the previous step and delete each one (making sure to have Cascade=True) (e.g.,$this->ConversationUser->Conversation->delete($conversation_id,true);
  3. Return True, so the User record is deleted

You don't need a beforeDelete in the ConversationUser model.

This works:

public function beforeDelete( $cascade = TRUE ) {

    #delete all conversations
    $conversationIns = $this->ConversationIn->find('all', array('conditions'=>array('ConversationIn.user_id'=>$this->id)));

    foreach ($conversationIns as $conversationIn ) {
        $delete = $this->ConversationIn->Conversation->delete( $conversationIn['ConversationIn']['conversation_id'] );
    }

    return TRUE;
}

People are also looking for solutions to the problem: php - Validation of fosuser field username

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.