jeffersongoncalves / laravel-knowledge-base
A Laravel package for building knowledge bases with articles, categories, versioning, and feedback
Package info
github.com/jeffersongoncalves/laravel-knowledge-base
pkg:composer/jeffersongoncalves/laravel-knowledge-base
Requires
- php: ^8.2
- illuminate/contracts: ^11.0|^12.0|^13.0
- illuminate/database: ^11.0|^12.0|^13.0
- illuminate/events: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- spatie/laravel-package-tools: ^1.15
Requires (Dev)
- larastan/larastan: ^2.9|^3.0
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-06 00:29:44 UTC
README
Laravel Knowledge Base
A Laravel package for building knowledge bases with articles, categories, versioning, feedback, and search.
Features
- Article Management — Create, update, publish, archive, and soft-delete articles with UUID and slug routing
- Hierarchical Categories — Nested parent/child categories with ordering and activation control
- Article Versioning — Automatic version history tracking with editor attribution and change notes
- User Feedback — Helpful/not helpful voting with optional comments, supports authenticated and anonymous users
- Related Articles — Many-to-many article relationships with sort ordering
- Full-Text Search — Database-powered search across published articles by title and content
- SEO Fields — Built-in SEO title, description, and keywords per article
- Customizable Models — Override any model via config while maintaining contract compliance
- Table Prefix — Configurable table prefix to avoid naming collisions (default:
kb_) - Translations — English and Brazilian Portuguese out of the box
Requirements
- PHP 8.2+
- Laravel 11+
Installation
composer require jeffersongoncalves/laravel-knowledge-base
Publish and run migrations:
php artisan vendor:publish --tag="knowledge-base-migrations"
php artisan migrate
Publish the config (optional):
php artisan vendor:publish --tag="knowledge-base-config"
Configuration
The config file (config/knowledge-base.php) covers:
Table Prefix
'table_prefix' => 'kb_',
Set to null to use table names without a prefix.
Custom Models
Override any model to extend the default behavior. Custom models must implement the corresponding contract:
'models' => [ 'article' => \App\Models\Article::class, 'category' => \App\Models\Category::class, 'article_version' => \App\Models\ArticleVersion::class, 'article_feedback' => \App\Models\ArticleFeedback::class, 'article_relation' => \App\Models\ArticleRelation::class, ],
Knowledge Base Settings
'default_visibility' => 'public', // default visibility for new articles 'versioning_enabled' => true, // track article version history 'feedback_enabled' => true, // allow user feedback 'track_views' => true, // track article view counts
Search
'search_engine' => 'database', // search engine type 'search_results_limit' => 20, // max results per search
Usage
Using the Service
The KnowledgeBaseService is the recommended way to interact with the knowledge base:
use JeffersonGoncalves\KnowledgeBase\Services\KnowledgeBaseService; $service = app(KnowledgeBaseService::class);
Creating Categories
// Auto-generates slug from name $category = $service->createCategory([ 'name' => 'Getting Started', ]); // With custom slug and parent $child = $service->createCategory([ 'name' => 'Installation', 'slug' => 'installation-guide', 'parent_id' => $category->id, 'description' => 'How to install the application', 'icon' => 'heroicon-o-wrench', 'sort_order' => 1, ]); // Update $service->updateCategory($category, ['name' => 'Quick Start']); // Delete (soft delete) $service->deleteCategory($category);
Creating Articles
$article = $service->createArticle([ 'category_id' => $category->id, 'title' => 'How to Install', 'slug' => 'how-to-install', 'content' => 'Step 1: Run composer require...', 'excerpt' => 'Quick installation guide.', 'visibility' => 'public', 'seo_title' => 'Installation Guide - My App', 'seo_description' => 'Learn how to install My App step by step.', 'seo_keywords' => 'install, setup, getting started', 'metadata' => ['difficulty' => 'beginner'], ], $author); // $author is any Eloquent Model (User, Admin, etc.)
This automatically:
- Generates a UUID
- Creates version 1 (when versioning enabled)
- Dispatches
ArticleCreatedevent
Updating Articles
$updated = $service->updateArticle($article, [ 'title' => 'How to Install (Updated)', 'content' => 'Updated installation steps...', ], $editor, 'Fixed outdated instructions');
When versioning is enabled, this creates a new version entry with the editor and change notes.
Publishing & Archiving
// Publish — sets status to Published, sets published_at, dispatches ArticlePublished $service->publishArticle($article); // Archive — sets status to Archived $service->archiveArticle($article); // Delete — soft deletes $service->deleteArticle($article);
Feedback
// Authenticated helpful feedback $service->addFeedback($article, true, $user, 'Very clear, thank you!', '127.0.0.1'); // Anonymous not-helpful feedback $service->addFeedback($article, false, null, 'Needs more examples'); // Anonymous without comment $service->addFeedback($article, true);
Feedback automatically increments helpful_count or not_helpful_count on the article and dispatches ArticleFeedbackReceived.
Search
// Basic search (only published articles) $results = $service->search('installation'); // With filters $results = $service->search('installation', [ 'category_id' => 1, 'visibility' => 'public', 'limit' => 10, ]);
Results are ordered by view_count descending (most popular first).
Using Models Directly
For queries outside the service, use ModelResolver:
use JeffersonGoncalves\KnowledgeBase\Support\ModelResolver; $articleClass = ModelResolver::article(); $categoryClass = ModelResolver::category(); // Article scopes $published = $articleClass::published()->get(); $drafts = $articleClass::draft()->get(); $archived = $articleClass::archived()->get(); $internal = $articleClass::byVisibility(ArticleVisibility::Internal)->get(); // Category scopes $active = $categoryClass::active()->get(); $roots = $categoryClass::root()->get(); $ordered = $categoryClass::ordered()->get(); $tree = $categoryClass::active()->root()->ordered()->get(); // Relationships $article->category; $article->author; $article->versions; $article->feedback; $article->relatedArticles; $category->parent; $category->children; $category->articles; // View tracking $article->incrementViewCount();
Extending Models
Create custom models that implement the required contract:
namespace App\Models; use JeffersonGoncalves\KnowledgeBase\Models\Article as BaseArticle; use JeffersonGoncalves\KnowledgeBase\Models\Contracts\ArticleContract; class Article extends BaseArticle implements ArticleContract { // Add custom relationships, scopes, methods... public function comments() { return $this->hasMany(Comment::class); } }
Then update the config:
// config/knowledge-base.php 'models' => [ 'article' => \App\Models\Article::class, // ... ],
Events
| Event | Payload | When |
|---|---|---|
ArticleCreated |
$article |
After article creation via service |
ArticlePublished |
$article |
After publishing via service |
ArticleFeedbackReceived |
$article, $feedback |
After feedback submission |
Listen to events in your EventServiceProvider or with listeners:
use JeffersonGoncalves\KnowledgeBase\Events\ArticlePublished; class SendArticleNotification { public function handle(ArticlePublished $event): void { // Notify subscribers about the new article $article = $event->article; } }
Enums
ArticleStatus
| Value | Label (en) | Label (pt_BR) |
|---|---|---|
draft |
Draft | Rascunho |
published |
Published | Publicado |
archived |
Archived | Arquivado |
ArticleVisibility
| Value | Label (en) | Label (pt_BR) |
|---|---|---|
public |
Public | Público |
internal |
Internal | Interno |
use JeffersonGoncalves\KnowledgeBase\Enums\ArticleStatus; use JeffersonGoncalves\KnowledgeBase\Enums\ArticleVisibility; $status = ArticleStatus::Published; $status->label(); // 'Published' or 'Publicado' $visibility = ArticleVisibility::Internal; $visibility->label(); // 'Internal' or 'Interno'
Database Tables
All tables use the configured prefix (default: kb_):
| Table | Description |
|---|---|
kb_categories |
Hierarchical article categories |
kb_articles |
Knowledge base articles |
kb_article_versions |
Article version history |
kb_article_feedback |
User feedback on articles |
kb_article_relations |
Related articles (pivot) |
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
