---
title: "Transferring comments — Comments for Laravel | Roundly"
description: "Move a whole discussion from one record to another when duplicates merge — replies, held and deleted comments included, with likes and attachments."
url: https://roundly-consulting.com/open-source/docs/comments-for-laravel/transferring-comments
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Comments for Laravel](https://roundly-consulting.com/open-source/docs/comments-for-laravel.md)

# Transferring comments

Comments::transfer($from, $to) moves every comment of one subject onto another and returns how many moved — for merging two records, such as duplicate tickets or two posts about the same thing. It re-points the commentable morph of all of $from’s comments in one transaction: top-level comments and replies, invisible, pending and hidden ones, and soft-deleted ones too, so a later restore lands on $to:

```php
use RoundlyConsulting\Comments\Facades\Comments;

$moved = Comments::transfer($duplicate, $original);   // int — e.g. 4
```

## What travels with the comments

- Replies keep their parent\_id, and every parent moves with them, so threads stay whole.
- Mentions, likes, reports and attachments belong to the comment, not the subject, so they follow it.
- A thread lock (locked\_at) is on the comment and travels with it.
- A subject lock stays where it is: a locked $from stays locked — moving its comments out is allowed — and $to does not become locked.
- Comments $from wrote as an author are not touched; only comments on it move.
- updated\_at is left alone — a move is not an edit.

## Refusals

When a check fails, nothing moves, nothing is recorded and no event fires:

- $from and $to are the same subject — the same morph type and key, even as two instances — so InvalidCommentTransferException is thrown.
- $to is subject-locked, so CommentsLockedException is thrown.
- With comments.authorization on, the policy’s existing create ability is checked on $to — create(?Model $user, ?Model $commentable) with $to as the commentable — and a denial throws UnauthorizedCommentActionException. A policy that doesn’t extend CommentPolicy needs no new method.

```php
use RoundlyConsulting\Comments\Exceptions\CommentsLockedException;
use RoundlyConsulting\Comments\Exceptions\InvalidCommentTransferException;

try {
    Comments::transfer($duplicate, $original);
} catch (InvalidCommentTransferException $e) {
    // $duplicate and $original are the same subject
} catch (CommentsLockedException $e) {
    // $original is locked
}
```

## After the move

CommentsTransferred fires with $from, $to and $count — also when nothing moved and $count is 0 — and Comments::fake() records the call for assertTransferred() (see Testing):

```php
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Comments\Events\CommentsTransferred;

Event::listen(function (CommentsTransferred $event): void {
    $event->from;   // the subject the comments left
    $event->to;     // the subject they now belong to
    $event->count;  // how many moved — 0 is possible
});
```

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/comments-for-laravel.md)
