Skip to content

Fluent Community Database Schema ​

Fluent Community uses custom database tables to store all community data. Here are the list of database tables and their schema to understand overall database design and related data attributes of each model.

Core Entity Relationships ​

🔍 Interactive ER Diagram

Click on the diagram below to zoom in for better readability. The diagram shows the relationships between all Fluent Community database tables.

Fluent Community Database Schema

Schema Overview ​

The Fluent Community database schema is built around these core concepts:

Feeds & Content: Community posts with rich media support and nested discussions Comments & Discussions: Threaded comment system with reactions and moderation Spaces & Groups: Content organization with membership management and permissions Users & Profiles: Extended user profiles with points, badges, and verification Reactions & Engagement: Social interactions (likes, bookmarks, custom reactions) on posts and comments Notifications: Real-time user notification system with multiple delivery channels Media Management: File uploads with multiple storage drivers (local, S3, R2, BunnyCDN) Activity Tracking: Comprehensive audit trail for all user actions and events Topics & Tags: Content categorization and discovery system Follow System (Pro): User-to-user following relationships and personalized feeds Moderation (Pro): Content moderation and reporting system Metadata System: Flexible key-value storage for all entities

Key Design Principles ​

Flexible Architecture: JSON columns used for extensible configuration data Performance Optimization: Strategic indexing on frequently queried columns Referential Integrity: Proper foreign key relationships maintained throughout Audit Trail: Comprehensive activity logging for all important operations WordPress Integration: Seamless integration with WordPress core tables (wp_users, wp_usermeta)

Database Tables ​

fcom_posts Table ​

This table stores posts and other content types in the community.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NULLID of the user who created the post
parent_idBIGINT UNSIGNED NULLID of the parent post (for nested content)
titleVARCHAR(192) NULLTitle of the post
slugVARCHAR(192) NULLURL-friendly version of the title
messageLONGTEXT NULLThe post content
message_renderedLONGTEXT NULLRendered version of the post content
typeVARCHAR(100) DEFAULT 'feed'Type of the post (feed, article)
content_typeVARCHAR(100) DEFAULT 'text'Type of content (text, image, video)
space_idBIGINT UNSIGNED NULLID of the space the post belongs to
privacyVARCHAR(100) DEFAULT 'public'Privacy setting (public, private, secret)
statusVARCHAR(100) DEFAULT 'published'Status (published, draft, pending)
featured_imageTEXT NULLURL or ID of the featured image
metaLONGTEXT NULLAdditional metadata in JSON format
is_stickyTINYINT(1) DEFAULT 0Whether the post is sticky
comments_countINT(11) DEFAULT 0Number of comments on the post
reactions_countINT(11) DEFAULT 0Number of reactions to the post
priorityINT(11) DEFAULT 0Priority for sorting
expired_atDATETIME NULLTimestamp when the post expires
scheduled_atDATETIME NULLTimestamp when the post is scheduled
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • user_id
  • slug
  • created_at
  • idx_space_id_status
  • idx_space_id_status_privacy

fcom_post_comments Table ​

This table stores comments and reactions for posts in the community.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NULLID of the user who made the comment
post_idBIGINT UNSIGNED NULLID of the post the comment belongs to
parent_idBIGINT UNSIGNED NULLID of the parent comment (for nested comments)
reactions_countBIGINT UNSIGNED DEFAULT 0Number of reactions to this comment
messageLONGTEXT NULLThe comment text
message_renderedLONGTEXT NULLRendered version of the comment
metaLONGTEXT NULLAdditional metadata in JSON format
typeVARCHAR(100) DEFAULT 'comment'Type (comment, moderation)
content_typeVARCHAR(100) DEFAULT 'text'Type of content (text, image)
statusVARCHAR(100) DEFAULT 'published'Status (published, draft, pending)
is_stickyTINYINT(1) DEFAULT 0Whether the comment is sticky
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • post_id
  • status
  • type

fcom_post_reactions Table ​

This table stores reactions to posts and comments in the community using a polymorphic relationship.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NULLID of the user who reacted
object_idBIGINT UNSIGNED NULLID of the object (post or comment)
parent_idBIGINT UNSIGNED NULLID of the parent object
object_typeVARCHAR(100) DEFAULT 'feed'Type of object (feed, comment)
typeVARCHAR(100) DEFAULT 'like'Type of reaction (like, love, bookmark)
ip_addressVARCHAR(100) NULLIP address of the user
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • object_user_object_type_type (object_id, user_id, object_type, type)
  • object_type_parent_id_user_id (object_type, parent_id, user_id)

fcom_spaces Table ​

This table stores information about spaces (communities or groups) within the platform.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
created_byBIGINT UNSIGNED NULLID of the user who created the space
parent_idBIGINT UNSIGNED NULLID of the parent space (for nested spaces)
titleVARCHAR(194) NOT NULLTitle of the space
slugVARCHAR(194) NOT NULLURL-friendly version of the space title
logoTEXT NULLURL or path to the space logo
cover_photoTEXT NULLURL or path to the cover photo
descriptionLONGTEXT NULLFull description of the space
typeVARCHAR(100) NULLType of space (space, space_group, sidebar_link)
privacyVARCHAR(100) DEFAULT 'public'Privacy setting (public, private, secret)
statusVARCHAR(100) DEFAULT 'published'Status (published, draft, archived)
serialINT(11) DEFAULT 1Display order/priority
settingsLONGTEXT NULLJSON settings for the space
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • title
  • status

fcom_space_user Table ​

This table manages the relationships between users and spaces, tracking membership and roles within each space.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
space_idBIGINT UNSIGNED NULLID of the space
user_idVARCHAR(194) NOT NULLID of the user
statusVARCHAR(100) DEFAULT 'active'Status (active, pending, blocked, suspended)
roleVARCHAR(100) DEFAULT 'member'User's role (member, admin, moderator)
metaTEXT NULLAdditional metadata in JSON format
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • status
  • space_id_user_id (space_id, user_id)
  • role

fcom_media_archive Table ​

This table manages media files associated with various objects in the community platform.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
object_sourceVARCHAR(100) NOT NULLSource of the object (post, comment, profile)
media_keyVARCHAR(100) NOT NULLUnique key for the media file
user_idBIGINT NULLID of the user who uploaded the media
feed_idBIGINT NULLID of the associated feed/post
is_activeTINYINT(1) DEFAULT 0Whether the media is active
sub_object_idBIGINT NULLID of a sub-object (comment ID)
media_typeVARCHAR(192) NULLType of media (image, video, document)
driverVARCHAR(192) DEFAULT 'local'Storage driver (local, s3, r2, bunnycdn)
media_pathTEXT NULLPath or identifier of the media file
media_urlTEXT NULLURL to access the media file
settingsTEXT NULLAdditional settings in JSON format
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • is_active
  • user_id
  • media_key
  • feed_id

fcom_meta Table ​

This table stores metadata for various objects in the community platform using a flexible key-value system.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
object_typeVARCHAR(50) NOT NULLType of object (space, user, post, feed)
object_idBIGINT NULLID of the associated object
meta_keyVARCHAR(100) NOT NULLKey for the metadata
valueLONGTEXT NULLValue of the metadata
created_atTIMESTAMP DEFAULT CURRENT_TIMESTAMP
updated_atTIMESTAMP NULL

Indexes:

  • object_type
  • object_id
  • meta_key

fcom_notifications Table ​

This table stores notification templates and definitions for the community platform.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
feed_idBIGINT UNSIGNED NULLID of the associated feed/post
object_idBIGINT UNSIGNED NULLID of the associated object
src_user_idBIGINT UNSIGNED NULLID of the user who triggered the notification
src_object_typeVARCHAR(100) NULLType of source object
actionVARCHAR(100) NULLAction that triggered the notification
titleVARCHAR(192) NULLTitle of the notification
contentTEXT NULLContent of the notification
routeTEXT NULLRoute/URL for the notification
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • feed_id
  • object_id
  • action

fcom_user_activities Table ​

This table tracks user activities within the community platform for audit and activity feed purposes.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NULLID of the user performing the activity
feed_idBIGINT UNSIGNED NULLID of the associated feed/post
space_idBIGINT UNSIGNED NULLID of the associated space
related_idBIGINT UNSIGNED NULLID of related object (comment, reaction)
messageTEXT NULLActivity message or description
is_publicTINYINT(1) DEFAULT 1Whether the activity is public
action_nameVARCHAR(100) DEFAULT ''Name of the action (post_created, comment_added)
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • feed_id
  • user_id
  • action_name

fcom_xprofile Table ​

This table stores extended profile information for users in the community platform.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NOT NULL UNIQUEID of the user associated with this profile
total_pointsINT(11) UNSIGNED NOT NULL DEFAULT 0Total points earned by the user
usernameVARCHAR(100) NULLUser's chosen username
statusENUM NOT NULL DEFAULT 'active'User status (active, blocked, pending)
is_verifiedTINYINT(1) UNSIGNED NOT NULL DEFAULT 0Whether the user is verified
display_nameVARCHAR(192) NULLUser's display name
avatarTEXT NULLURL or path to user's avatar image
short_descriptionTEXT NULLBrief description or bio of the user
last_activityDATETIME NULLTimestamp of user's last activity
metaLONGTEXT NULLAdditional metadata in JSON format
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • user_id
  • username

fcom_notification_users Table ​

This table stores individual user notifications and their read status.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
object_typeVARCHAR(50) DEFAULT 'notification'Type of object (notification, subscription)
notification_typeVARCHAR(50) DEFAULT 'web'Type of notification (web, email, push)
object_idBIGINT UNSIGNED NULLID of the notification from fcom_notifications
user_idBIGINT UNSIGNED NULLID of the user receiving the notification
is_readTINYINT(1) UNSIGNED DEFAULT 0Whether the notification has been read
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • user_id_is_read_object_type (user_id, is_read, object_type)
  • object_id_is_read_object_type_notification_type (object_id, is_read, object_type, notification_type)

fcom_terms Table ​

This table stores taxonomy terms (topics, tags, categories) for content organization.

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
parent_idBIGINT UNSIGNED NULLID of the parent term (for hierarchical taxonomies)
taxonomy_nameVARCHAR(50) NOT NULLName of the taxonomy (topic, tag, category)
slugVARCHAR(100) NOT NULLURL-friendly identifier
titleLONGTEXT NULLTerm title/name
descriptionLONGTEXT NULLTerm description
settingsLONGTEXT NULLAdditional settings in JSON format
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • taxonomy_name
  • slug

fcom_term_feed Table ​

This table links posts to terms (topics, tags, categories).

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
term_idBIGINT UNSIGNED NULLID of the term
post_idBIGINT UNSIGNED NULLID of the post
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • term_id
  • post_id

Pro Plugin Tables ​

fcom_follows Table (Pro Plugin) ​

This table stores user following relationships (Pro feature).

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NOT NULLID of the user who is following
following_idBIGINT UNSIGNED NOT NULLID of the user being followed
statusVARCHAR(50) DEFAULT 'active'Status (active, inactive)
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • user_id
  • following_id
  • user_id_following_id (user_id, following_id)

fcom_moderation Table (Pro Plugin) ​

This table stores content moderation and reporting data (Pro feature).

ColumnTypeComment
idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NULLID of the user who reported
post_idBIGINT UNSIGNED NULLID of the reported post
parent_idBIGINT UNSIGNED NULLID of the parent object
reactions_countBIGINT UNSIGNED DEFAULT 0Number of reactions
messageLONGTEXT NULLModeration message
message_renderedLONGTEXT NULLRendered version of the message
metaLONGTEXT NULLAdditional metadata in JSON format
typeVARCHAR(100) DEFAULT 'comment'Type (comment, report)
content_typeVARCHAR(100) DEFAULT 'text'Type of content
statusVARCHAR(100) DEFAULT 'published'Status (published, pending, rejected)
is_stickyTINYINT(1) DEFAULT 0Whether the entry is sticky
created_atTIMESTAMP NULL
updated_atTIMESTAMP NULL

Indexes:

  • post_id
  • status
  • type

WordPress Integration ​

Fluent Community seamlessly integrates with WordPress core tables for user management and authentication:

users Table ​

WordPress core user table - used for authentication and basic user information.

ColumnTypeComment
IDBIGINT UNSIGNED Auto IncrementPrimary key
user_loginVARCHAR(60) NOT NULLUsername for authentication
user_passVARCHAR(255) NOT NULLHashed password
user_nicenameVARCHAR(50) NOT NULLURL-friendly username
user_emailVARCHAR(100) NOT NULLUser email address
user_urlVARCHAR(100) NOT NULLUser website URL
user_registeredDATETIME NOT NULLRegistration timestamp
user_activation_keyVARCHAR(255) NOT NULLActivation key
user_statusINT(11) NOT NULL DEFAULT 0User status
display_nameVARCHAR(250) NOT NULLUser's display name

Integration: Fluent Community extends WordPress users with the fcom_xprofile table for community-specific data.

usermeta Table ​

WordPress core user metadata table - stores additional user information.

ColumnTypeComment
umeta_idBIGINT UNSIGNED Auto IncrementPrimary key
user_idBIGINT UNSIGNED NOT NULL DEFAULT 0Reference to users table
meta_keyVARCHAR(255) NULLMeta key
meta_valueLONGTEXT NULLMeta value

Key Meta Keys Used:

  • first_name - User's first name
  • last_name - User's last name
  • description - User biography
  • wp_capabilities - User roles and capabilities

Integration: Fluent Community may store additional metadata here for WordPress compatibility.


Entity Relationships

One-to-Many Relationships

  • User → Posts: One user can create many posts

    php
    $user->posts()->get();
  • User → Comments: One user can create many comments

    php
    $user->comments()->get();
  • Space → Posts: One space can contain many posts

    php
    $space->posts()->get();
  • Post → Comments: One post can have many comments

    php
    $post->comments()->get();
  • User → Notifications: One user can receive many notifications

    php
    $user->notifications()->get();

Many-to-Many Relationships

  • Users ↔ Spaces: Users can join multiple spaces, spaces can have multiple members

    php
    $user->spaces()->get();
    $space->members()->get();
  • Posts ↔ Topics (Pro): Posts can have multiple topics, topics can be on multiple posts

    php
    $post->topics()->get();
    $topic->posts()->get();
  • Users ↔ Users (Pro): Users can follow other users

    php
    $user->following()->get();
    $user->followers()->get();

Polymorphic Relationships

  • Reactions: Can be attached to posts or comments

    php
    $post->reactions()->get();
    $comment->reactions()->get();
  • Meta: Can be attached to any entity type

    php
    Meta::where('object_type', 'post')->where('object_id', $postId)->get();
  • Media: Can be attached to various content types

    php
    $post->media()->get();

Common Data Types

Fluent Community uses consistent data types across all tables:

Data TypeUsageExample
BIGINT UNSIGNEDPrimary keys, foreign keys, large integersid, user_id, post_id
INT(11)Counters, small integerscomments_count, priority
VARCHAR(192)Short text fields, titles, namestitle, slug, name
VARCHAR(100)Type fields, status fieldstype, status, privacy
TEXTMedium text contentdescription, content
LONGTEXTLarge text content, JSON datamessage, meta, settings
TIMESTAMPTimestamps with automatic updatescreated_at, updated_at
DATETIMESpecific date/time valuesscheduled_at, expired_at
TINYINT(1)Boolean flagsis_sticky, is_active
ENUMFixed value setsstatus (active, blocked)

Indexing Strategy

All Fluent Community tables include strategic indexes for optimal performance:

Primary Keys

  • All tables have an auto-incrementing id column as the primary key
  • Ensures unique identification of each record

Foreign Key Indexes

  • user_id - Indexed on all tables with user relationships
  • post_id - Indexed for comment and reaction lookups
  • space_id - Indexed for space-related queries
  • object_id - Indexed for polymorphic relationships

Composite Indexes

  • idx_space_id_status - Fast filtering of posts by space and status
  • idx_space_id_status_privacy - Fast filtering with privacy settings
  • Multiple column indexes for common query patterns

Unique Indexes

  • slug - Ensures unique URLs for posts, spaces, and topics
  • user_id (in xprofile) - One profile per user
  • code (in coupons, if applicable) - Unique coupon codes

Performance Indexes

  • created_at - For chronological sorting
  • status - For filtering by publication status
  • type - For filtering by content type
  • is_read - For filtering read/unread notifications

Working with the Database

Fluent Community provides Eloquent-style models for all database tables:

php
use FluentCommunity\App\Models\Feed;
use FluentCommunity\App\Models\Comment;
use FluentCommunity\App\Models\Space;

// Fetch published posts
$posts = Feed::where('status', 'published')
    ->orderBy('created_at', 'desc')
    ->limit(10)
    ->get();

// Get post with comments
$post = Feed::with('comments')->find($postId);

// Create a new post
$post = Feed::create([
    'user_id' => get_current_user_id(),
    'space_id' => $spaceId,
    'title' => 'My Post Title',
    'message' => 'Post content here',
    'status' => 'published',
    'type' => 'feed'
]);

Direct Database Queries

For advanced use cases, you can use WordPress's $wpdb object:

php
global $wpdb;

// Get table name with prefix
$table = $wpdb->prefix . 'fcom_posts';

// Execute query
$posts = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT * FROM $table WHERE status = %s AND space_id = %d",
        'published',
        $spaceId
    )
);

Important: Always use prepared statements to prevent SQL injection.


Database Migrations

Fluent Community handles database schema creation and updates automatically. The migration files are located in:

/databases/Migrators/

Migration Files

  • PostsMigrator.php - Creates wp_fcom_posts table
  • CommentsMigrator.php - Creates wp_fcom_post_comments table
  • SpacesMigrator.php - Creates wp_fcom_spaces table
  • XProfileMigrator.php - Creates wp_fcom_xprofile table
  • And more...

Running Migrations

Migrations run automatically on plugin activation and updates. To manually trigger migrations:

php
do_action('fluent_community/run_migrations');

Best Practices

1. Use Models Instead of Direct Queries

Good:

php
$posts = Feed::where('status', 'published')->get();

Avoid:

php
global $wpdb;
$posts = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}fcom_posts WHERE status = 'published'");

2. Use Relationships

Good:

php
$post = Feed::with(['comments', 'author', 'space'])->find($id);

Avoid:

php
$post = Feed::find($id);
$comments = Comment::where('post_id', $id)->get();
$author = User::find($post->user_id);

3. Use Query Builder Methods

Good:

php
Feed::where('space_id', $spaceId)
    ->where('status', 'published')
    ->orderBy('created_at', 'desc')
    ->paginate(20);

4. Leverage Indexes

Good: Query on indexed columns

php
Feed::where('status', 'published')->where('space_id', $spaceId)->get();

Avoid: Querying on non-indexed columns for large datasets

php
Feed::where('message', 'LIKE', '%keyword%')->get(); // Slow on large tables

5. Use Transactions for Multiple Operations

php
DB::beginTransaction();
try {
    $post = Feed::create($postData);
    $post->topics()->attach($topicIds);
    $post->meta()->create($metaData);

    DB::commit();
} catch (\Exception $e) {
    DB::rollback();
    // Handle error
}

Next Steps


Additional Resources

Schema Visualization

For a visual representation of the database schema, you can use tools like:

  • phpMyAdmin
  • MySQL Workbench
  • TablePlus
  • Adminer

Database Documentation

The complete schema definitions are available in the plugin's migration files:

/wp-content/plugins/fluent-community/databases/Migrators/

Support

For questions about the database schema:

Fluent Community developer documentation