WordPress as a Knowledge Base

WordPress as a Knowledge Base

Tutorial Details
  • Program: WordPress
  • Version: 3+
  • Difficulty: Medium
  • Estimated Completion Time: 1 hour

At work we previously used KBPublisher to manage our knowledge base. It costed money, it was hard to style, code is encrypted with ion cube and so on, basically very hard to maintain. WordPress can do the same things and even better.

This tutorial will show you how to use custom taxonomies for knowledge base sections and custom posts for knowledge base articles.


Step 1 Administration

Knowledge base sections and articles need to be managed. WordPress makes this easy to do with custom taxonomies and custom post types.

Just register the new taxonomy and post type. Add the following into functions.php from your theme.

For more information on the ins and outs of this functionality, read our other custom post type and custom taxonomy articles.

function register_kb() {
	register_post_type( 'knowledgebase',
		array(
			'labels' => array(
				'name' => 'Knowledge Base',
				'menu_name' => 'Knowledge Base',
				'singular_name' => 'Article',
				'all_items' => 'All Articles'
			),
			'public' => true,
			'publicly_queryable' => true,
			'show_ui' => true,
			'show_in_menu' => true,
			'show_in_nav_menus' => true,
			'menu_position ' => 20,
			'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'comments', 'post-formats', 'revisions' ),
			'hierarchical' => false,
			'taxonomies' => array( 'section' ),
			'has_archive' => true,
			'rewrite' => array( 'slug' => 'knowledgebase', 'hierarchical' => true, 'with_front' => false )
		)
	);
	
	register_taxonomy( 'section', array( 'knowledgebase' ),
		array(
			'labels' => array(
				'name' => 'Sections',
				'menu_name' => 'Sections',
				'singular_name' => 'Section',
				'all_items' => 'All Sections'
			),
			'public' => true,
			'hierarchical' => true,
			'show_ui' => true,
			'rewrite' => array( 'slug' => 'knowledgebase-section', 'hierarchical' => true, 'with_front' => false ),
		)
	);
}
add_action( 'init', 'register_kb' );

function kb_rewrite_rules( $wp_rewrite ) {
	$new_rules = array( 'knowledgebase/(.*)/(.*)' => 'index.php?post_type=knowledgebase&section=' . $wp_rewrite->preg_index( 1 ) . '&knowledgebase=' . $wp_rewrite->preg_index( 2 ) );
	$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action( 'generate_rewrite_rules', 'kb_rewrite_rules' );

This will run after WordPress has finished loading but before any headers are sent, registering the post type and taxonomy. Also, it will add the rewrite rules for the permalinks of the taxonomy and post type.

The register_post_type registers the custom post type, this is used for the KB articles. The register_taxonomy registers the custom taxonomy, this is used for the KB sections. The articles won’t be hierarchical but the sections will be, so it gives the possibility to create a tree structure.

Also it would be nice to show the sections that an article is assigned to.

function kb_columns( $defaults ) {
	$defaults['section'] = 'Sections';
	return $defaults;
}
add_filter( 'manage_knowledgebase_posts_columns', 'kb_columns' );

function kb_custom_column( $column_name, $post_id ) {
	$taxonomy = $column_name;
	$post_type = get_post_type( $post_id );
	$terms = get_the_terms( $post_id, $taxonomy );
	if ( !empty( $terms ) ) {
		foreach ( $terms as $term ) {
			$post_terms[] = "<a href='edit.php?post_type={$post_type}&{$taxonomy}={$term->slug}'> " . esc_html(sanitize_term_field('name', $term->name, $term->term_id, $taxonomy, 'edit')) . '</a>';
		}
		echo join( ', ', $post_terms );
	}
	else echo '<i>No terms.</i>';
}
add_action( 'manage_knowledgebase_posts_custom_column', 'kb_custom_column', 10, 2 );

Now add some sections and some articles so there is something to show.


Step 2 Showing the Sections

Add the following into functions.php from your theme.

function kb_sections( $sections = array(), $active_section = null ) {
	$taxonomy = 'section';
	$link_class = '';
	if ( empty( $sections ) ) {
		$link_class = 'root';
		$sections = get_terms( $taxonomy, array( 'parent' => 0, 'hide_empty' => 0 ) );
		$active_section = kb_active_section();
		echo '<ul id="kb-sections" class="unstyled">';
	}
	if ( empty( $active_section ) ) {
		$active_section = '';
	}
	foreach ( $sections as $section ) {
		$toggle = '';
		$section_children = get_terms( $taxonomy, array( 'parent' => $section->term_id, 'hide_empty' => 0 ) );
		if ( !empty( $section_children ) && $link_class != 'root' ) {
			$toggle = '<i class="toggle"></i>';
		}
		echo '<li class="' . ( $section->term_id == $active_section ? 'active' : '' ) . '">';
		echo '<a  href="' . get_term_link( $section, $taxonomy ) . '" class="' . $link_class . '" rel="' . $section->slug . '">' . $toggle . $section->name . '</a>';
		
		if ( !empty( $section_children ) ) {
			echo '<ul id="' . $section->slug . '" class="children">';
			kb_sections( $section_children, $active_section );
		}
		echo "</li>";
	}
	echo "</ul>";
}

function kb_active_section() {
	$taxonomy = 'section';
	$current_section = '';
	if ( is_single() ) {
		$sections = explode( '/', get_query_var( $taxonomy ) );
		$section_slug = end( $sections );
		if ( $section_slug != '' ) {
			$term = get_term_by( 'slug', $section_slug, $taxonomy );
		} else {
			$terms = wp_get_post_terms( get_the_ID(), $taxonomy );
			$term = $terms[0];
		}
		$current_section = $term->term_id;
	} else {
		$term = get_term_by( 'slug', get_query_var( $taxonomy ), get_query_var( 'taxonomy' ) );
		$current_section = $term->term_id;
	}
	return $current_section;
}

In the theme folder create a file called sidebar-sections.php where your kb_sections function will be called outputting an unordered and nested list of sections.

<?php kb_sections(); ?>

Like this, the KB sections can be shown everywhere as desired by including the sidebar.

<?php get_sidebar( 'sections' ); ?>

Step 3 Showing the Articles

Add the following into functions.php from your theme.

function kb_article_permalink( $article_id, $section_id ) {
	$taxonomy = 'section';
	$article = get_post( $article_id );
	$section = get_term( $section_id, $taxonomy );
	$section_ancestors = get_ancestors( $section->term_id, $taxonomy );
	krsort( $section_ancestors );
	$permalink = '<a href="/knowledgebase/';
	foreach ($section_ancestors as $ancestor):
		$section_ancestor = get_term( $ancestor, $taxonomy );
		$permalink.= $section_ancestor->slug . '/';
	endforeach;
	$permalink.= $section->slug . '/' . $article->post_name . '/" >' . $article->post_title . '</a>';
	return $permalink;
}

Note: this method is necessary because an article can be linked to multiple sections.

This will generate a hierarchical permalink structure.

Like: /knowledgebase/section-slug/sub-section-slug/another-sub-section-slug/article-slug

In the theme folder then create these files: archive-knowledgebase.php, single-knowledgebase.php, content-knowledgebase.php, taxonomy-section.php.

In archive-knowledgebase.php add the following to show the sections and recent articles.

<?php
get_header();
get_sidebar( 'sections' );
while ( have_posts() ) : the_post();
	$terms = wp_get_post_terms( $post->ID, 'section' );
	$term = $terms[0];
	echo kb_article_permalink( $post->ID, $term->term_id );
endwhile;
get_footer();
?>

In single-knowledgebase.php add the following.

<?php
get_header();
while ( have_posts() ) : the_post();
	get_template_part( 'content', 'knowledgebase' );
endwhile;
get_footer();
?>

In content-knowledgebase.php add the following.

<?php
get_sidebar( 'sections' );
the_title();
the_content();
?>

In taxonomy-section.php add the following to show a list of articles from a section.

<?php
global $wp_query;
$args = array_merge( $wp_query->query, array( 'posts_per_page' => 100 ) );
query_posts( $args );
$term = get_term_by( 'slug', get_query_var( 'term' ), 'section' );

get_header();
get_sidebar( 'sections' );
while ( have_posts() ) : the_post();
	echo kb_article_permalink( $post->ID, $term->term_id );
endwhile;
get_footer();
?>

This can be structured and styled as desired.


Example

A real life example of how this works and how it can be used: syneto.net


References

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • kierzniak

    Hi, nice article. Do you know maybe how to add a menu page with articles from all sections? The only solution that I know is to create shortcode add to page and add this page to menu. But this is to complicated to my clients ;]

    • http://www.jpattison.com JPinc

      Had to create the same thing last night. This will loop through each category and display 3 posts from each category below the respective category title.

      <?php $categories = get_categories( array (‘orderby’ => ‘count’, ‘order’ => ‘desc’ ) ); ?>
      <?php foreach ($categories as $category) : ?>
      <?php query_posts( array ( ‘post_type’ => ‘your_post_type’, ‘category_name’ => $category->slug, ‘showposts’ => ’3′, ‘orderby’ => ‘date’, ‘order’ => ‘ASC’ ) ); ?>
      <?php
      global $wp_query;
      $cat_ID = get_query_var(‘cat’); // grabs category ID
      $cat_link = get_category_link($cat_ID); // grabs the archive link associated with the category ID
      ?>

      <div class=”postcat_box”>
      <h2><?php single_cat_title(); // display category title ?></h2>

      <?php // good old wordpress loop
      if ( have_posts() ):
      while ( have_posts() ) :
      the_post();
      ?>
      <div class=”category_post”>
      <a href=”<?php the_permalink(); ?>”><?php the_title();?></a>
      <?php the_excerpt();?>
      </div> <!– /.category_post –>
      <?php endwhile; ?>
      <?php endif; // ends wordpress loop ?>

      <a class=”catarchive_link” href=”<?php echo $cat_link;?>” alt=”Read more articles”>» Find More Articles</a>
      </div><!– /.postcat_box –>

      <?php endforeach; // ends the primary category loop ?>

      • http://www.jpattison.com JPinc

        Slight revision to my original post. I shuffled the “if” statement to check if the category has posts before displaying. If there’s no posts associated with the category, then it won’t show up.

        <?php $categories = get_categories( array (‘orderby’ => ‘count’, ‘order’ => ‘desc’ ) ); ?>
        <?php foreach ($categories as $category) : ?>
        <?php query_posts( array ( ‘post_type’ => ‘your_post_type’, ‘category_name’ => $category->slug, ‘showposts’ => ’3′, ‘orderby’ => ‘date’, ‘order’ => ‘ASC’ ) ); ?>
        <?php
        global $wp_query;
        $cat_ID = get_query_var(‘cat’); // grabs category ID
        $cat_link = get_category_link($cat_ID); // grabs the archive link associated with the category ID
        ?>
        <?php if ( have_posts() ): // start wordpress loop and check to see if category contains posts ?>
        <div class=”postcat_box”>
        <h2><?php single_cat_title(); // display category title ?></h2>

        <?php // if category has posts, display em’
        while ( have_posts() ) :
        the_post();
        ?>
        <div class=”category_post”>
        <a href=”<?php the_permalink(); ?>”><?php the_title();?></a>
        <?php the_excerpt();?>
        </div> <!– /.category_post –>
        <?php endwhile; ?>

        <a class=”catarchive_link” href=”<?php echo $cat_link;?>” alt=”Read more articles”>» Find More Articles</a>
        </div><!– /.postcat_box –>
        <?php endif; // ends wordpress loop ?>
        <?php endforeach; // ends the primary category loop ?>

        • http://oustcat.com oustcat

          JPinc, I have spent several hours attempting to get the code you’ve provided to display each category/section and 3 posts from each category but have been unsuccessful. Nothing displays. There seems to be an issue with obtaining the categories, which is evident when I comment out ‘category_name’ => $category->slug in the query_post.

          Can you look at my code, and determine where the issue lies? I’m using a page template (page-knowledgebase.php) for this code.

          ‘count’, ‘order’ => ‘desc’ ) );
          $cat_slug = $category->slug; ?>

          ‘knowledgebase’, ‘showposts’ => ’3′, ‘orderby’ => ‘date’,
          ‘order’ => ‘DESC’, ‘category_name’ => $cat_slug ) ); ?>

          <a href="”>

          <a class="catarchive_link" href="” alt=”Read more articles”>» Find More Articles

          Thank you.

        • http://oustcat.com oustcat

          JPinc, I have spent several hours attempting to get the code you’ve provided to display each category/section and 3 posts from each category but have been unsuccessful. Nothing displays. There seems to be an issue with obtaining the categories, which is evident when I comment out ‘category_name’ => $category->slug in the query_post.

          Can you look at my code, and determine where the issue lies? I’m using a page template (page-knowledgebase.php) for this code.

          or http://pastie.org/3918256

          Thank you.

          • http://www.jpattison.com JPinc

            I took a look and here’s a corrected version

            http://pastebin.com/PkFeX1Hh

            You had the $cat_slug = $category->slug; variable listed before the foreach statement when it should follow. Every time the “foreach” loops through the category list it needs to define the category name associated with that particular loop instance.

            Here’s a simplified version which just generates a list of category slug names to illustrate.

            < ?php $categories = get_categories( array (‘orderby’ => ‘count’, ‘order’ => ‘desc’ ) ); ?>
            < ul>
            < ?php foreach ($categories as $category) : ?>
            < ?php $cat_slug = $category->slug; ?>
            < li>< ?php echo $cat_slug; ?>< /li>
            < ?php endforeach; // ends the primary category loop ?>
            < /ul>

  • R.R.

    Very good one. I would like to see more articles about the permalink manipulatons. Construction custom ones, etc.

  • Pingback: WordPress as a Knowledge Base | Qtiva

  • Pingback: How to use WordPress as a Knowledge Base | WPAOT

  • JB

    Where are you defining emptyempty( ) ?

    • http://wp.envato.com/ Japh Thomson
      Staff

      Sorry about that, emptyempty should actually just be empty (standard PHP function). Our code syntax highlighter has a bug :(

      • JB

        Awesome thanks!

        Now where is the knowledgebase_article_permalink() function defined?

        • https://gurde.com Robert
          Author

          That is a typo. Sorry for that. It should be kb_article_permalink instead of knowledgebase_article_permalink.

          For the future as an advise, when these kind of typos appear and errors are generated you can look up the source code. Copy pasting blindly is not going to help your knowledge much.

          It’s not an excuse, but I’m human and I do mistakes too.

      • http://wpgetready.com Nando

        Something is missing: knowledgebase_article_permalink … ?

      • https://gurde.com Robert
        Author

        Please correct that typo. It should be kb_article_permalink instead of knowledgebase_article_permalink.

        • http://wp.envato.com/ Japh Thomson
          Staff

          Thanks for your quick correction on this, Robert! Correction done :)

  • http://amrabdelaziz.com amrabdelaziz

    very nice tutorial
    >

  • Pingback: WordPress as a Knowledge Base | Shadowtek Hosting and Design Solutions

  • http://govertz.dk Govertz

    I will set this up on my localhost, and use it to organise my collection of a mixture made of tutorials and articles, wich I find usefull, and use in my efford to become a wordpress developer.

  • http://arifriyanto.com Arif Riyanto

    Great tuts, Robert. Here’s article I was looking for.

  • Mike

    This is exactly what I am looking for but I cannot get it to work.. When I go to save a post or page now It just gives me a blank page. but in the background the changes are saved..

    Here is my functions.php code

     array(  
                    'name' => 'Knowledge Base',  
                    'menu_name' => 'Knowledge Base',  
                    'singular_name' => 'Article',  
                    'all_items' => 'All Articles'  
                ),  
                'public' => true,  
                'publicly_queryable' => true,  
                'show_ui' => true,  
                'show_in_menu' => true,  
                'show_in_nav_menus' => true,  
                'menu_position ' => 20,  
                'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'comments', 'post-formats', 'revisions' ),  
                'hierarchical' => false,  
                'taxonomies' => array( 'section' ),  
                'has_archive' => true,  
                'rewrite' => array( 'slug' => 'knowledgebase', 'hierarchical' => true, 'with_front' => false )  
            )  
        );  
      
        register_taxonomy( 'section', array( 'knowledgebase' ),  
            array(  
                'labels' => array(  
                    'name' => 'Sections',  
                    'menu_name' => 'Sections',  
                    'singular_name' => 'Section',  
                    'all_items' => 'All Sections'  
                ),  
                'public' => true,  
                'hierarchical' => true,  
                'show_ui' => true,  
                'rewrite' => array( 'slug' => 'knowledgebase-section', 'hierarchical' => true, 'with_front' => false ),  
            )  
        );  
    }  
    add_action( 'init', 'register_kb' );  
     
    function kb_rewrite_rules( $wp_rewrite ) {  
        $new_rules = array( 'knowledgebase/(.*)/(.*)' => 'index.php?post_type=knowledgebase&section=' . $wp_rewrite->preg_index( 1 ) . '&knowledgebase=' . $wp_rewrite->preg_index( 2 ) );  
        $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;  
    }  
    add_action( 'generate_rewrite_rules', 'kb_rewrite_rules' ); 
    
    ?>
    
    <?php
        function kb_columns( $defaults ) {  
            $defaults['section'] = 'Sections';  
            return $defaults;  
        }  
        add_filter( 'manage_knowledgebase_posts_columns', 'kb_columns' );  
          
        function kb_custom_column( $column_name, $post_id ) {  
            $taxonomy = $column_name;  
            $post_type = get_post_type( $post_id );  
            $terms = get_the_terms( $post_id, $taxonomy );  
            if ( !emptyempty( $terms ) ) {  
                foreach ( $terms as $term ) {  
                    $post_terms[] = "<a>slug}'> " . esc_html(sanitize_term_field('name', $term->name, $term->term_id, $taxonomy, 'edit')) . '</a>';  
                }  
                echo join( ', ', $post_terms );  
            }  
            else echo '<i>No terms.</i>';  
        }  
        add_action( 'manage_knowledgebase_posts_custom_column', 'kb_custom_column', 10, 2 );  
    ?>
    
     0, 'hide_empty' => 0 ) );  
                $active_section = kb_active_section();  
                echo '';  
            }  
            if ( emptyempty( $active_section ) ) {  
                $active_section = '';  
            }  
            foreach ( $sections as $section ) {  
                $toggle = '';  
                $section_children = get_terms( $taxonomy, array( 'parent' => $section->term_id, 'hide_empty' => 0 ) );  
                if ( !emptyempty( $section_children ) && $link_class != 'root' ) {  
                    $toggle = '<i></i>';  
                }  
                echo 'term_id == $active_section ? 'active' : '' ) . '">';  
                echo '<a href="' . get_term_link( $section, $taxonomy ) . '" rel="nofollow">slug . '">' . $toggle . $section->name . '</a>';  
          
                if ( !emptyempty( $section_children ) ) {  
                    echo 'slug . '" class="children">';  
                    kb_sections( $section_children, $active_section );  
                }  
                echo "";  
            }  
            echo "";  
        }  
          
        function kb_active_section() {  
            $taxonomy = 'section';  
            $current_section = '';  
            if ( is_single() ) {  
                $sections = explode( '/', get_query_var( $taxonomy ) );  
                $section_slug = end( $sections );  
                if ( $section_slug != '' ) {  
                    $term = get_term_by( 'slug', $section_slug, $taxonomy );  
                } else {  
                    $terms = wp_get_post_terms( get_the_ID(), $taxonomy );  
                    $term = $terms[0];  
                }  
                $current_section = $term->term_id;  
            } else {  
                $term = get_term_by( 'slug', get_query_var( $taxonomy ), get_query_var( 'taxonomy' ) );  
                $current_section = $term->term_id;  
            }  
            return $current_section;  
        }  
    ?>
    
    term_id, $taxonomy );  
            krsort( $section_ancestors );  
            $permalink = '<a>slug . '/';  
            endforeach;  
            $permalink.= $section->slug . '/' . $article->post_name . '/" >' . $article->post_title . '</a>';  
            return $permalink;  
        }  
    ?>
    
    • http://.- Sieben

      @Mike

      on line 72 i see you have double empty

      ******************************************************
      if ( emptyempty( $active_section ) ) {
      $active_section = ”;
      ************************************************

      Perhaps you copy directly from the code syntax, there is only one empty

      ******************************************************
      if ( empty( $active_section ) ) {
      $active_section = ”;
      ************************************************

      • http://wp.envato.com/ Japh Thomson
        Staff

        Apologies for that bug in our syntax highlighter! We should have it fixed soon.

  • Joe

    Is it possible for you to build this into a plugin?

    • Martyn

      Oh, that would be so awesome!

      I am fairly new to WP and PHP so this is a true battle for me.
      Although I feel I am learning a lot from this tut, I somehow have the feeling some steps are missing that only real programmers seem to know.

  • http://.- Sieben

    i have a multisite, does it work well?

    i don’t know where exactly where to edit to remove “knowledgebase/” i want to get rid of that, any help?

  • http://designcanyon.com/ Steve Kamn

    Thanks for the very informative tutorial.

  • Pingback: WordPress Weekly Links | WPStream.com

  • Stephen

    This doesnt work at all like the demo. It doesnt list the articles in the sidebar under the sections or work like the demo at all. Expectations from the demo are not met at all!

    • https://gurde.com Robert
      Author

      Hi Stephen,

      The demo is intended to show you what you can achieve.
      As I believe the articles found here are for learning purposes, and I tried to teach you something. If you are not willing to think and just copy paste and hope it works… then you are going the wrong path.

      • http://www.allenmoore.me Allen

        Thanks for that reply Robert. Someone needed to say that this is an starting point, not a way to be lazy.

        And also thank you for this code. I’m going to be using this on a project here at work. When we get done I’ll be sure to post the finished product.

  • Pingback: Организация «Базы знаний» на WordPress | Wordpresso

  • Pingback: Google Alert - China Man Ferrari Driver hit Taxi Bugis Singapore 2012

  • http://www.uckhandla.com/ Ujamshi

    Is what I’m looking for! Thanks a lot.

  • Pingback: WordPress and Web Development: Top Resources for June 2012 - ManageWP

  • Dario

    I thing is high recomedable you do a theme with this tutorial

  • WP Rookie

    Hi, please explain, is there something else to be done here since I have no results adding this code to functions.php

    I have created all five other PHP files and uploaded to server, but still no response. Can you please give an explanation for dummies?

    Thanks

    • WP Rookie

      My mistake. I have added code at the end of functions.php.
      I have added the same code above and it works

  • Will

    Robert,

    I know that this is a tutorial not a cut and paste exercise but I am struggling (even with a lot of thought!) to figure out how to emulate the functionality you have on your demo, i.e list the articles within the section in the sidebar…any chance you would offer a hint or two??

    Love the tutorial though and have learnt from it already…

    Cheers,

    Will

    • Martyn

      Rightright, me 2.
      I have been here two days and still haven’t figured it out.
      Teach me master ;-)

  • http://raspians.com TC

    Hi I love the code implementing now have a question it seems on single-knowledgebase.php and content-knowledgebase.php the output is not properly inside a div tag so it offsets the text just left of the main content I have been trying everything I can think of to insert the div for content and main based on the simple twentyten 2 column layout can you please assist in point me to where it would go everything I try just puts it out there?

    Again thanks for the code it’s perfect for what I am doing. Any assistance you can offer would be greatly appreciated.

  • Pingback: Create a custom taxonomy menu in WordPress

  • Ken

    Neat to see what can be done with WP. I had started a project similar to this and have a popular KB article and a recent KB article sections on my KB landing page. One thing I wanted to implement was including a KB# in addition to the pretty URL given by the permalink structure. I was figuring that I could just use the article ID number as the root and then just add “kb” to the front giving me “kb001234″ as an example. Would there be a way to add this number to the title dynamically or is it possible to just create a search for this CPT that could find the ID number based on a kb# as well as search the title?

  • Pingback: Como crear con Wordpress una Knowledge Base | Memorias de un aprendiz

  • http://www.facebook.com/BADBOYJ James Brian Fosker

    How can i integrate this with yoothemes