PHP code example of truefanspace / laravel-react-reactions

1. Go to this page and download the library: Download truefanspace/laravel-react-reactions library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

truefanspace / laravel-react-reactions example snippets


use TrueFans\LaravelReactReactions\Traits\HasReactions;
use TrueFans\LaravelReactReactions\Traits\HasComments;

class Post extends Model
{
    use HasReactions, HasComments;

    protected $appends = ['reactions_summary', 'user_reaction'];

    public function canManageComment($comment): bool
    {
        // null = creating new comment, Comment instance = editing/deleting
        if ($comment === null) {
            return auth()->check(); // Anyone can comment
        }
        
        // Users can manage their own comments
        return $comment->user_id === auth()->id();
    }
}

use Illuminate\Support\Facades\DB;

class PostController extends Controller
{
    public function index()
    {
        $userId = auth()->id();
        
        // ✅ OPTIMIZED: Load all posts with reactions in 1 query
        $posts = Post::withReactionsData($userId)
            ->latest()
            ->get()
            ->map(fn($post) => [
                'id' => $post->id,
                'title' => $post->title,
                'reactions_summary' => $post->parseReactionsSummary(),
                'user_reaction' => $post->parseUserReaction(),
            ]);

        return Inertia::render('Posts/Index', ['posts' => $posts]);
    }

    public function show(Post $post)
    {
        $userId = auth()->id();
        
        // ✅ OPTIMIZED: Load all comments with reactions efficiently
        $postIds = [$post->id];
        
        // Get comment counts in one query
        $commentCounts = Comment::whereIn('commentable_id', $postIds)
            ->where('commentable_type', Post::class)
            ->whereNull('parent_id')
            ->select('commentable_id', DB::raw('count(*) as total'))
            ->groupBy('commentable_id')
            ->pluck('total', 'commentable_id');
        
        // Load comments with replies in one query
        $comments = Comment::where('commentable_id', $post->id)
            ->where('commentable_type', Post::class)
            ->whereNull('parent_id')
            ->with(['user:id,name,email', 'replies.user:id,name,email'])
            ->withCount('replies')
            ->latest()
            ->take(5)
            ->get()
            ->map(fn($comment) => [
                'id' => $comment->id,
                'content' => $comment->content,
                'user' => $comment->user,
                'user_id' => $comment->user_id,
                'created_at' => $comment->created_at,
                'is_edited' => $comment->is_edited,
                'can_edit' => $userId === $comment->user_id,
                'can_delete' => $userId === $comment->user_id,
                'replies_count' => $comment->replies_count,
                'replies' => $comment->replies->map(fn($reply) => [
                    'id' => $reply->id,
                    'content' => $reply->content,
                    'user' => $reply->user,
                    'user_id' => $reply->user_id,
                    'created_at' => $reply->created_at,
                    'is_edited' => $reply->is_edited,
                    'can_edit' => $userId === $reply->user_id,
                    'can_delete' => $userId === $reply->user_id,
                ]),
            ]);

        return Inertia::render('Posts/Show', [
            'post' => $post,
            'comments' => $comments,
            'total_comments' => $commentCounts->get($post->id, 0),
        ]);
    }
}

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return [
            ...parent::share($request),
            'auth' => [
                'user' => $request->user(),
            ],
            'flash' => [
                'success' => fn() => $request->session()->get('success'),
                'error' => fn() => $request->session()->get('error'),
            ],
            // Share reaction types from config
            'reactionTypes' => config('react-reactions.types', []),
        ];
    }
}

// Loading 10 posts = 21 queries (1 + 10*2)
$posts = Post::latest()->get(); // Appended attributes cause N+1

// Loading 10 posts = 1 query
// Loading 1000 posts = still 1 query!
$posts = Post::withReactionsData(auth()->id())
    ->latest()
    ->get()
    ->map(fn($post) => [
        'id' => $post->id,
        'reactions_summary' => $post->parseReactionsSummary(),
        'user_reaction' => $post->parseUserReaction(),
    ]);

$posts->map(function($post) {
    $comments = $post->comments()->get(); // N+1 query
    $totalComments = $post->comments()->count(); // Another N+1
});

$postIds = $posts->pluck('id');

// Get all comment counts in 1 query
$commentCounts = Comment::whereIn('commentable_id', $postIds)
    ->where('commentable_type', Post::class)
    ->whereNull('parent_id')
    ->select('commentable_id', DB::raw('count(*) as total'))
    ->groupBy('commentable_id')
    ->pluck('total', 'commentable_id');

// Load all comments with replies in 1 query
$allComments = Comment::whereIn('commentable_id', $postIds)
    ->where('commentable_type', Post::class)
    ->whereNull('parent_id')
    ->with(['user', 'replies.user'])
    ->withCount('replies')
    ->latest()
    ->get()
    ->groupBy('commentable_id');

return [
    // Customize reaction types and emojis
    'types' => [
        'like' => '👍',
        'adore' => '🥰',  // You can change this to 'love' => '❤️'
        'haha' => '😂',
        'wow' => '😮',
        'sad' => '😢',
        'angry' => '😠',
        // Add your own:
        // 'fire' => '🔥',
        // 'celebrate' => '🎉',
    ],

    'comments' => [
        'reactions_enabled' => true,
        'max_depth' => 3,
        'edit_timeout' => 300, // seconds
        'per_page' => 10,
    ],

    'notifications' => [
        'enabled' => true,
        'admin_email' => env('REACTIONS_ADMIN_EMAIL'),
        'notify_owner' => true,
        'notify_parent_author' => true,
    ],
];

public function share(Request $request): array
{
    return [
        ...parent::share($request),
        'reactionTypes' => config('react-reactions.types', []),
    ];
}

// Add or update reaction
$model->react(int $userId, string $type): void

// Remove reaction
$model->unreact(int $userId): void

// Get reactions summary
$model->reactionsSummary(): array

// Get user's reaction
$model->userReaction(int $userId): ?string

// Query scope for optimized loading
Model::withReactionsData(?int $userId)

// Parse reactions data (after withReactionsData)
$model->parseReactionsSummary(): array
$model->parseUserReaction(): ?string

// Add a comment
$model->addComment(int $userId, string $content): Comment

// Get comments relationship
$model->comments(): MorphMany

// Check permissions
$model->canManageComment(?Comment $comment): bool

// Add a reply
$comment->addReply(int $userId, string $content): Comment

// Get replies
$comment->replies(): HasMany

// Check permissions
$comment->canEdit(): bool
$comment->canDelete(): bool

// Query scope
Comment::topLevel() // Only top-level comments
bash
php artisan vendor:publish --provider="TrueFans\LaravelReactReactions\LaravelReactReactionsServiceProvider"
bash
# Publish and run migrations
php artisan vendor:publish --tag=react-reactions-migrations
php artisan migrate

# Publish React components (TypeScript)
php artisan vendor:publish --tag=react-reactions-components

# Publish configuration file
php artisan vendor:publish --tag=react-reactions-config
jsx
import Reactions from '@/Components/Reactions/Reactions';
import Comments from '@/Components/Comments/Comments';

export default function PostShow({ post, comments, total_comments }) {
    return (
        <div>
            <h1>{post.title}</h1>
            
            {/* Reactions */}
            <Reactions
                reactableType="App\\Models\\Post"
                reactableId={post.id}
                initialReactions={post.reactions_summary}
                userReaction={post.user_reaction}
            />

            {/* Comments */}
            <Comments
                commentableType="App\\Models\\Post"
                commentableId={post.id}
                initialComments={comments}
                totalComments={total_comments}
                currentUserId={auth.user.id}
            />
        </div>
    );
}