Installation
composer require dvtrung/comment-bundle
Add to config/bundles.php (Symfony) or config/app.php (Laravel via bridge):
return [
// ...
DvTrung\CommentBundle\DvTrungCommentBundle::class => ['all' => true],
];
Publish Config
php artisan vendor:publish --provider="DvTrung\CommentBundle\DvTrungCommentBundle" --tag="config"
Edit config/comment.php to define:
default_driver (e.g., database, disqus, or custom)First Use Case: Database Comments
Define a model (e.g., Post) with a comments() relationship:
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
Create a comment via facade:
use DvTrung\CommentBundle\Facades\Comment;
$comment = Comment::create([
'commentable_id' => $post->id,
'commentable_type' => Post::class,
'user_id' => auth()->id(),
'body' => 'Great post!',
]);
Blade Integration
@commentable($post)
@foreach($post->comments as $comment)
<div>{{ $comment->body }}</div>
@endforeach
@endcommentable
Switching Drivers Dynamically
Configure multiple drivers in config/comment.php:
'drivers' => [
'database' => [
'table' => 'comments',
],
'disqus' => [
'shortname' => 'your-site',
'api_key' => env('DISQUS_API_KEY'),
],
],
Use in code:
Comment::setDriver('disqus')->create([...]);
Hybrid Approach (Database + Disqus)
disqus_thread_id) in the database.Threaded Replies
$reply = Comment::create([
'parent_id' => $comment->id,
'body' => 'Thanks for your input!',
]);
Validation Rules
Extend the Comment model or use form requests:
use DvTrung\CommentBundle\Rules\CommentRules;
$request->validate([
'body' => ['required', new CommentRules],
]);
API Endpoints
Route::post('/posts/{post}/comments', function (Request $request, Post $post) {
return Comment::create([
'commentable_id' => $post->id,
'commentable_type' => Post::class,
'body' => $request->body,
]);
});
Event Listeners Listen for comment creation/deletion:
Comment::created(function ($comment) {
// Send notification, log, etc.
});
MorphTo for polymorphic relationships if not already set up.$comments = Cache::remember("comments.{$post->id}", now()->addHours(1), function () use ($post) {
return $post->comments()->latest()->get();
});
database driver:
use Illuminate\Database\Eloquent\SoftDeletes;
class Comment extends Model
{
use SoftDeletes;
}
Driver Mismatches
commentable_type matches the fully qualified class name (e.g., App\Models\Post).get_morph_class() helper or cast types in config:
'drivers' => [
'database' => [
'morph_map' => [
'post' => Post::class,
],
],
],
Disqus Webhooks
use DvTrung\CommentBundle\Services\DisqusWebhook;
$validator = new DisquusWebhook($request->all());
if (!$validator->isValid()) {
abort(403);
}
Polymorphic Conflicts
Comment vs. PostComment).commentable_type prefix (e.g., app.Post).Migration Issues
commentable_id and commentable_type columns exist:
Schema::table('comments', function (Blueprint $table) {
$table->morphs('commentable');
});
Driver-Specific Errors
config/comment.php for typos in driver names or missing keys.Logging
Enable debug mode in config/comment.php:
'debug' => env('APP_DEBUG', false),
Check logs for driver initialization errors.
Common SQL Errors
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'commentable_type'
Fix: Run migrations or check table structure.Custom Drivers
Create a new driver by extending DvTrung\CommentBundle\Contracts\DriverInterface:
namespace App\Drivers;
use DvTrung\CommentBundle\Contracts\DriverInterface;
class SlackDriver implements DriverInterface
{
public function create(array $data) { ... }
public function find($id) { ... }
}
Register in config/comment.php:
'drivers' => [
'slack' => [
'webhook_url' => env('SLACK_WEBHOOK_URL'),
],
],
Model Events Override model events in a service provider:
Comment::created(function ($comment) {
// Custom logic (e.g., send email)
});
Blade Directives
Extend the @commentable directive in a service provider:
Blade::directive('commentable', function ($expr) {
return "<?php echo \$__env->make('comment::partials.thread', ['commentable' => {$expr}])->render(); ?>";
});
$posts = Post::with(['comments' => function ($query) {
$query->latest()->limit(10);
}])->get();
cursor() for infinite scroll:
$comments = $post->comments()->latest()->cursor()->paginate(10);
commentable_type and user_id for large datasets.How can I help you explore Laravel packages today?