Update your database with forum migrations
8.xAfter publishing the migrations, run the standard Laravel migration command to create the necessary forum tables in your database.
php artisan migraterepository·8.x·Indexed 20 days ago
https://github.com/team-tea-time/laravel-forumA complete forum solution for Laravel applications providing database schemas, configuration options, and pre-built UI presets, including Livewire-based options. It includes a set of Artisan commands for preset installation (forum:preset-install), listing (forum:preset-list), seeding (forum:seed), and statistics synchronization (forum:sync), as well as API resources for Categories, Posts, and Threads.
After publishing the migrations, run the standard Laravel migration command to create the necessary forum tables in your database.
php artisan migratePublish the package's assets (config, translations, and migrations) to your application directories by running the vendor:publish command.
php artisan vendor:publishInstall the package using Composer. Laravel's package discovery should automatically register the TeamTeaTime\Forum\ForumServiceProvider. If manual registration is required, add the provider to bootstrap/providers.php.
composer require riari/laravel-forum:^8.0// bootstrap/providers.php
TeamTeaTime\Forum\ForumServiceProvider::class,To render the forum UI, you must install a UI preset. Use php artisan forum:preset-list to view available options. Once you have chosen a preset, install it using the forum:preset-install {name} command.
Note: The livewire-tailwind preset is the default active preset in the forum.frontend.preset configuration, but it requires Livewire and other dependencies.
# List available presets
php artisan forum:preset-list
# Install a specific preset (e.g., livewire-tailwind)
php artisan forum:preset-install livewire-tailwindforum.integration.user_name key.The project provides a docker-compose.yml file to orchestrate a development and testing environment. It includes services for a MySQL database, Composer, and PHPUnit.
Note that the mysql service uses a tmpfs mount at /var/lib/mysql, meaning data is stored in memory and will be lost when the container stops. This is optimized for fast testing cycles.
docker-compose upYou can populate the forum tables with sample categories, threads, posts, and a user using the forum:seed command.
docker-compose exec php-fpm php artisan forum:seedEnsure your environment meets the requirements for the package version you are using:
| Laravel version | Livewire version* | Package version | PHP version |
|---|---|---|---|
| 13 | 4 | ^8.0 | ^8.3 |
| 12 | 3 | ^7.0 | ^8.2 |
When consuming the API, a post object is represented via PostResource. The JSON response includes core post attributes and a set of available actions for performing operations on the post.
Attributes:
id: The unique identifier of the post.thread_id: The ID of the thread this post belongs to.author_id: The ID of the post author.author_name: The name of the post author.content: The body content of the post.post_id: The ID of the parent post (if this is a reply).sequence: The position of the post in the thread.created_at, updated_at, deleted_at: Timestamps.Actions:
The actions object contains generated URLs for specific operations:
patch:update: URL to update the post.delete:delete: URL to delete the post.post:restore: URL to restore a deleted post.Links:
Metadata links are provided in a links object:
self: URL to fetch the specific post.thread: URL to fetch the parent thread.parent: (Conditional) If post_id is present, the URL to fetch the parent post.{
"id": 1,
"thread_id": 10,
"author_id": 5,
"author_name": "John Doe",
"content": "Hello World",
"post_id": null,
"sequence": 1,
"created_at": "2026-07-14T00:00:00.000000Z",
"updated_at": "2026-07-14T00:00:00.000000Z",
"deleted_at": null,
"actions": {
"patch:update": "/api/posts/1",
"delete:delete": "/api/posts/1",
"post:restore": "/api/posts/1"
},
"links": {
"self": "/api/posts/1",
"thread": "/api/threads/10"
}
}When consuming the forum's API, category objects are represented using the CategoryResource. The JSON response includes metadata about the category, its hierarchy, and available API actions.
Key fields include:
id: Unique identifier.title: Category name.description: Category description.accepts_threads: Boolean indicating if threads can be created here.is_private: Boolean indicating if the category is private.thread_count & post_count: Statistics for the category.left & right: Nested set model values (_lft and _rgt) used for hierarchical positioning.actions: An object containing API routes for performing operations on the category.links: HATEOAS-style links for navigating to the category or its related threads.{
"id": 1,
"title": "General",
"description": "Discussion for everyone",
"accepts_threads": true,
"newest_thread_id": 10,
"latest_active_thread_id": 12,
"thread_count": 5,
"post_count": 25,
"is_private": false,
"left": 1,
"right": 10,
"parent_id": null,
"color_light_mode": "#ffffff",
"color_dark_mode": "#000000",
"created_at": "2023-01-01T00:00:00.000000Z",
"updated_at": "2023-01-01T00:00:00.000000Z",
"actions": {
"patch:update": "/api/category/1/update",
"delete:delete": "/api/category/1/delete"
},
"links": {
"self": "/api/category/1/fetch",
"newest_thread": "/api/thread/10/fetch",
"latest_active_thread": "/api/thread/12/fetch"
}
}When consuming the forum API, a ThreadResource represents a discussion thread. The JSON response includes core thread attributes, boolean flags for status, and a set of available administrative actions.
id: Unique identifier for the thread.category_id: ID of the category the thread belongs to.author_id: ID of the user who created the thread.author_name: Name of the thread author.title: The thread title.pinned: Boolean (true if the thread is pinned).locked: Boolean (true if the thread is locked).first_post_id: ID of the initial post in the thread.last_post_id: ID of the most recent post in the thread.reply_count: Total number of replies.created_at, updated_at, deleted_at: Timestamps.The actions object contains URLs for performing administrative tasks on the thread via POST requests:
post:lock: Lock the thread.post:unlock: Unlock the thread.post:pin: Pin the thread.post:unpin: Unpin the thread.post:rename: Rename the thread.post:move: Move the thread.delete:delete: Delete the thread.post:restore: Restore a deleted thread.The links object provides related resource endpoints:
self: The endpoint to fetch the thread details.category: The endpoint to fetch the associated category.posts: The endpoint to fetch all posts within this thread.first_post_id: The endpoint to fetch the first post.last_post_id: The endpoint to fetch the last post.{
"id": 1,
"category_id": 5,
"author_id": 10,
"author_name": "John Doe",
"title": "How to use Laravel Forum",
"pinned": true,
"locked": false,
"first_post_id": 100,
"last_post_id": 150,
"reply_count": 5,
"created_at": "2026-07-14T10:00:00.000000Z",
"updated_at": "2026-07-14T11:00:00.000000Z",
"deleted_at": null,
"actions": {
"post:lock": "/api/thread/1/lock",
"post:unlock": "/api/thread/1/unlock",
"post:pin": "/api/thread/1/pin",
"post:unpin": "/api/thread/1/unpin",
"post:rename": "/api/thread/1/rename",
"post:move": "/api/thread/1/move",
"delete:delete": "/api/thread/1/delete",
"post:restore": "/api/thread/1/restore"
},
"links": {
"self": "/api/thread/1",
"category": "/api/category/5",
"posts": "/api/thread/1/posts",
"first_post_id": "/api/post/100",
"last_post_id": "/api/post/150"
}
}The following services are defined in the docker-compose.yml file for local development and testing:
mysql: A MySQL database container built from docker/mysql/Dockerfile. Uses tmpfs for /var/lib/mysql to ensure high-speed testing.composer: A container for running Composer commands. It maps the current directory to /app and sets the entrypoint to /usr/bin/composer.phpunit: A container for running tests. It maps the current directory to /app and sets the entrypoint to vendor/bin/phpunit.services:
mysql:
container_name: lf-tests-mysql
build:
context: .
dockerfile: docker/mysql/Dockerfile
tmpfs: /var/lib/mysql
composer:
build:
context: .
dockerfile: docker/composer/Dockerfile
environment:
COMPOSER_CACHE_DIR: /app/var/cache/composer
volumes:
- .:/app
working_dir: /app
entrypoint: /usr/bin/composer
phpunit:
build:
context: .
dockerfile: docker/phpunit/Dockerfile
restart: "no"
volumes:
- .:/app
working_dir: /app
entrypoint: vendor/bin/phpunit