Developer Overview
Welcome to the ThemeRuby Multi Authors developer documentation. This guide will help you integrate the plugin into your themes and extend its functionality.
Quick Start for Developers
1. Check if Plugin is Active
Always check if the plugin is active before using its functions:
if ( function_exists( 'tmauthors_get_post_authors' ) ) {
// Plugin is active, use its functions
$authors = tmauthors_get_post_authors( get_the_ID() );
}
2. Display Authors in Your Theme
Basic implementation in single.php or content.php:
<?php
if ( function_exists( 'tmauthors_the_authors' ) ) {
echo '<div class="post-authors">';
echo '<span class="byline">By: </span>';
tmauthors_the_authors();
echo '</div>';
}
?>
3. Query Posts by Author
Use standard WP_Query with author parameters:
$query = new WP_Query( array(
'author__in' => array( 1, 5, 8 ), // Posts by these authors
'posts_per_page' => 10,
) );
Architecture
How It Works
ThemeRuby Multi Authors uses WordPress's built-in taxonomy system to manage author relationships:
Post ID 123
├── Taxonomy: ema_author
│ ├── Term: user-1-john-doe (User ID: 1)
│ ├── Term: user-5-jane-smith (User ID: 5)
│ └── Term: user-8-bob-johnson (User ID: 8)
Benefits of This Approach
✅ No custom tables - Uses WordPress core ✅ Standard queries - Works with WP_Query ✅ Efficient - Leverages WordPress's optimized taxonomy queries ✅ Scalable - Handles thousands of posts and users ✅ Compatible - Works with any plugin/theme
Database Structure
No custom tables! Uses standard WordPress tables:
wp_terms- Stores author termswp_term_taxonomy- Links toema_authortaxonomywp_term_relationships- Links posts to author termswp_termmeta- Stores user ID for each term
Key Concepts
Primary vs Co-Authors
- Primary Author: The
post_authorfield inwp_posts(always exists) - Co-Authors: Additional authors stored as taxonomy terms
The plugin handles both seamlessly - when you call tmauthors_get_post_authors(), it returns all authors (primary + co-authors).
Author Terms
Each WordPress user gets a corresponding taxonomy term:
User: john-doe (ID: 123)
↓
Term: user-123-john-doe
↓
Term Meta: user_id = 123
This mapping is automatic and happens when:
- User is assigned as author for the first time
- User is created/updated
Caching Strategy
The plugin uses multi-level caching:
- Object Cache - WordPress transient/object cache
- Per-Request Cache - Stores results for current page load
- Database Cache - MySQL query cache (server-level)
Cache is automatically cleared when:
- Authors are assigned/removed
- Posts are updated
- Users are modified
API Structure
Template Tags
Public functions for use in themes:
// Get authors
tmauthors_get_post_authors( $post_id )
// Display authors
tmauthors_the_authors( $post_id, $args )
// Check multiple authors
tmauthors_has_multiple_authors( $post_id )
// Set authors
tmauthors_set_post_authors( $post_id, $author_ids )
👉 Complete Template Tags Reference
Hooks & Filters
Customize plugin behavior:
// Modify author list
add_filter( 'tmauthors_post_authors', $callback, 10, 2 );
// Customize author display
add_filter( 'tmauthors_display', $callback, 10, 3 );
// After authors assigned
add_action( 'tmauthors_assigned', $callback, 10, 2 );
👉 Complete Hooks & Filters Reference
WP_Query Integration
Query posts by author:
// Single author
new WP_Query( array( 'author' => 5 ) );
// Multiple authors (OR)
new WP_Query( array( 'author__in' => array( 1, 5, 8 ) ) );
// Exclude authors
new WP_Query( array( 'author__not_in' => array( 3, 6 ) ) );
// By author name
new WP_Query( array( 'author_name' => 'john-doe' ) );
Common Use Cases
1. Display Authors in Theme
// In single.php
if ( function_exists( 'tmauthors_get_post_authors' ) ) {
$authors = tmauthors_get_post_authors( get_the_ID() );
if ( count( $authors ) > 1 ) {
echo '<div class="co-authors">Co-authored by: ';
} else {
echo '<div class="single-author">By: ';
}
foreach ( $authors as $index => $author ) {
if ( $index > 0 ) echo ', ';
echo '<a href="' . get_author_posts_url( $author->ID ) . '">';
echo esc_html( $author->display_name );
echo '</a>';
}
echo '</div>';
}
2. Show Popular Authors Widget
function my_popular_authors_widget() {
global $wpdb;
// Get authors with most posts
$popular_authors = $wpdb->get_results( "
SELECT t.term_id, tm.meta_value as user_id, COUNT(*) as post_count
FROM {$wpdb->term_relationships} tr
JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
JOIN {$wpdb->termmeta} tm ON t.term_id = tm.term_id
WHERE tt.taxonomy = 'ema_author'
AND tm.meta_key = 'user_id'
GROUP BY t.term_id
ORDER BY post_count DESC
LIMIT 10
" );
foreach ( $popular_authors as $popular ) {
$user = get_user_by( 'id', $popular->user_id );
echo '<li>' . $user->display_name . ' (' . $popular->post_count . ' posts)</li>';
}
}
3. Custom Author Archive
// In author.php
$author_id = get_queried_object_id();
// Get all posts by this author (automatic with archive filtering)
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
// Show if this is co-authored
$authors = tmauthors_get_post_authors( get_the_ID() );
if ( count( $authors ) > 1 ) {
echo '<span class="co-authored-badge">Co-authored</span>';
}
}
}
4. REST API Integration
// Add authors to REST API response
add_action( 'rest_api_init', function() {
register_rest_field( 'post', 'authors', array(
'get_callback' => function( $post ) {
$authors = tmauthors_get_post_authors( $post['id'] );
return array_map( function( $author ) {
return array(
'id' => $author->ID,
'name' => $author->display_name,
'url' => get_author_posts_url( $author->ID ),
);
}, $authors );
},
) );
} );
Best Practices
1. Always Check for Plugin
// ✅ Good
if ( function_exists( 'tmauthors_get_post_authors' ) ) {
$authors = tmauthors_get_post_authors();
}
// ❌ Bad - will error if plugin deactivated
$authors = tmauthors_get_post_authors();
2. Use Proper Escaping
// ✅ Good
echo esc_html( $author->display_name );
// ❌ Bad - security risk
echo $author->display_name;
3. Cache Expensive Queries
// ✅ Good
$cache_key = 'my_authors_query_' . $post_id;
$authors = wp_cache_get( $cache_key );
if ( false === $authors ) {
$authors = tmauthors_get_post_authors( $post_id );
wp_cache_set( $cache_key, $authors, 'my_plugin', 3600 );
}
// ❌ Bad - queries database every time
$authors = tmauthors_get_post_authors( $post_id );
4. Provide Fallbacks
// ✅ Good - works even if plugin deactivated
if ( function_exists( 'tmauthors_get_post_authors' ) ) {
$authors = tmauthors_get_post_authors();
} else {
// Fallback to default WordPress author
$author = get_user_by( 'id', get_post_field( 'post_author' ) );
$authors = array( $author );
}
foreach ( $authors as $author ) {
echo $author->display_name;
}
Performance Considerations
Query Optimization
The plugin uses optimized queries:
-- Efficient LEFT JOIN used by plugin
SELECT p.*, GROUP_CONCAT(u.ID) as author_ids
FROM wp_posts p
LEFT JOIN wp_term_relationships tr ON p.ID = tr.object_id
LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'ema_author'
LEFT JOIN wp_termmeta tm ON tt.term_id = tm.term_id AND tm.meta_key = 'user_id'
WHERE p.post_status = 'publish'
GROUP BY p.ID
Caching Recommendations
- Enable Object Cache - Redis/Memcached for best performance
- Enable Plugin Cache - Settings > ThemeRuby Multi Authors
- Use Page Caching - WP Super Cache, W3 Total Cache, etc.
Database Indexes
The plugin uses WordPress's standard indexes. For large sites (10,000+ posts), consider adding:
-- Optional index for better performance on large sites
CREATE INDEX idx_ema_user_id ON wp_termmeta (meta_key, meta_value)
WHERE meta_key = 'user_id';
Code Standards
The plugin follows:
- ✅ WordPress Coding Standards
- ✅ WordPress PHP Documentation Standards
- ✅ WPCS (WordPress Coding Standards)
- ✅ PHP_CodeSniffer compatible
Browser Support
JavaScript supports:
- ✅ Modern browsers (Chrome, Firefox, Safari, Edge)
- ✅ IE11 with polyfills (if needed)
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
Debugging
Enable Debug Mode
// In wp-config.php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'SCRIPT_DEBUG', true );
Plugin Debug Filter
// Enable plugin-specific debugging
add_filter( 'tmauthors_debug', '__return_true' );
Check Queries
// Show SQL queries
define( 'SAVEQUERIES', true );
// In template
global $wpdb;
print_r( $wpdb->queries );
Next Steps
For Theme Developers
- Theme Integration Guide - Complete theme integration
- Template Tags - All available functions
- Display Examples - Styling examples
For Plugin Developers
- Hooks & Filters - Extend functionality
- WP_Query Integration - Query customization
- GitHub Repository - Contribute code
Support
For development questions:
Ready to integrate?