Building a question-answer interface
Throughout the previous sections, we learned the basics of web application frameworks while looking at how WordPress fits into web development. By now, you should be able to visualize the potential of WordPress for application development and how it can change your career as developers. Being human, we always prefer practical approach to learn new things over the more conventional theoretical approach.
So, I will complete this chapter by converting default WordPress functionality into a simple question-answer interface such as Stack Overflow, to give you a glimpse of what we will develop throughout this book.
Prerequisites for building a question-answer interface
We will be using version 4.2.2 as the latest stable version; this is available at the time of writing this book. I suggest that you set up a fresh WordPress installation for this book, if you haven't already done so.
Tip
Also, we will be using the Twenty Fourteen theme, which is available with default WordPress installation. Make sure that you activate the Twenty Fourteen theme in your WordPress installation.
First, we have to create an outline containing the list of tasks to be implemented for this scenario:
- Create questions using the admin section of WordPress.
- Allow users to answer questions using comments.
- Allow question creators to mark each answer as correct or incorrect.
- Highlight the correct answers of each question.
- Customize the question list to include a number of answers and number of correct answers.
Now, it's time to get things started.
The goal of this application is to let people submit questions and get answers from various experts in the same field. First off, we need to create a method to add questions and answers. By default, WordPress allows us to create posts and submit comments to the posts. In this scenario, a post can be considered as the question and comments can be considered as the answers. Therefore, we have the capability of directly using normal post creation for building this interface.
However, I would like to choose a slightly different approach by using custom post types plugin, which you can find at http://codex.wordpress.org/Post_Types#Custom_Post_Types, in order to keep the default functionality of posts and let the new functionality be implemented separately without affecting the existing ones. We will create a plugin to implement the necessary tasks for our application:
- First off, create a folder called
wpwa-questions
inside the /wp-content/plugins
folder and add a new file called wpwa-questions.php
. - Next, we need to add the block comment to define our file as a plugin:
- Having created the main plugin file, we can move into creating a custom post type called
wpwa-question
using the following code snippet. - Include this code snippet in your
wpwa-questions.php
file of the plugin:add_action('init', 'register_wp_questions');
function register_wp_questions() {
$labels = array(
'name' => __( 'Questions', 'wpwa_questions' ),
'singular_name' => __( 'Question', 'wpwa_questions'),
'add_new' => __( 'Add New', 'wpwa_questions'),
'add_new_item' => __( 'Add New Question', 'wpwa_questions'),
'edit_item' => __( 'Edit Questions', 'wpwa_questions'),
'new_item' => __( 'New Question', 'wpwa_questions'),
'view_item' => __( 'View Question', 'wpwa_questions'),
'search_items' => __( 'Search Questions', 'wpwa_questions'),
'not_found' => __( 'No Questions found', 'wpwa_questions'),
'not_found_in_trash' => __( 'No Questions found in Trash', 'wpwa_questions'),
'parent_item_colon' => __( 'Parent Question:', 'wpwa_questions'),
'menu_name' => __( 'Questions', 'wpwa_questions'),
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'description' => __( 'Questions and Answers', 'wpwa_questions'),
'supports' => array( 'title', 'editor', 'comments' ),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => true,
'capability_type' => 'post'
);
register_post_type( 'wpwa_question', $args );
}
This is the most basic and default code for custom post type creation, and I assume that you are familiar with the syntax. We have enabled title, editor, and comments in the support section of the configuration. These fields will act the role of question title, question description, and answers. Other configurations contain the default values and hence explanations will be omitted. If you are not familiar, make sure to have a look at documentation on custom post creation at http://codex.wordpress.org/Function_Reference/register_post_type.
Note
Beginner- to intermediate-level developers and designers tend to include the logic inside the functions.php
file in the theme. This is considered a bad practice as it becomes extremely difficult to maintain because your application becomes larger. So, we will be using plugins to add functionality throughout this book and drawbacks of the functions.php
technique will be discussed in later chapters.
- Once the code is included, you will get a new section on the admin area for creating questions. This section will be similar to the posts section inside the WordPress admin. Add few questions and insert some comments using different users before we move into the next stage.
Before we go into the development of questions and answers, we need to make some configurations so that our plugin works without any issues. Let's look at the configuration process:
- First, we have to look at the comment-related settings inside Discussion Settings the WordPress Settings section. Here, you can find a setting called Before a comment appears.
- Disable both checkboxes so that users can answer and get their answers displayed without approval process. Depending on the complexity of application, you can decide whether to enable these checkboxes and change the implementation.
- The second setting we have to change is the Permalinks. Once we create a new custom post type and view it on browser, it will redirect you to a
404 page not found
page. Therefore, we have to go to the Permalinks section of WordPress Settings and update the Permalinks using the Save Changes button. This won't change the Permalinks. However, this will flush the rewrite rules so that we can use the new custom post type without 404
errors.
Now, we can start working with the answer-related features.
Customizing the comments template
Usually, the comments section is designed to show comments of a normal post.
While using comments for custom features such as answers, we need to customize the existing template and use our own designs.
- So, open the
comments.php
file inside the Twenty Fourteen theme. - Navigate through the code and you will find a code section similar to the following one:
- First, we need to customize the existing comments list to suit the requirements of the answers list. By default, WordPress will use the
wp_list_comments
function inside the comments.php
file to show the list of answers for each question. We need to modify the answers list in order to include the answer status button. So, we will change the previous implementation as following: - Here, we will include a conditional check for the post type in order to choose the correct answer list generation function. When the post type is
wpwa_question
, we call the wp_list_comments
function with the callback parameter defined as wpwa_comment_list
, which will be the custom function for generating answers list.Note
Arguments of the wp_list_comments
function can be either an array or string. Here, we have preferred array-based arguments over string-based arguments.
In the next section, we will be completing the customization of comments template by adding answer statuses and allowing users to change the statuses.
Changing the status of answers
Once the users provide their answers, the creator of the question should be able to mark them as correct or incorrect answers. So, we will implement a button for each answer to mark the status. Only the creator of the questions will be able to mark the answers. Once the button is clicked, an AJAX request will be made to store the status of the answer in the database.
Implementation of the wpwa_comment_list
function goes inside the wpwa-questions.php
file of our plugin. This function contains lengthy code, which is not necessary for our explanations. Hence, I'll be explaining the important sections of the code. It's ideal to work with the full code for the wpwa_comment_list
function from the source code folder:
The wpwa_comment_list
function is used as the callback function of the comments list, and hence, it will contain three parameters by default. Remember that the button for marking the answer status should be only visible to the creator of the question.
In order to change the status of answers, follow these steps:
- First, we will get the current logged-in user from the
wp_get_current_user
function. Also, we can get the creator of the question using the global $post
object. - Next, we will check whether the logged-in user created the question. If so, we will set
show_answer_status
to true. Also, we have to retrieve the status of the current answer by passing the comment_id
and _wpwa_answer_status
keys to the get_comment_meta
function. - Then, we will have to include the common code for generating comments list with necessary condition checks.
- Open the
wpwa-questions.php
file of the plugin and go through the rest of wpwa_comment_list
function to get an idea of how comments loop works. - Next, we have to highlight correct answers of each question and I'll be using an image as the highlighter. In the source code, we use following code after the header tag to show the correct answer highlighter:
- In the source code, you will see a
<div>
element with the class reply
for creating the comment reply link. We will need to insert our answer button status code right after this, as shown in the following code: - If the
show_answer_status variable
is set to true
, we get the comment ID, which will be our answer ID, using the get_comment_ID
function. Then, we will get the status of answer as true or false using the _wpwa_answer_status
key from the wp_commentmeta
table. - Based on the returned value, we will define buttons for either Mark as Incorrect or Mark as Correct. Also, we will specify some CSS classes and HTML5 data attribute to be used later with jQuery.
- Finally, we keep the
comment_id
in a hidden variable called hcomment
. - Once you include the code, the button will be displayed for the author of the question, as shown in the following screen:
- Next, we need to implement the AJAX request for marking the status of the answer as true or false.
Before this, we need to see how we can include our scripts and styles into WordPress plugins. Here is the code for including custom scripts and styles for our plugin. Copy the following code into the wpwa-questions.php
file of your plugin:
WordPress comes in-built with an action hook called wp_enqueue_scripts
, for adding JavaScript and CSS files. The wp_enqueue_script
action is used to include script files into the page while the wp_register_script
action is used to add custom files. Since jQuery is built-in to WordPress, we can just use the wp_enqueue_script
action to include jQuery into the page. We also have a custom JavaScript file called questions.js
, which will contain the functions for our application.
Inside JavaScript files, we cannot access the PHP variables directly. WordPress provides a function called wp_localize_script
to pass PHP variables into script files. The first parameter contains the handle of the script for binding data, which will be wp_questions
in this scenario. The second parameter is the variable name to be used inside JavaScript files to access these values. The third and final parameters will be the configuration array with the values.
Then, we can include our questions.css
file using the wp_register_style
and wp_enqueue_style
functions, which will be similar to JavaScript, file inclusion syntax, we discussed previously. Now, everything is set up properly to create the AJAX request.
Saving the status of answers
Once the author clicks the button, the status has to be saved to the database as true or false depending on the current status of the answer. Let's go through the jQuery code located inside the questions.js
file for making the AJAX request to the server:
The preceding code creates a basic AJAX request to the mark_answer_status
action. Most of the code is self-explanatory and code comments will help you to understand the process.
Note
The important thing to note here is that we have used the configuration settings assigned in the previous section, using the wpwaconf
variable. Once a server returns the response with success status, the button will be updated to contain new status and display text.
The next step of this process is to implement the server-side code for handling AJAX request. First, we need to define AJAX handler functions using the WordPress add_action
function. Since logged-in users are permitted to mark the status, we don't need to implement the add_action
function for wp_ajax_nopriv_{action}
:
Implementation of the wpwa_mark_answer_status
function is given in the following code:
We can get the necessary data from the $_POST
array and use to mark the status of the answer using the update_comment_meta
function. This example contains the most basic implementation of data saving process. In real applications, we need to implement necessary validations and error handling.
Now, the author who asked the question has the ability to mark answers as correct or incorrect. So, we have implemented a nice and simple interface for creating a question-answer site with WordPress. The final task of the process will be the implementation of questions list.
Generating a question list
Usually, WordPress uses the archive.php
file of the theme, for generating post lists of any type. We can use a file called archive-{post type}.php
for creating different layouts for different post types:
- Here, we will create a customized layout for our questions.
- Make a copy of the existing
archive.php
file of the TwentyFourteen theme and rename it as archive-wpwa_question.php
. Here, you will find the following code section: - The TwentyFourteen theme uses a separate template for generating the content of each post type. We cannot modify the existing
content.php
file as it affects all kinds of posts. So, create a custom template called content-questions.php
by duplicating the content.php
file and change the preceding code to the following: - Finally, we need to consider the implementation of
content-wpwa_question.php
file. In the questions list, only the question title will be displayed, and therefore, we don't need the content of the post. So, we have to either remove or comment the the_excerpt
and the_content
functions of the template. We can comment the following line within this template: - Then, we will create our own metadata by adding the following code to the
<div>
element with the entry-content
class:The first container will make use of the existing comments_popup_link
function to get the number of answers given for the questions.
- Then, we need to display the number of correct answers of each question. The custom function called
wpwa_get_correct_answers
is created to get the correct answers. The following code contains the implementation of the wpwa_get_correct_answers
function inside the plugin:We can set the array of arguments to include the conditions to retrieve the approved answers of each post, which contains the correct answers. The number of results generated from the get_comments
function will be returned as correct answers. Now, you should have a question list similar to following image:
Throughout this section, we looked at how we can convert the existing functionalities of WordPress for building a simple question-answer interface. We took the quick and dirty path for this implementation by mixing HTML and PHP code inside both, themes and plugins.
Note
I suggest that you go through the Chapter01
source code folder and try this implementation on your own test server. This demonstration was created to show the flexibility of WordPress. Some of you might not understand the whole implementation. Don't worry as we will develop a web application from scratch using detailed explanation in the following chapters.