Awesome tips & tricks to help restaurants increase the return on investment on their websites. If your local restaurant has flash, music playing or PDF menus, pass it on!
The WordPress 'big projects' group. Practical advice, discussion and idea sharing for scaling WordPress.
Whether you’re starting a simple blog, creating a corporate website or building a creative portfolio with WordPress, a “Contact (Us)” page is (almost) always necessary and it’s (almost) always better to have a contact form instead of sharing your e-mail address publicly (spam robots love them, though). Of course, there are plenty of great contact form plugins for WordPress but why bloat up the website with heavy plugins with lots of database queries, when we can use just a lovely, simple custom shortcode plugin instead?
Benefits of Building Your Own Contact Form
Plugins are awesome, but too many of them with lots of functionality you don’t need can bloat up your website by using database connections, running extra PHP code, adding CSS stylesheets and JS files to your header… so, at some point, you just want to stay away from existing plugins, regardless of how awesome the plugin is that you want to use.
If you don’t know how to code, I must admit that your hands are (kind of) tied and you’re bound to use plugins. But if you’re familiar with WordPress development at any level (and I’m assuming that you are, since you’re still with me) then you should consider the benefits of hacking your own theme or coding your own plugin. Here are the advantages in my mind:
- Optimization – Using too much code, especially extra code you don’t need, can even push your hosting plan’s limits in some cases. But even if you have plenty of resources on your server, optimization is always good for your website’s health.
- Cleanliness – Apart from the health of the server, cleaner code can be a huge benefit for your website loading & parsing speed. By coding/hacking on your own, you just use what you need and don’t have to load tons of stuff in order to utilize a simple functionality on your website. It’s even good for SEO, you know.
- The joy of taking control – You should never underestimate the power of calling the shots. Taking control on your website definitely makes you a more enthusiastic designer/developer than using a bunch of ready-made code. That’s why, even though we provide the full code for those who don’t want to, I personally think that you should not copy/paste the code here but write it yourself. Even if you type exactly the same code, you could see how the plugin works and you feel the delight of taking control. Seriously.
The Code
All right, enough with the chit-chat – let’s start coding! We’re not going to deal with huge amounts of code or any kind of hard work here, so even if you’re a beginner at PHP and/or WordPress, you can understand the code by following my lead and researching any part of the code that you don’t recognize.
It’s possible to put this code directly to your theme’s functions.php file, but a better way to go is using it as a plugin. This way when you switch themes, you don’t lose functionality and end up with shortcodes being printed in your content. Let’s start with the standard plugin information:
<?php /* Plugin Name: Simple Contact Form Shortcode Plugin URI: http://wp.tutsplus.com/author/barisunver/ Description: A simple contact form for simple needs. Usage: <code>[contact email="your@email.address"]</code> Version: 1.0 Author: Barış Ünver Author URI: http://beyn.org/ */ // This line of comment holds the place of the amazingly simple code we're going to write. So you don't really need to read this. ?>A Tiny Helper Function: get_the_ip()
As you can guess from the name of the function, we’re getting the real IP address of the user, even if the user is connecting through a proxy server. It’s not bulletproof, of course, but we’re going to use this as an extra bit of information from the user anyways.
Basically, we’re going to try to get the different $_SERVER variables: HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP and REMOTE_ADDR, respectively. Here’s the code:
function wptuts_get_the_ip() { if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) { return $_SERVER["HTTP_X_FORWARDED_FOR"]; } elseif (isset($_SERVER["HTTP_CLIENT_IP"])) { return $_SERVER["HTTP_CLIENT_IP"]; } else { return $_SERVER["REMOTE_ADDR"]; } }The Shortcode
If you follow my posts here on Wptuts+, you know that I absolutely love WordPress’ Shortcode API.
I’m going to divide the shortcode into 3 sections to be able to explain it better, but let’s not forget to open and close the shortcode function first:
function wptuts_contact_form_sc( $atts ) { // This line of comment, too, holds the place of the brilliant yet simple shortcode that creates our contact form. And yet you're still wasting your time to read this comment. Bravo. } add_shortcode( 'contact', 'wptuts_contact_form_sc' );Attributes of Our Shortcode
We need to set a few attributes in order to stay flexible while still being lightweight. Here’s ten:
extract( shortcode_atts( array( // if you don't provide an e-mail address, the shortcode will pick the e-mail address of the admin: "email" => get_bloginfo( 'admin_email' ), "subject" => "", "label_name" => "Your Name", "label_email" => "Your E-mail Address", "label_subject" => "Subject", "label_message" => "Your Message", "label_submit" => "Submit", // the error message when at least one of the required fields are empty: "error_empty" => "Please fill in all the required fields.", // the error message when the e-mail address is not valid: "error_noemail" => "Please enter a valid e-mail address.", // and the success message when the e-mail is sent: "success" => "Thanks for your e-mail! We'll get back to you as soon as we can." ), $atts ) );Remember that we’re going to reference them in our code as a variable with the attribute’s name (e.g. $label_submit).
E-Mailing the E-Mail
This is the most important part of the function, so I’ll go ahead and explain the code inside the code, with comment lines:
// if the <form> element is POSTed, run the following code if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { $error = false; // set the "required fields" to check $required_fields = array( "your_name", "email", "message", "subject" ); // this part fetches everything that has been POSTed, sanitizes them and lets us use them as $form_data['subject'] foreach ( $_POST as $field => $value ) { if ( get_magic_quotes_gpc() ) { $value = stripslashes( $value ); } $form_data[$field] = strip_tags( $value ); } // if the required fields are empty, switch $error to TRUE and set the result text to the shortcode attribute named 'error_empty' foreach ( $required_fields as $required_field ) { $value = trim( $form_data[$required_field] ); if ( empty( $value ) ) { $error = true; $result = $error_empty; } } // and if the e-mail is not valid, switch $error to TRUE and set the result text to the shortcode attribute named 'error_noemail' if ( ! is_email( $form_data['email'] ) ) { $error = true; $result = $error_noemail; } if ( $error == false ) { $email_subject = "[" . get_bloginfo( 'name' ) . "] " . $form_data['subject']; $email_message = $form_data['message'] . "\n\nIP: " . wptuts_get_the_ip(); $headers = "From: " . $form_data['name'] . " <" . $form_data['email'] . ">\n"; $headers .= "Content-Type: text/plain; charset=UTF-8\n"; $headers .= "Content-Transfer-Encoding: 8bit\n"; wp_mail( $email, $email_subject, $email_message, $headers ); $result = $success; $sent = true; } // but if $error is still FALSE, put together the POSTed variables and send the e-mail! if ( $error == false ) { // get the website's name and puts it in front of the subject $email_subject = "[" . get_bloginfo( 'name' ) . "] " . $form_data['subject']; // get the message from the form and add the IP address of the user below it $email_message = $form_data['message'] . "\n\nIP: " . wptuts_get_the_ip(); // set the e-mail headers with the user's name, e-mail address and character encoding $headers = "From: " . $form_data['your_name'] . " <" . $form_data['email'] . ">\n"; $headers .= "Content-Type: text/plain; charset=UTF-8\n"; $headers .= "Content-Transfer-Encoding: 8bit\n"; // send the e-mail with the shortcode attribute named 'email' and the POSTed data wp_mail( $email, $email_subject, $email_message, $headers ); // and set the result text to the shortcode attribute named 'success' $result = $success; // ...and switch the $sent variable to TRUE $sent = true; } }The Contact Form
This part is, of course, as important as the previous part. After all, how can the previous code send an e-mail if there’s no contact form? :)
// if there's no $result text (meaning there's no error or success, meaning the user just opened the page and did nothing) there's no need to show the $info variable if ( $result != "" ) { $info = '<div class="info">' . $result . '</div>'; } // anyways, let's build the form! (remember that we're using shortcode attributes as variables with their names) $email_form = '<form class="contact-form" method="post" action="' . get_permalink() . '"> <div> <label for="cf_name">' . $label_name . ':</label> <input type="text" name="your_name" id="cf_name" size="50" maxlength="50" value="' . $form_data['your_name'] . '" /> </div> <div> <label for="cf_email">' . $label_email . ':</label> <input type="text" name="email" id="cf_email" size="50" maxlength="50" value="' . $form_data['email'] . '" /> </div> <div> <label for="cf_subject">' . $label_subject . ':</label> <input type="text" name="subject" id="cf_subject" size="50" maxlength="50" value="' . $subject . $form_data['subject'] . '" /> </div> <div> <label for="cf_message">' . $label_message . ':</label> <textarea name="message" id="cf_message" cols="50" rows="15">' . $form_data['message'] . '</textarea> </div> <div> <input type="submit" value="' . $label_submit . '" name="send" id="cf_send" /> </div> </form>';Tip: If you looked carefully at the HTML code of the contact form, you probably saw the extra $subject variable. Remember the shortcode attribute ‘subject’ with no default value? This means that you can use the shortcode like this, if you want to set a default subject: [contact subject="Job application"]
The return of the Shortcode
This last bit is pretty simple: Show the success message if the e-mail is sent, or the e-mail form and the error message (if there is one). Here’s the code:
if ( $sent == true ) { return $info; } else { return $info . $email_form; }We’re not showing the form again if the e-mail is sent, but if you want to show it anyways, you could use this simple line instead:
return $info . $email_form;The CSS
Of course, the code by itself wouldn’t look great. With some make-up, CSS, we can make our form prettier. Add these lines of CSS code into your style.css file of your theme:
.contact-form label, .contact-form input, .contact-form textarea { display: block; margin: 10px 0; } .contact-form label { font-size: larger; } .contact-form input { padding: 5px; } #cf_message { width: 90%; padding: 10px; } #cf_send { padding: 5px 10px; }If you did everything right, you will see something similar to the image below:
Congratulations, you just built your own contact form shortcode!
Conclusion
This simple contact form is adequate for most websites but if you want to add more fields to it, you just need to edit the form and add the $form_data['name_of_the_new_field'] variables into the $email_message variable (and maybe add the field’s name to the $required_fields array.
If you have any ideas on how to improve this code or show your website pages where you used it, please share your comment with us below!
By default, when a visitor search on your site using WordPress built-in search engine, it search through all post types. But on some websites, you may want to be able to search only within a specific post type. Here’s a handy code snippet to do it.
Let’s say that you’re a launching new product, giving away freebies or organizing an event. How do you deliver the message to your readers? Popular choice is to display a modal dialog in a lightbox, thus forcing the user to take notice. But there’s another, less obtrusive, yet still effective way, to get a user’s attention. In this tutorial we’ll be creating a plugin that displays custom site-wide announcements across the top of the page, with the ability to schedule messages to appear between two given dates.
Step 1 Creating the Plugin
Our first step is to create a plugin folder and the main plugin file, with properly formatted header. Head on to wp-content/plugins and create a folder named simple-announcements. Now open your favorite editor and create a new php file called simple-announcements.php – the main file for our plugin. All the following PHP code should be placed in this file. Next, add the following code at the very beginning of the file:
<?php /* Plugin Name: Simple Announcements Plugin URI: http://wp.tutsplus.com Description: A simple announcements plugin. Version: 1.0 Author: Aleksandra Laczek Author URI: http://webtuts.pl */ ?>It’s a standard plugin header, and you could extend it with other information if you like (read more in Plugins section of the WordPress Codex).
Once it’s done, go to Plugins section of WordPress administration area, and you should see the plugin, ready to be activated.
Before we move any further, we will define a constant to store our plugin path. This constant will be used throughout the plugin, and will make our job a little easier. Drop this line of code into simple-announcements.php, below the header.
<?php define('SIMPLE_ANNOUNCEMENTS_PATH', plugin_dir_url( __FILE__ )); ?>Step 2 Creating Custom Post Type
To make it easy to edit and add new announcements, we’re going to create a dedicated custom post type called Announcements.
<?php function sap_register_announcements() { $labels = array( 'name' => _x( 'Announcements', 'post type general name' ), 'singular_name' => _x( 'Announcement', 'post type singular name' ), 'add_new' => _x( 'Add New', 'Announcement' ), 'add_new_item' => __( 'Add New Announcement' ), 'edit_item' => __( 'Edit Announcement' ), 'new_item' => __( 'New Announcement' ), 'view_item' => __( 'View Announcement' ), 'search_items' => __( 'Search Announcements' ), 'not_found' => __( 'No Announcements found' ), 'not_found_in_trash' => __( 'No Announcements found in Trash' ), 'parent_item_colon' => '' ); $args = array( 'labels' => $labels, 'singular_label' => __('Announcement', 'simple-announcements'), 'public' => true, 'capability_type' => 'post', 'rewrite' => false, 'supports' => array('title', 'editor'), ); register_post_type('announcements', $args); } add_action('init', 'sap_register_announcements'); ?>Now head to the administration area. There should be a new item in the menu, just below Comments.
Step 3 Creating Custom Meta Boxes
Announcements are rather simple, and all we really need is the post edit section to input our message. But to be able to schedule announcements, we’ll need two additional fields to input a start and end date. For this purpose we’re going to create a meta box and put our fields inside (we could also use custom fields instead).
Adding Meta Box
<?php function sap_add_metabox() { add_meta_box( 'sap_metabox_id', 'Scheduling', 'sap_metabox', 'announcements', 'side', 'high' ); } add_action( 'add_meta_boxes', 'sap_add_metabox' ); ?>Wptuts+ has a great step by step tutorial on Custom Meta Boxes.
This piece of code adds a meta box named ‘Schedule‘ to the right column on the Announcements post edit screen. You can read more about the add_meta_box function and its parameters in the WordPress Codex.
I just want you to take notice of the third parameter – sap_metabox. It’s the name of callback function that renders HTML for the meta box content. We’ll be writing that function in a moment.
Adding the Fields
We’re going to add two fields to store the start and end date of the announcements.
<?php function sap_metabox( $post ) { $values = get_post_custom( $post->ID ); $start_date = isset( $values['sap_start_date'] ) ? esc_attr( $values['sap_start_date'][0] ) : ''; $end_date = isset( $values['sap_end_date'] ) ? esc_attr( $values['sap_end_date'][0] ) : ''; wp_nonce_field( 'sap_metabox_nonce', 'metabox_nonce' ); ?> <p> <label for="start_date">Start date</label> <input type="text" name="sap_start_date" id="sap_start_date" value="<?php echo $start_date; ?>" /> </p> <p> <label for="end_date">End date</label> <input type="text" name="sap_end_date" id="sap_end_date" value="<?php echo $end_date; ?>" /> </p> <?php } ?>First thing we do here, is get all current custom fields’ values. Then we create a nonce field, that will be needed for validation later.
Finally we’re printing out HTML code for the two input fields, with values that we determined at the beginning.
Step 4 Registering JavaScript and CSS Files
We just created two custom meta boxes to input the dates for scheduling announcements. To make this task easier, we’re going to add a JavaScript date picker. For this purpose I decided to use jQuery Datepicker. The script is actually bundled in with WordPress, so we just need to enqueue it, but for the CSS we need a jQuery UI theme. As we’ve mentioned before Helen Hou-Sandi, core WordPress contributor, has worked on two jQuery UI themes which complement WordPress. We’ll use the ‘fresh’ theme which matches the default WordPress admin, so download the jquery-ui-fresh.css file from her GitHub repository, and save it to your simple-announcements/js folder.
We need one more JavaScript file to store all custom JavaScript code related to front and back end. We will call this file announcements.js. For now just create an empty JavaScript file and put it in the js folder, we’ll get to writing custom code later.
After this, the plugin folder should be organized as shown below.
Now it’s time to enqueue scripts and stylesheets, so that we can actually use them.
<?php function sap_backend_scripts($hook) { global $post; if( ( !isset($post) || $post->post_type != 'announcements' )) return; wp_enqueue_style( 'jquery-ui-fresh', SIMPLE_ANNOUNCEMENTS_PATH . 'css/jquery-ui-fresh.css'); wp_enqueue_script( 'announcements', SIMPLE_ANNOUNCEMENTS_PATH . 'js/announcements.js', array( 'jquery', 'jquery-ui-datepicker' ) ); } add_action( 'admin_enqueue_scripts', 'sap_backend_scripts' ); ?>Our script will be used only in admin section, and what is more, only while adding or editing Announcements Post Type. Therefore we should make sure, that any scripts and styles are loaded only when needed.
Step 5 Adding Datepicker to Date Fields
In order to use the datepicker, we need to add some custom JavaScript code to assign date pickers to input fields. This code goes into the announcements.js file created in the previous step.
jQuery(document).ready(function($) { if($('#sap_start_date').length) { $(function() { var pickerOpts = { dateFormat: "yy-mm-dd" }; jQuery("#sap_start_date").datepicker(pickerOpts); jQuery("#sap_end_date").datepicker(pickerOpts); }); } }Notice the dateFormat option. We need to separate elements of the date with a ‘-’ character. This will be important later, during validation.
More documentation on how to use Datepicker can be found in jQuery UI website.
To see the datepicker in action, go ahead and add a new Announcement. Try to add a start or end date and you’ll notice the datepicker calendar pop up.
Step 6 Saving Meta Box Data
Now that we’ve got all the needed fields, we can proceed to saving the data from the meta box to the database. We do that by calling the sap_metabox_save function on the save_post action.
<?php function sap_metabox_save( $post_id ) { if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return $post_id; if( !isset( $_POST['metabox_nonce'] ) || !wp_verify_nonce( $_POST['metabox_nonce'], 'sap_metabox_nonce' ) ) return $post_id; if( !current_user_can( 'edit_post' ) ) return $post_id; // Make sure data is set if( isset( $_POST['sap_start_date'] ) ) { $valid = 0; $old_value = get_post_meta($post_id, 'sap_start_date', true); if ( $_POST['sap_start_date'] != '' ) { $date = $_POST['sap_start_date']; $date = explode( '-', (string) $date ); $valid = checkdate($date[1],$date[2],$date[0]); } if ($valid) update_post_meta( $post_id, 'sap_start_date', $_POST['sap_start_date'] ); elseif (!$valid && $old_value) update_post_meta( $post_id, 'sap_start_date', $old_value ); else update_post_meta( $post_id, 'sap_start_date', ''); } if ( isset( $_POST['sap_end_date'] ) ) { if( $_POST['sap_start_date'] != '' ) { $old_value = get_post_meta($post_id, 'sap_end_date', true); $date = $_POST['sap_end_date']; $date = explode( '-', (string) $date ); $valid = checkdate($date[1],$date[2],$date[0]); } if($valid) update_post_meta( $post_id, 'sap_end_date', $_POST['sap_end_date'] ); elseif (!$valid && $old_value) update_post_meta( $post_id, 'sap_end_date', $old_value ); else update_post_meta( $post_id, 'sap_end_date', ''); } } add_action( 'save_post', 'sap_metabox_save' ); ?>This is a fairly standard way of saving meta box data. First, we check that:
- the post is not being auto saved,
- the nonce is present and valid,
- current user can actually edit the post.
After that we proceed with data validation, and finally save both dates to the database.
Step 7 Displaying Announcements
It’s time to display our announcement! It’ll be a two step process – first we need to create a function that selects relevant announcements using WP_Query and creates HTML markup, and then we’ll write some JavaScript and CSS to style the output.
Display Function
<?php function sap_filter_where( $where = '' ) { // ...where dates are blank $where .= " OR (mt1.meta_key = 'sap_start_date' AND CAST(mt1.meta_value AS CHAR) = '') OR (mt2.meta_key = 'sap_end_date' AND CAST(mt2.meta_value AS CHAR) = '')"; return $where; } function sap_display_announcement() { global $wpdb; $today = date('Y-m-d'); $args = array( 'post_type' => 'announcements', 'posts_per_page' => 0, 'meta_key' => 'sap_end_date', 'orderby' => 'meta_value_num', 'order' => 'ASC', 'meta_query' => array( array( 'key' => 'sap_start_date', 'value' => $today, 'compare' => '<=', ), array( 'key' => 'sap_end_date', 'value' => $today, 'compare' => '>=', ) ) ); // Add a filter to do complex 'where' clauses... add_filter( 'posts_where', 'sap_filter_where' ); $query = new WP_Query( $args ); // Take the filter away again so this doesn't apply to all queries. remove_filter( 'posts_where', 'sap_filter_where' ); $announcements = $query->posts; if($announcements) : ?> <div id="announcements" class="hidden"> <div class="wrapper"> <a class="close" href="#" id="close"><?php _e('x', 'simple-announcements'); ?></a> <div class="sap_message"> <?php foreach ($announcements as $announcement) { ?> <?php echo do_shortcode(wpautop(($announcement->post_content))); ?> <?php } ?> </div> </div> </div> <?php endif; } add_action('wp_footer', 'sap_display_announcement'); ?>The key is to select the right announcements from the database, based on the start and end date. We need only those which start before, and end after, the current date. Also, since we didn’t make the start and end date fields mandatory, we should include announcements without a scheduled date.
Start and end date are saved in the postmeta table, assigned to a specific post via the post_id column. We use a meta_query with WP_Query to fetch the right posts.
Finally, we loop through all selected announcements with simple foreach statement and display them with custom HTML markup.
Frontend JavaScript and CSS
Right now you should be able to see the announcements displayed on the home page, but you’ll notice a few problems:
- announcements are at the bottom of the page
- it’s impossible to close them
- they lack styling
Taking care of those issues will require writing some custom JavaScript code. But before we get to that, we need two more external JavaScript plugins:
- jQuery Cookie – we don’t need the whole package, just the jquery.cookie.js file
- jQuery Cycle – we’ll be using the Lite version – jquery.cycle.min.js.
Copy both files to simple-announcements/js folder. Now, remember how we loaded JavaScript in admin to show the datepicker? It’s time to add some scripts and styles to the front end. Don’t worry about the announcements.css, we’ll create it shortly.
<?php function sap_frontend_scripts() { wp_enqueue_style( 'announcements-style', SIMPLE_ANNOUNCEMENTS_PATH . 'css/announcements.css'); wp_enqueue_script( 'announcements', SIMPLE_ANNOUNCEMENTS_PATH . 'js/announcements.js', array( 'jquery' ) ); wp_enqueue_script( 'cookies', SIMPLE_ANNOUNCEMENTS_PATH . 'js/jquery.cookie.js', array( 'jquery' ) ); wp_enqueue_script( 'cycle', SIMPLE_ANNOUNCEMENTS_PATH . 'js/jquery.cycle.lite.js', array( 'jquery' ) ); } add_action('wp_enqueue_scripts', 'sap_frontend_scripts'); ?>Now that we have all the necessary tools we can write the final piece of JavaScript. This code goes in announcements.js, below scripts added in step 5, inside the main jQuery(document).ready() function.
if($('#announcements').length) { if($.cookie('sap_active') == 'false') { $("#announcements").hide(); }; $("#close").click(function() { $("#announcements").slideUp("normal"); $.cookie('sap_active', 'false', { expires: 2, path: '/'}); return false; }); $("body").prepend($("#announcements")); $('#announcements .sap_message').cycle('fade'); }Let’s break down the code.
The Close Button
We don’t want to annoy our visitors, that’s why we added a closing button to the announcement. But right now it doesn’t do anything. With a little JavaScript we’re going to hide the announcement on the click event, with a nice slide effect. To make sure that the announcement doesn’t pop up when a user visits us next time, we’re creating a cookie that will expire in two days (that’s what we needed the jQuery Cookie plugin for).
if($.cookie('sap_active') == 'false') { $("#announcements").hide(); }; $("#close").click(function() { $("#announcements").slideUp("normal"); $.cookie('sap_active', 'false', { expires: 2, path: '/'}); return false; });First thing we need to do, is to check if our cookie named ‘sap_active‘ is present. If it is and its value equals to ‘false‘, we simply hide the whole announcements bar. The cookie is created when the user hits the close button.
Moving Announcement to Top of the Page
$("body").prepend($("#announcements"));Next we move the announcements bar to top of the page. To display the announcement bar, we hooked into wp_footer, since themes are required to implement it. wp_footer is a hook that is fired right before the closing </body> tag, which means that our announcement will be appended to the end of the document (that’s why it’s displayed at the bottom). Here we’re using jQuery to display it at the very top of the page, at the same time pushing down the content.
Cycle Through Announcements
$('#announcements').cycle('fade');Remember when I said that it’s possible to have more than one announcement active on any given date? If that happens, we don’t want to display all of them at once, but rather cycle through them. That’s exactly what this last piece of code does.
Step 8 Styling the Announcement Bar
Right now our announcements bar doesn’t look like much. Let’s add some CSS rules and style it up a bit. All CSS rules should be placed in the announcements.css file in the simple-announcements/css folder.
#announcements {display: hidden; text-align: center; background: #FF7F00; height: 35px;} #announcements .wrapper {width: 1000px; text-align: left; margin: 0 auto; padding: 5px 0;} #announcements .wrapper .close {float: right; font-weight: bold; padding: 0 5px;} #announcements .wrapper .close:hover{background: #000; border-radius: 5px;} #announcements .wrapper .sap_message p{margin: 0;color: #fff;}With these few rules we changed the background color of the announcement bar to orange, positioned the close button to the right and centered announcements on the page. What we’ve done here is really basic, you could certainly go further, and play with the background or add a shadow, change the font etc.
That’s it! Let’s take a look at the end result.
Conclusion
Announcements bar is simple yet effective way to communicate with visitors. You could definitely do more in terms of styling and functionality, but I believe this tutorial should be a good starting point. Feel free to use this code as a canvas for your own custom plugins, and let us know about your ideas in comments below.
Paste the following code in your functions.php file, save it, and you're done.
function ds_print_jquery_in_footer( &$scripts) { if ( ! is_admin() ) $scripts->add_data( 'jquery', 'group', 1 ); } add_action( 'wp_default_scripts', 'ds_print_jquery_in_footer' );Credit: Dominik Schilling.
Developing a WordPress theme for a real estate website can be a long process. In this article, I will explain the process of creating a website for a real estate agency and explain methods and best practices that are not only standard to WordPress, but also to make it easier to develop such a site.
What This Article Is About
This article will show a simple HTML 5 layout with some CSS 3. It will also include the structure as created by WordPress with a combination of WordPress functions and additional PHP code. We will also include a top navigation menu from WordPress.
Planning the Requirements of the Real Estate Site
We first need to plan the exact WordPress functionality and features that we will be using in addition to the HTML 5 and CSS structure that we will be creating.
Planning the Web Pages and WordPress Code That We Will Be Creating
Since our theme will revolve around a real estate agency, we will be performing the following actions:
- Create a home page that will list news from the agency
- A sidebar for listings as well as the featured salesperson of the month
- A top navigation menu to display some links to other pages.
- A footer that displays the current date and other legal information about the real estate agency.
- A simple web page to display full content for listings, news, and salespeople
Using the WordPress Features to Create Our Various Web Pages
The Home Page – Our home page will be a simple HTML 5 web page with a main column and a sidebar. Our main column will contain news about the agency, maintained by the WordPress administrator entering posts with a category of “news”. The sidebar will include the titles of the 10 newest listings with links to the full listing. Also, we will include one salesperson of the month with a bio and a photo.
To have listings and the featured salesperson show up, the WordPress administrator will add all listing posts to a category called “listings”. Although all salespeople posts will be added to a category called “salesperson”, the WordPress administrator will add a tag called “featured” to the one salesperson who will be featured.
Our listings page will contain five of the most recent listings with a link displayed as the title.
Step 1: Preparing the WordPress Folder Structure
Add a new folder to your wp-content/themes. Call it “realestate”. Create five blank PHP files which will conform to the WordPress standard for all themes. The files will contain these titles:
- index.php – Since index.php is the main file for all PHP sites, this file will be the file that always gets called when someone visits your real estate website and it will call the other files using standard WordPress theme functions.
- style.css – WordPress themes use normal CSS to format your HTML layout.
- header.php – All WordPress themes have headers and this is named exactly that.
- sidebar.php – Since we want to have listings and the salesperson of the month, we need a sidebar and this file will list the information here.
- footer.php – All standard WordPress themes have a footer, so all of your code will go into this file.
- single.php – To display full posts of single posts for listings, news, and salespeople.
The HTML will be broken down into these files and I will go through each one with the corresponding HTML 5 and PHP by the following steps:
Step 2: Creating Our Header With header.php
<!DOCTYPE html> <html> <head> <title> ABC Real Estate Agency </title> <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>"> </head> <body> <div id="wrapper"> <header> <div id="header"> <nav> <?php if ( function_exists( 'register_nav_menu' ) ) { register_nav_menu( 'main-menu', 'Main Menu' ); } wp_nav_menu(); ?> </nav> <h1> Welcome to ABC Real Estate </h1> </div> </header>Explanation of header.php
Here, I am simply creating the opening HTML and I use standard CSS attributes in my HTML including wrapper and header.
Some notes about header.php:
- I start the header with <!DOCTYPE html> which tells the web browser that I want it to display the web page with HTML 5.
- I wrap my entire header in the <header> tag which is new in HTML 5.
- I have added the standard <link> tag to call my style.css, but I specified bloginfo('stylesheet_url') instead of saying style.css. WordPress knows how to use this code to load style.css automatically.
- I started a <DIV> for wrapper, but I do not close it. I will close it later in my footer.php file.
I use the following code:
if ( function_exists( 'register_nav_menu' ) ) { register_nav_menu( 'main-menu', 'Main Menu' ); } wp_nav_menu();To create and display the navigation menu and in the WordPress administration screen, all of my links will be in the main menu link. Since I use “’Main Menu” as the second parameter in my register_nav_menu() function, it will display in the WordPress administration screen for the admin to enter links.
- I also use the <nav> tag which is new to HTML 5 and describes the code as a navigation bar. Best practices dictate that this tag should be used only once in your HTML 5 document, although, it will not break the website if you need to use it more than once.
Step 3: Create the index.php, the File That Will Be Called When the Theme Loads
<?php get_header(); ?> <div id="main"> <div id="content"> <h1> News From ABC Agency </h1> <?php query_posts('category_name=news&showposts=10'); ?> <?php if (have_posts()) : while (have_posts()) : the_post(); ?> <h1><?php the_title(); ?></h1> <h4>Posted on <?php the_time('F jS, Y') ?></h4> <p><? php the_content(); ?></p> <hr> <?php endwhile; else: ?> <p><? php _e(‘No news has been reported at this time’); ?></p> <?php endif; ?> </div> <?php get_sidebar(); ?> </div> <div style=” clear: both; ”></div> <?php get_footer(); ?>Explanation of My index.php Code
This is the entire HTML 5 that I am using in my theme. Since I want news to appear, we have to take into consideration that news may not be available. Otherwise, we can mislead people to see an unfinished website and that is not professional.
My first line: <?php get_header(); ?>
This executes my code from header.php.
The next three lines are standard HTML 5 and are simply <div> tags that display HTML using ID attributes that we can call with our style.css file.
The next line: <?php query_posts('category_name=news&showposts=10'); ?>
This is a very important line. It tells the theme that we want to show posts that only have a category of “news”. Without this line, our theme will print every post including listings and salespeople and we do not want that in this place. We only want news. If the real estate agency has new listings, then the WordPress administrator can list it as news, but the actual listings will not be published here as we save that for the sidebar.
The next line: <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
This is the line that creates a loop of our posts and since the previous line is using the query_posts function, only posts with a category of news will display in this loop.
One special line: <?php get_sidebar(); ?>
This line tells our WordPress theme to print the entire sidebar and will pull all of the HTML and PHP code from sidebar.php.
Another special line: <?php get_footer(); ?>
This line tells our WordPress theme to print the entire footer and will display all of the HTML and PHP code from footer.php.
Step 4: Our Sidebar Code in sidebar.php
<aside> <div id="sidebar"> <h2> Latest Listings </h2> <?php query_posts('category_name=listings&showposts=5'); ?> <?php while (have_posts()) : the_post(); ?> <h3><?php the_title(); ?></h3> <?php endwhile;?> query_posts( ' cat=1↦tag=apples&orderby=date&order=ASC ' ); <h2> Salesperson Of The Month </h2> <?php query_posts('category_name=salesperson&tag=featured&showposts=1'); ?> <?php while (have_posts()) : the_post(); ?> <h3><?php the_title(); ?></h3> <p><? php the_content(); ?></p> <?php endwhile;?> </div> </aside>Explanation of My sidebar.php Code
I start off with the <aside> tag which is new in HTML 5 and it tells the web browser that this is all sidebar text or the content is beside the main the content intended for the website visitor.
Next I add the HTML: <div id="sidebar"> which tells WordPress to format this <div> tag according to the CSS in #sidebar in my style.css file. The last line closes this <div>.
The next thing I want to do is display my latest listings and I start it off with the HTML: <h2> Latest Listings </h2>
To show the listings: I enter the line <?php query_posts('category_name=listings∓orderby=date&order=DESC&showposts=5'); ?>
This line of code will display any posts that have the added to the category “listings” and will display them in descending order, so every time I add a new listing, it appears first in my list.
The next three lines will display the actual listing titles with links to their full pages.
Finally, I want my sidebar to display the salesperson of the month and I also use the WordPress query_posts() function. Since all of my salespeople have a category of “salesperson”, I use the code <?php query_posts('category_name=salesperson&tag=featured&showposts=1'); ?> to show one salesperson. Notice, that I also added a tag called “featured”. Since I have more than one salesperson in my agency, I want to display only the salesperson I feature and in the WordPress administration screen, I add a tag called “featured” to any salesperson that I want in this section, so the query_posts() parameter for “tag” matches it exactly. I also narrow my results to just one post (in case the WordPress administrator tagged more than one salesperson as a featured post).
Step 5: Creating My Footer Using footer.php
<footer> <div id="footer"> © <?php echo Date(‘Y’) ?> ABC Agency. All rights reserved. </div> </footer> </div> </body> </html>This is pretty simple. I have a <div> and a </div> tag to include all of my footer information. I wrap the entire footer in my <footer> tag which is new to HTML 5.
Also, my last 3 HTML tags close my wrapper <div> tab as well as my <html> and <body> tags. I also use the PHP Date function to print the current year. I will point out that most webmasters hard code the current year and that is a mistake and bad practice. The reason for this is that when the new year changes on January 1, the previous year is still displaying unless the webmaster was waiting until midnight on January 1 to manually change the year. To make matters worse, most webmasters forget to change the current year for several years making the website look unprofessional and behind in its updates. Using this simple PHP date function will save the headaches for both the webmaster as well as the website owner and update the year automatically allowing the webmaster to focus on other, more important tasks.
Step 6: Creating the Single Page for News, Listings, and Salespeople
<?php if (have_posts()) : while (have_posts()) : the_post(); ?> /* if have posts */ <div class="post" id="post-<?php the_ID(); ?>"> <div class="post-info"> <img src="<?php bloginfo('template_directory') ?>/images/authors/<?php the_author_ID()?>.jpg" alt="<?php the_author() ?>" alt="<?php the_author() ?>" title="<?php the_author() ?>" /> <em><?php the_time('F jS, Y') ?></em> <span class="post-tag"><?php the_tags('', ' . ', ''); ?></span> </div> <div class="entry"> <h2><?php the_title(); ?></h2> <?php the_content(); ?> /* load post content in full version */ </div>Here, I use simple HTML 5 to display the full post data when a hyperlink leads a website visitor to a post for listings, news, and salespeople.
Finally…
Step 6: Adding Your CSS With style.css
body { text-align: center; } h1,h2,h3 { color: #3399FF; font-family:arial; } h1 { font-size: 14pt ; } h2 { font-size: 12pt ; } h3 { font-size: 10pt ; } #wrapper { display: block; border: 2px #999 solid; border-radius: 10px; box-shadow: 3px 3px 7px #333; width:92%; margin: 0px auto 0px auto; } #header { border: 2px #999 solid; } #content { width: 75%; border: 2px #999 solid; float: left; } #sidebar { width: 23%; border: 2px #999 solid; float: right; } #footer { border: 2px #999 solid; } .title { font-size: 11pt; font-family: verdana; font-weight: bold; }This CSS will create a main section with a sidebar on the right. I use some of my favorite colors, but you can change this CSS to suit the needs of the website or the website owner.
Conclusion
In conclusion, this is the standard way to create a WordPress Real Estate theme. It includes all of the main features of any real estate website including salespeople and listings. I also demonstrate the standard parts of any WordPress theme including the header, posts loop, footer, sidebar as well as single page templates. Furthermore, since HTML 5 is becoming mainstream, it is time to develop all WordPress themes in HTML 5 and I included some of the most popular and important HTML 5 tags.
Let us know what you think in the comments below!
WordPress needs no introduction among designers and writers. It use to known as the synonym for blogging but now days it is used to create any type of website of any complexity. WordPress has reached phenomenally high usage rates. There are over 70 million publishers who use WordPress, making it a popular publishing platform. These days every other WordPress blogs look more or less similar, to stand uniquely, you need to tweak it using quality hacks.
You all must’ve known that the new version v3.3.1 is already arrived and most of you going to update (or already updated) your WordPress to v3.3.1 anyway. So, it’s a right time to implement some new hacks also.
Of Course, WordPress Codex is always the best place to learn about WordPress and its tweaks. But unfortunately, it’s too much for a simple WordPress user. This the only reason we compiled this fairly comprehensive list of the Quality WordPress Hacks to unleash the power of your favorite blogging engine.
One of the greatest things about blogging is the immediate feedback a blogger can get from his readers. Still it’s often possible that your readers don’t give you clear idea about their likes and dislikes. Unfortunately, there is no way to find out about visitors thinking about your blog. It’s always essential to play safe and give others what they like. This article focuses on organized collection of some of the Most Useful WordPress Hacks for your Admin Panel which will definitely make your blogging life easier.
You may be interested in the following related articles as well.
Feel free to join us and you are always welcome to share your thoughts that our readers may find helpful.
Don’t forget to and follow us on Twitter — for recent updates.
How to disable dragging of metaboxes in admin panel
If you want to disable the functionality of dragging of metaboxes within the admin area and dashboard so the meta boxes can’t be repositioned then you need to deactivate the JS for this function. Go to functions.php in your theme folder and add following code.
function disable_drag_metabox() { wp_deregister_script('postbox'); } add_action( 'admin_init', 'disable_drag_metabox' );
Show an urgent message in the WordPress admin panel
When applying changes to the theme or plugins, you might want to inform users that something important needs doing, or you want to inform other admins to not to perform any changes while you are working on specific file. Following steps shows you how to add a error or status message via adding some code to your theme’s functions.php.
Just change the string in line 14 to put the desired notification or error message.
function showMessage($message, $errormsg = false) { if ($errormsg) { echo '<div id="message" class="error">'; } else { echo '<div id="message" class="updated fade">'; } echo "<p><strong>$message</strong></p></div>"; } function showAdminMessages() { showMessage("Working on Theme's function.php, Do not touch it till further notice.", true); } add_action('admin_notices', 'showAdminMessages');
How to show admin bar only for admins
Adding the following code into your theme’s functions.php file will only allow admins to see the admin bar.
if (!current_user_can('manage_options')) { add_filter('show_admin_bar', '__return_false'); }
How to remove menu items from admin bar (on top)
This hack gives you flexibility to remove the menu items from the admin bar in top section of your WordPress admin area. Go to functions.php in your theme folder and add following code.
function wps_admin_bar() { global $wp_admin_bar; $wp_admin_bar->remove_menu('wp-logo'); $wp_admin_bar->remove_menu('about'); $wp_admin_bar->remove_menu('wporg'); $wp_admin_bar->remove_menu('documentation'); $wp_admin_bar->remove_menu('support-forums'); $wp_admin_bar->remove_menu('feedback'); $wp_admin_bar->remove_menu('view-site'); } add_action( 'wp_before_admin_bar_render', 'wps_admin_bar' );
Replace “Howdy, admin” in WordPress admin bar
Some people might find this silly but there are many who wants to replace the notification “Howdy, admin” from the admin bar of admin area. To do so, following code needs to be dropped into your theme’s functions.php file.
function replace_howdy( $wp_admin_bar ) { $my_account=$wp_admin_bar->get_node('my-account'); $newtitle = str_replace( 'Howdy,', 'Logged in as', $my_account->title ); $wp_admin_bar->add_node( array( 'id' => 'my-account', 'title' => $newtitle, ) ); } add_filter( 'admin_bar_menu', 'replace_howdy',25 );
Hide ‘help’ Tab from admin panel
I’ve never used the The ‘help’ tab in the top right corner of the WordPress admin area and this function is most of the time unnecessary for your clients too. With some simple CSS it’s possible to hide this tab.
Go to theme’s functions.php and add following code.
function hide_help() { echo '<style type="text/css"> #contextual-help-link-wrap { display: none !important; } </style>'; } add_action('admin_head', 'hide_help');
How to add new items to admin bar
Add following code to your theme’s functions.php and you can easily able to add new items to admin bar.
function wp_admin_bar_new_item() { global $wp_admin_bar; $wp_admin_bar->add_menu(array( 'id' => 'wp-admin-bar-new-item', 'title' => __('iShift Archive'), 'href' => 'http://www.instantshift.com/archive/' )); } add_action('wp_before_admin_bar_render', 'wp_admin_bar_new_item');
How to remove menu items from WordPress admin panel/dashboard
WordPress admin panel comes with a lot of options in the left side menu, but you can get rid of them easily if required. This hack gives you flexibility to remove the menu items from the admin panel.
just paste the following code in your theme’s functions.php file.
add_action( 'admin_menu', 'remove_links_menu' ); function remove_links_menu() { remove_menu_page('index.php'); // Dashboard remove_menu_page('edit.php'); // Posts remove_menu_page('upload.php'); // Media remove_menu_page('link-manager.php'); // Links remove_menu_page('edit.php?post_type=page'); // Pages remove_menu_page('edit-comments.php'); // Comments remove_menu_page('themes.php'); // Appearance remove_menu_page('plugins.php'); // Plugins remove_menu_page('users.php'); // Users remove_menu_page('tools.php'); // Tools remove_menu_page('options-general.php'); // Settings }
Remove the Editor submenu item from Appearance menu
Removing a editor submenu from the Appearance menu is a bit tricky as it doesn’t respond to the unset() function. Use following hack to remove it from Appearance menu.
function remove_editor_menu() { remove_action('admin_menu', '_add_themes_utility_last', 101); } add_action('_admin_menu', 'remove_editor_menu', 1);
Change WordPress version in admin footer
Adding this code in your theme’s functions.php will change the version string in the bottom-right of the WordPress admin pages.
function change_footer_version() { return 'Version 1.0.0'; } add_filter( 'update_footer', 'change_footer_version', 9999 );
Change footer text in WordPress admin panel
Adding this code in your theme’s functions.php will change the footer text to anything you like it to be. Just change the “My Custom footer text” string with your choice.
function remove_footer_admin () { echo 'My Custom footer text.'; } add_filter('admin_footer_text', 'remove_footer_admin');
How to display dashboard in a single column only
Adding this code to the functions.php of your WordPress theme will force the WordPress admin dashboard to display in a single column only.
function single_screen_columns( $columns ) { $columns['dashboard'] = 1; return $columns; } add_filter( 'screen_layout_columns', 'single_screen_columns' ); function single_screen_dashboard(){return 1;} add_filter( 'get_user_option_screen_layout_dashboard', 'single_screen_dashboard' );
How to disable browser upgrade notification/warning
Many of you may have noticed the browser upgrade notification / warning on your admin panel deshboard. If you simply want to get rid of these notification / warning then add following code in your theme’s functions.php file.
function disable_browser_upgrade_warning() { remove_meta_box( 'dashboard_browser_nag', 'dashboard', 'normal' ); } add_action( 'wp_dashboard_setup', 'disable_browser_upgrade_warning' );
How to add custom pointers in admin area
Many of you may have noticed pointers in your WordPress admin panel. Pointers are useful if you want to provide guidelines to your users about your theme or plugin within your admin area.
Adding following code in your theme’s functions.php file will allow you to add pointer within your admin area.
Don’t forget to put the desired label and message on line 8 & 9.
Also update the ID with jquery to assign the pointer in place of #menu-appearance in line 14. For example if you want your pointer’s tooltip to point towards media menu then use id #menu-media instead of #menu-appearance or in case of settings menu use id #menu-settings
add_action( 'admin_enqueue_scripts', 'my_admin_enqueue_scripts' ); function my_admin_enqueue_scripts() { wp_enqueue_style( 'wp-pointer' ); wp_enqueue_script( 'wp-pointer' ); add_action( 'admin_print_footer_scripts', 'my_admin_print_footer_scripts' ); } function my_admin_print_footer_scripts() { $pointer_content = '<h3>iShift | Notice</h3>'; $pointer_content .= '<p>Added new functions to Edit Post section and few more options for users (authors and subscribers only).</p>'; ?> <script type="text/javascript"> //<![CDATA[ jQuery(document).ready( function($) { $('#menu-appearance').pointer({ content: '<?php echo $pointer_content; ?>', position: 'top', close: function() { // Once the close button is hit } }).pointer('open'); }); //]]> </script> <?php }
Show the count of pingbacks & trackbacks within admin post columns
This hack simply adds a new column called counts within the admin post columns which display the total number of pingbacks and trackbacks for each post.
Go to functions.php in your theme folder and add following code.
function commentCount($type = 'comments'){ if($type == 'trackbacks'): $typeSql = 'comment_type = "trackback"'; $oneText = 'One :trackback'; $moreText = '% :trackbacks'; $noneText = 'No :trackbacks'; elseif($type == 'pingbacks'): $typeSql = 'comment_type = "pingback"'; $oneText = 'One :pingback'; $moreText = '% :pingbacks'; $noneText = 'No :pingbacks'; endif; global $wpdb; $result = $wpdb->get_var(' SELECT COUNT(comment_ID) FROM '.$wpdb->comments.' WHERE '.$typeSql.' AND comment_approved="1" AND comment_post_ID= '.get_the_ID() ); if($result == 0): echo str_replace('%', $result, $noneText); elseif($result == 1): echo str_replace('%', $result, $oneText); elseif($result > 1): echo str_replace('%', $result, $moreText); endif; } add_filter('manage_posts_columns', 'posts_columns_counts', 1); add_action('manage_posts_custom_column', 'posts_custom_columns_counts', 1, 2); function posts_columns_counts($defaults){ $defaults['wps_post_counts'] = __('Counts'); return $defaults; } function posts_custom_columns_counts($column_name, $id){ if($column_name === 'wps_post_counts'){ commentCount('trackbacks'); echo "<br />"; commentCount('pingbacks'); } }
How to show post attachment count in admin column
Adding this code to the functions.php of your WordPress theme will display the post attachment count in a custom admin column.
add_filter('manage_posts_columns', 'posts_columns_attachment_count', 5); add_action('manage_posts_custom_column', 'posts_custom_columns_attachment_count', 5, 2); function posts_columns_attachment_count($defaults){ $defaults['wps_post_attachments'] = __('Att'); return $defaults; } function posts_custom_columns_attachment_count($column_name, $id){ if($column_name === 'wps_post_attachments'){ $attachments = get_children(array('post_parent'=>$id)); $count = count($attachments); if($count !=0){echo $count;} } }
How to add featured image thumbnail to WordPress admin columns
The admin pages listing the site’s posts and pages come with various text columns like title, tags, categories, author and so on. In order to see what the featured images are, you have to visit each post or page individually. Using this hack you can add a column with a reasonably sized thumbnail copy of the featured image. Please note that this only works for themes that support featured images.
Just add following code to your theme’s functions.php file.
// Add the posts and pages columns filter. They can both use the same function. add_filter('manage_posts_columns', 'tcb_add_post_thumbnail_column', 5); add_filter('manage_pages_columns', 'tcb_add_post_thumbnail_column', 5); // Add the column function tcb_add_post_thumbnail_column($cols){ $cols['tcb_post_thumb'] = __('Featured'); return $cols; } // Hook into the posts an pages column managing. Sharing function callback again. add_action('manage_posts_custom_column', 'tcb_display_post_thumbnail_column', 5, 2); add_action('manage_pages_custom_column', 'tcb_display_post_thumbnail_column', 5, 2); // Grab featured-thumbnail size post thumbnail and display it. function tcb_display_post_thumbnail_column($col, $id){ switch($col){ case 'tcb_post_thumb': if( function_exists('the_post_thumbnail') ) echo the_post_thumbnail( 'admin-list-thumb' ); else echo 'Not supported in theme'; break; } }
How to hide admin post meta-boxes
On may places you need to provide clean or simplify WordPress admin interface for your clients. Following hack provides you facility to hide meta boxes of post section in Admin area.
Add this code to your WordPress theme’s functions.php file.
add_action( 'admin_menu', 'remove_meta_boxes' ); function remove_meta_boxes() { remove_meta_box( 'submitdiv', 'post', 'normal' ); // Publish meta box remove_meta_box( 'commentsdiv', 'post', 'normal' ); // Comments meta box remove_meta_box( 'revisionsdiv', 'post', 'normal' ); // Revisions meta box remove_meta_box( 'authordiv', 'post', 'normal' ); // Author meta box remove_meta_box( 'slugdiv', 'post', 'normal' ); // Slug meta box remove_meta_box( 'tagsdiv-post_tag', 'post', 'side' ); // Post tags meta box remove_meta_box( 'categorydiv', 'post', 'side' ); // Category meta box remove_meta_box( 'postexcerpt', 'post', 'normal' ); // Excerpt meta box remove_meta_box( 'formatdiv', 'post', 'normal' ); // Post format meta box remove_meta_box( 'trackbacksdiv', 'post', 'normal' ); // Trackbacks meta box remove_meta_box( 'postcustom', 'post', 'normal' ); // Custom fields meta box remove_meta_box( 'commentstatusdiv', 'post', 'normal' ); // Comment status meta box remove_meta_box( 'postimagediv', 'post', 'side' ); // Featured image meta box remove_meta_box( 'pageparentdiv', 'page', 'side' ); // Page attributes meta box }
Hide admin color scheme options from user profile
Adding this code to your theme’s functions.php will hide the admin color scheme from the user profile page in admin section.
function admin_color_scheme() { global $_wp_admin_css_colors; $_wp_admin_css_colors = 0; } add_action('admin_head', 'admin_color_scheme');
How to change WordPress admin and login page logo
This one’s an old trick, but a still and good one. You can change the logo for the login page and the WordPress Admin area pages.
To change the login page logo then simply add following code to your theme’s functions.php file. Don’t forget to change the logo location in line 3.
function my_custom_login_logo() { echo '<style type="text/css"> h1 a { background-image:url('.get_bloginfo('template_url').'/images/login_page_logo.png) !important; } </style>'; } add_action('login_head', 'my_custom_login_logo');To change the WordPress Admin area logo (the one which located in the top left side of your Admin panel) then simply add following code to your theme’s functions.php file. Again, Don’t forget to change the logo location in line 3.
function custom_logo() { echo '<style type="text/css"> #header-logo { background-image: url('.get_bloginfo('template_directory').'/images/admin_page_logo.png) !important; } </style>'; } add_action('admin_head', 'custom_logo');
Change WordPress default FROM email address
Adding this code into your theme’s functions.php file will change the WordPress default FROM email address, as by default, you can’t modify the FROM email adress. Don’t forget to put the desired email address on line 5 (in place of ‘admin@yourdomain.com’) and desired name on line 8 (in place of ‘Your Blog Name’).
add_filter('wp_mail_from', 'new_mail_from'); add_filter('wp_mail_from_name', 'new_mail_from_name'); function new_mail_from($old) { return 'admin@yourdomain.com'; } function new_mail_from_name($old) { return 'Your Blog Name'; }Find Something Missing?
Feel free to share any hack that you think would be a great addition in this article and that has not been listed already.
Recently this problem troubled me a lot. All time I try to activate my plugin, I get the following error:
The plugin generated 1186 characters of unexpected output during activation. If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.
After several attempts of debugging, I failed to understand why it is coming. The mysterious thing was that, this error was not coming for all WordPress installations!
Today, I decided to read the core files those are responsible for activating and/or deactivating the plugins. When I was reading wp-admin/includes/plugin.php, I saw a action hook ‘activated_plugin’ is available just before throwing the error. I believed, if I monitor what is happening here, I can know the reason of the error. So I wrote a small function to save the errors like:
add_action('activated_plugin','save_error'); function save_error(){ update_option('plugin_error', ob_get_contents()); }Then, I tried re-activating my plugin and I believed the error is saved in the wordpress option table. Now I need to see what happened. In my plugin page, I put these codes:
echo get_option('plugin_error');Then what I found what is causing the error. It was holding the what you see on the image.
It was like bolt to me. Why the hell was it coming! Then I again looking at my source and I saw I have included a wrong file.
For using dbDelta we have to include the file in following way:
require_once ABSPATH.'wp-admin/includes/upgrade.php';but I included a wrong file by:
require_once ABSPATH.'wp-admin/upgrade.php';As the filename was same, I confused with path and included wrong and it taken me several days to solve it.
However, I have solved it. I believe, if you ever face any such problems with your plugin, you can find the output texts using the above methods. If you have better methods, please share with me. I would simply love to know.
No related posts.
Backing Up Your Database
Languages: English • 日本語 • Português do Brasil • Русский • ไทย • 中文(简体) • (Add your language)
It is strongly recommended that you backup your database at regular intervals and before an upgrade.
Restoring your database from backup is then possible if something goes wrong.
Backup using cPanel X
cPanel is a popular control panel used by many web host. The backup feature can be used to backup your MySql database. Do not generate a full backup, as these are strictly for archival purposes and cannot be restored via cPanel. Look for 'Download a MySQL Database Backup' and click the name of the database. A *.gz file will be downloaded to your local drive.
There is no need to unzip this file to restore it. Using the same cPanel program, browse to the gz file and upload it. Once the upload is complete, the bottom of the browser will indicate dump complete. If you are uploading to a new host, you will need to recreate the database user along with the matching password. If you change the password, make the corresponding change in the wp-config.php file.
Using phpMyAdmin
phpMyAdmin is the name of the program used to manipulate your database.
Information below has been tried and tested using phpMyAdmin versions 2.5.3, 2.5.7-pl1, and 2.6.1-pl3 running on Unix.
Detailed options are listed below, though in most cases you will be fine with the default export options.
Backup Process with phpMyAdmin
- Log into phpMyAdmin on your server
- From the main login screen, select 'Databases'
(You may not need to do this step)- Now click the name of your database - or your WordPress database if you have several databases.
(Your screen may look slightly different, depending on the version.)- The next screen will show you all the tables inside your WordPress database.
Ignore those, and click the 'Export' tab on the top set of tabs.- Look at the left box at the top of the Export section. All the tables in the database you selected are in that box.
- If you have other programs that use the database, then choose only those tables that correspond to your WordPress install. They will be the ones with that start with "wp_" or whatever 'table_prefix' you specified in your 'wp-config.php' file.
- If you only have your WordPress blog installed, leave it as is (or click 'Select All' if you changed the selection)
- Ensure that the SQL radio button is selected.
- The SQL section
Tick the following boxes:
- 'Structure'
- 'Add DROP TABLE / VIEW / PROCEDURE / FUNCTION'
- 'Add IF NOT EXISTS'
- 'Add AUTO_INCREMENT' and
- 'Enclose table and field names with backquotes'
- The DATA section
It doesn't matter too much what you check here. So long as you check the DATA box itself, the Complete inserts and Extended Inserts are mostly cosmetic changes to the output style, though Extended Inserts can help if you are having issues with the file size.
- Tick the 'Save as file' option, and leave the template name as is.
- Now click 'Go' and you should be prompted for a file to download. Save the file to your computer.
Depending on the database size, this may take a few moments.- You have now backed up your database.
If you wanted, you could download a backup in each of the compression formats. Your choice. For example: None and "zipped":
Remember - you have NOT backed up the files and folders - such as images - but all your posts and comments are now safe.![]()
Using Straight MySQL Commands
phpMyAdmin cannot handle large databases so using straight MySQL code will help.
1. Change your directory to the directory you want to dump things to:
user@linux:~> cd files/blog2. Use mysqldump to dump all database tables. To dump only certain tables from the database, give their names at the place shown by (tablename tablename tablename), and omit the parentheses ( ) in any case. (For help, try: man mysqldump.):
user@linux:~/files/blog> mysqldump --add-drop-table -h mysqlhostserver -u mysqlusername -p databasename (tablename tablename tablename) | bzip2 -c > blog.bak.sql.bz2 Enter password: (enter your mysql password) user@linux~/files/blog>Example: mysqldump --add-drop-table -h db01.example.net -u dbocodex -p dbwp | bzip2 -c > blog.bak.sql.bz2 Enter password: my-password user@linux~/files/blog>The bzip2 -c after the | (pipe) means the backup is compressed on the fly, and the > blog.bak.sql.bz2 sends the bzip output to a file named blog.bak.sql.bz2. It does in one line the same thing that these two commands do:
mysqldump --add-drop-table -h db01.example.net -u dbocodex -p dbwp > blog.bak.sql bzip2 blog.bak.sqlDespite bzip2 being able to compress most files more effectively than the older compression algorithms (.Z, .zip, .gz), it is considerably slower (compression and decompression). If you have a large database to dump, gzip is a faster option to use.
mysqldump --add-drop-table -h db01.example.net -u dbocodex -p dbwp | gzip > blog.bak.sql.gzUsing MySQL Workbench
MySQL Workbench (formerly known as MySQL Administrator) is a program for performing administrative operations, such as configuring your MySQL server, monitoring its status and performance, starting and stopping it, managing users and connections, performing backups, restoring backups and a number of other administrative tasks.
You can perform most of those tasks using a command line interface such as that provided by mysqladmin or mysql, but MySQL Workbench is advantageous in the following respects:
- Its graphical user interface makes it more intuitive to use.
- It provides a better overview of the settings that are crucial for the performance, reliability, and security of your MySQL servers.
- It displays performance indicators graphically, thus making it easier to determine and tune server settings.
- It is available for Linux, Windows and MacOS X, and allows a remote client to backup the database across platforms. As long as you have access to the MySQL databases on the remote server, you can backup your data to wherever you have write access.
- There is no limit to the size of the database to be backed up as there is with phpMyAdmin.
Note: The instruction below was written for older version (MySQL Administrator).
Backing Up the Database
This assumes you have already installed MySQL Admin and set it up so that you can login to the MySQL Database Server either locally or remotely. Refer to the documentation that comes with the installation package of MySQL Admin for your platform for installation instructions.
- Open the MySQL Admin client and login as you had previously set up to do.
- From the icon menu on the left hand side of the client window select Backup.
- If you have not already created a Backup Project, do this now by clicking on the "New Project" button at the lower part of the window and type in a name for the Backup Project where prompted.
- Select one or more databases that you want to Backup (in the MySQL Admin client these are called a "Schema" (pl. "Schemata")). Add them to the Backup Content window on the right using the right-pointing arrow button.
- When you have selected the Schema(ta), you can save the Backup Project. Or you may simply choose to Backup Now using the button on the lower right of the window.
- A dialogue will come up asking you where to put the Backup. Enter the pathname or browse to the location using the dialogue.
- Assuming all is correct (and you have write permissions in the directory to which you are writing the Backup), the backup will complete shortly.
Restoring From a Backup
- Open the MySQL Admin client and login as you had previously set up to do.
- From the icon menu on the left hand side of the client window select Restore.
- Click the "Open Backup File" button on the lower right of the window.
- Type in or browse to the Schema(ta) backup file and select. Click "Open".
- The Target Schema(ta) will most likely be the "Original Location", or you may choose an alternate location using the drop-down menu.
- Click the "Start Restore" button on the lower right of the window. The database restore will commence.
MySQL GUI Tools
In addition to MySQL Workbench, there are many GUI tools that let you backup (export) your database.
Using WordPress Database Backup Plugin
Austin Matzko maintains a WordPress plugin originally created by Skippy called WordPress Database Backup (WP-DB-Backup). It was bundled with WordPress 2.0 but is no longer included with WordPress 2.1.
Installation
- Search "WP-DB-Backup" on Administration > Plugins Panel > Add New.
- Activate the plugin.
- The plugin will attempt to create a directory /wp-content/backup-*/ inside your WordPress directory. You may need to make /wp-content writable (at least temporarily) for it to create this directory.
Backing up
- Navigate to Administration > Tools > Backup Panel
- Select any tables, in addition to the core WordPress tables, that should be backed-up.
- Select the Backup Options; the backup can be saved on the server, downloaded, or emailed.
- Finally, click on the Backup button to actually perform the backup. You can also schedule regular backups.
Restoring the Data
The file created is a standard SQL file. If you want information about how to upload that file, look at Restoring Your Database From Backup.
Resources and Backup Plugins
For blogger who self-hosts the WordPress blog publishing system on a web hosting server with own registered domain name, sometimes, you may decide to reorganize the blog link URL to make it tidier or to reflect new focus or theme of the blog. If you decide to change the URL or link location of your WordPress blog due to changing of domain name (such as from http://www.old-domain.com/ to http://www.new-domain.com/) or the blog to another directory location (such as from http://www.domain.com/ to http://www.domain.com/blog/), there are some steps that should be done to ensure the proper migration and no breaking links.
The tricky part when moving WordPress blog to another location is that WordPress is using absolute path in URL link instead of relative path in URL link location when stores some parameters in database. Within blog posts’ contents itself, users may also use the old URLs when creating reference backlinks. All these values in the database will need to be changed when WordPress is moved. The following guide will show you which database fields that has references or values related to blog’s URLs that you want to modify. Note that this guide is not about how to move WordPress blog from one server or host to another new hosting service.Once the blog has been moved (all files copy over in case of moving location or server or new domain name properly propagated across Internet for new domain name), the first thing to change is to tell WordPress the new blog location (wp-config.php should be no changes, and .htaccess file should be also no changes. If for some reason mod_rewrite rules for friendly URLs no longer works, you can always regenerate the .htaccess file via WP Administration’s Update Permalinks page). This value can be changed via WordPress Options page, but if you no longer able to access to old blog URL, you have to modify the value via MySQL database.
Note: The guide uses SQL statements based on MySQL replace() function to modify the database. To run SQL queries, login to MySQL database that houses WordPress tables via phpMyAdmin or login to the DB server and run MySQL client as root.
To update WordPress options with the new blog location, use the following SQL command:
UPDATE wp_options SET option_value = replace(option_value, 'http://www.old-domain.com', 'http://www.new-domain.com') WHERE option_name = 'home' OR option_name = 'siteurl';
After that you will need to fix URLs of the WordPress posts and pages, which translated from post slug, and stored in database wp_posts table as guid field. The URL values in this field are stored as absolute URLs instead of relative URLs, so it needs to be changed with the following SQL query:
UPDATE wp_posts SET guid = replace(guid, 'http://www.old-domain.com','http://www.new-domain.com');
If you have linked internally within blog posts or pages with absolute URLs, these links will point to wrong locations after you move the blog location. Use the following SQL commands to fix all internal links to own blog in all WordPress posts and pages:
UPDATE wp_posts SET post_content = replace(post_content, 'http://www.old-domain.com', 'http://www.new-domain.com');
Browse through WordPress blog to check if everything is okay. You also need to re-login to WP Administration as authentication cookie has now became invalid due to different domain.
Related Posts:
Integral to any WordPress developer’s arsenal is the local server. In this tutorial, I want to walk you all the way from installing a local server to theming, exporting databases, and beyond.
What We Will Do
In this tutorial, I will take you through the entire process of installing a local server on your computer, creating a mock site, and deploying that site in production. By the end of this tutorial, you should be able to understand how to:
- Install a local server and configure WordPress locally
- Import content into your local database
- Create and edit a site or plugin locally
- Install and configure WordPress on your production server
- Import database content into your production site
- Transfer the wp-content folder that houses plugins, themes, and other elements
- Sit back and enjoy clients that love you because of minimal downtime!
And, really to me that last point is what it’s all about. I understand that there are some limitations of local servers and sometimes a maintenance mode is necessary, but by utilizing a local server you can effectively eliminate almost all downtime on a normal site. Without further ado, let’s dig in!
Step 1. Install and Configure a Local Server
I personally use MAMP (I’m a Mac guy all the way), and it is available for download here. For you Windows users, I would recommend XAMMP, which is available here. There is also an XAMMP version for Mac users.
Click on the link above to download to application. Once it downloads drag the application icon into your application folder (for Mac users), or use the XAMMP installer for Windows users.
After installing, you will find MAMP in /Applications/MAMP. XAMMP will be located in Start -> Programs -> XAMMP. That’s it for the install! Once you open MAMP, be sure to take a look at the preferences by clicking on the “Preferences” button. Your ports should be set up like this on Mac:
Starting the Local Server for the First Time
Now that the local server is installed, we will need to start the Apache and MySQL servers. XAMMP also comes with Filezilla and Mercury as included, optional services.
To start up the servers for MAMP, go to: /Applications/MAMP and click on the MAMP icon. The control panel will look like this:
In the above images, we can see the green lights mean that our servers are active. On my older MacBook, this was not always the case (I will address that later). For now, green means go! You can open MAMP’s start page by clicking the “Open Start Page” button. This will take you to your phpinfo, phpMyAdmin access, and other important configuration settings that we will use later.
For XAMMP, the control panel, accessed at \xampp\xampp-control.exe, will look like this:
Again, this is straightforward stuff. Click “Start” to start the Apache and mySQL servers. The admin area can be accessed by typing http://127.0.0.1 or http://localhost into your browser.
Congratulations on installing your local server!
Step 2. Installing and Configuring WordPress on Your Local Server
First, be sure to download the latest version of WordPress here. After that, you get to do the famous 5-minute WordPress install, which is also outlined here.
- From within your local server’s phpMyAdmin, create a new database named “wordpress”. You can add that on the very first page that comes up when you click on the phpMyAdmin link.
- Unzip the WordPress folder and copy it to applications/MAMP/htdocs for MAMP, and programs/XAMMP/htdocs for XAMMP users. The new URL for MAMP will be http://localhost:8888/wordpress/. If you are working on a site that will later be named something else like “blog”, now would be a good time to rename the folder. The URL will change accordingly.
Since I also develop sites without WordPress, I have copied the whole folder over instead of taking the contents out. By leaving root items in their own folder, this also allows me to test Drupal, Joomla, and Magento themes.
- In the wordpress folder, duplicate the wp-config-sample.php file, and rename it to wp-config.php.
- Open wp-config.php in an editor, and starting at line 17, you want to edit the following with your configuration found on your local server’s start page:
// ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define('DB_NAME', 'database_name_here'); /** MySQL database username */ define('DB_USER', 'username_here'); /** MySQL database password */ define('DB_PASSWORD', 'password_here'); /** MySQL hostname */ define('DB_HOST', 'localhost');Obviously, we named our database “wordpress” in step 1, so that goes there. For MAMP users, the username and password can both be set to “root” as that is the default admin user. By default on XAMMP the user “root” has no password.
You can add more users to the wordpress database in phpMyAdmin if you want. The hostname should stay as “localhost”.- With wp-config.php still open, we also want to go ahead and get our unique authentication keys. To do that, visit https://api.wordpress.org/secret-key/1.1/salt/ and use the code that displays to replace lines 45-52:
define('AUTH_KEY', 'put your unique phrase here'); define('SECURE_AUTH_KEY', 'put your unique phrase here'); define('LOGGED_IN_KEY', 'put your unique phrase here'); define('NONCE_KEY', 'put your unique phrase here'); define('AUTH_SALT', 'put your unique phrase here'); define('SECURE_AUTH_SALT', 'put your unique phrase here'); define('LOGGED_IN_SALT', 'put your unique phrase here'); define('NONCE_SALT', 'put your unique phrase here');- Save and close wp-config.php.
- Begin the installation process by visiting wp-admin/install.php. In MAMP, if you’re site URL is http://localhost:8888/wordpress, then you will enter http://localhost:8888/wordpress/wp-admin/install.php.
- If your wp-config.php settings are correct, then you will be prompted to enter the blog name, your email, and username info.
If an error appears, don’t worry! The issue will be in your wp-config.php file. Go there and figure out which setting above is incorrect.
Now, WordPress should be active and ready on your local server. You can access the admin dashboard on MAMP at http://localhost:8888/wordpress/wp-login.php. If you changed the folder name, then change “wordpress” to the new name. XAMMP users can do away with the :8888 or enter 127.0.0.1/wordpress/wp-login.php.
Step 3. Create and Edit Your Site
Starting with Themes and Plugins
Your default WordPress installation will come with a default theme called Twenty Ten. To add more themes, you can copy them straight into the wp-content/themes folder or you can install them via the WordPress dashboard in “Appearance -> Themes”. Themes can be edited locally via “Appearance -> Editor” or a text editor.
Plugins can also be installed the same way, either copy them into wp-content/plugins or find new plugins via the WordPress dashboard in “Plugins -> Add New”. Plugins can also be edited locally via “Plugins -> Editor” or a text editor.
Having a local server is also a great way to test new plugins and find which ones work for your sites. Every WordPress developer should have a tool bag full of plugins that they can make work for them at their disposal.
Importing Content
So now that we have our theme and our plugins, what about content? Well, click here to download an XML file full of WordPress post content that should help you get started.
To import that XML content into your local server:
- Go to “Tools ->Import”
- In the list of options that appears, click “WordPress”, since you are uploading WordPress content. This will also apply when you import data from this site to your production site.
- If this is the first time that you have imported content, you will be asked to install the WordPress Importer. Click “Install Now”. This actually installs a new plugin in our wp-content/plugins folder named “wordpress-importer”.
- After it is installed, click on the link to activate and run the importer.
- Browse to the posts.xml file (or any other exported WordPress database file), and upload.
- On the next screen, attribute the new posts to an author (usually admin), and be sure to click “Download and import file attachments”. I find this to be helpful if I am importing new data.
Now, if you visit the admin dashboard, you will see that you now have posts, categories, comments, pages, and users to utilize as you test and develop themes and plugins.
Importing data does not overwrite existing data, it only adds to what is there. So don’t worry about that as you import.
Getting Those Pretty Permalinks
This is something that frustrated me greatly when I first started working, but the solution is simple.
First, open your httpd.conf file in /Applications/MAMP/conf/apache/. Lines 378-381 will look like this:
<Directory /> Options Indexes FollowSymLinks AllowOverride None </Directory>Replace that code with:
<Directory /> Options Indexes FollowSymLinks AllowOverride All </Directory>Your pretty permalinks should be all good to go, which should also help quicken your production.
Step 4. Ready the Production Server
Now that you have installed and configured WordPress on your local server, you can apply the same principles to install WordPress on your production server.
The nice thing is that since you only need to change some wp-config.php database settings, you can simply do the following to get WordPress up and running in a production environment:
- Log into our server’s control panel, navigate to phpMyAdmin, and create the database named “wordpress”.
- While logged into phpMyadmin, make sure to note username, password, and database host address, as we will need to edit these values in wp-config.php.
- Edit wp-config.php to match the new server settings.
- Upload the entire WordPress folder via FTP to your production server. Again, this may be named something else if you want it to be in a sub-folder (ex. http://mysite.com/blog/ – where “blog” is your WP install). If you want to install WordPress in the root of your site, move the folder over to the root folder of your site, and then move the contents out into your root folder leaving the original WordPress folder empty. You can then delete that folder. This will also ensure that you move over all of the plugins and themes that you have been testing with. You can delete unwanted plugins and themes in your production enviroment by removing them from the wp-content folder or disabling them in the WordPress dashboard.
- Complete the famous 5-minute install as outlined before. Remember, if there is an error, it is almost always due to an error in the wp-config.php settings. WordPress will even tell you this on its error page.
Now WordPress is active in production, but it lacks content. We must get our local server content that we have perfected over to our live site.
Step 5 . Transferring Your Database Content and Files
Exporting the Local Server Content
In order to export our local server content, we need to log in to our local WordPress dashboard, again http://localhost:8888/wordpress/wp-login.php for MAMP users and http://localhost/wordpress/wp-login.php for XAMMP users.
Next, scroll down to “Tools -> Export”.
Since this is the first export, select “All Content” and click “Download Now”. As WordPress states, “This will contain all of your posts, pages, comments, custom fields, terms, navigation menus and custom posts.”.
Immediately (depending on the size of the database), you will have an XML file which has a name structure of sitename.wordpress.year-month-day.xml. This is the file that we will import just like we did with posts.xml on our local server.
Importing Content into Production
Since we just learned how to import new data into our local server, use the same principles to install your content from your local server to your production server
Exporting and Importing Directly in phpMyAdmin
I also want to point out that you can also import and export directly in phpMyAdmin. To export our local server data, we would:
- Open phpMyAdmin from the MAMP or XAMMP start page.
- Click on our database named “wordpress” or whatever you have named the WordPress database.
- Click on the “Export” tab, and choose an XML type export.
- Be sure to check the box for “Save as file”. Since the content of my site was small, I chose not to compress it, but I would highly recommend it for larger databases.
This will save a database backup XML file directly to your hard drive. Now you can import it via WordPress or your production server’s phpMyAdmin.
To import our newly created XML file (mine saved as wordpress.xml), repeat steps 1 and 2 from above, but at step 3, click “Import”. That screen will look like this:
Browse to your saved XML file, and click the radio button for XML under “Format of imported file”.
And that’s all folks! You now have a fully functional site that you created and configured on a local server, but exported and deployed into production.
Local Environment Tips and Tricks
In addition to the tutorial above, I wanted to throw out a couple of things that I do while working in my local environment that have proven helpful when moving to production:
Secure Your Site Before it Goes Live
This last year was the first time that I had a site get hacked. I know that may be old hat for some, but there is nothing like getting a call from a client to report it. Now, the good news was that it was easy to take care of and secure, but through that experience I learned that you can never go wrong with securing your site early.
One of the easiest things to do to add a layer of security to your site is to create a blank index.php file and place it in your wp-content folder, wp-content/plugins, wp-content/themes folder. This is a quick fix that can be done at the beginning of the development process to create an added layer of security for your site by preventing indexing of your content.
In that index.php file, I would just add the following code:
<?php //This is for added security, and it prevents indexing. ; ?>Use Downtime to Learn New Things
My local server has proved invaluable in my learning the ins and outs of WordPress plugins and themes. Because I don’t need the internet anymore, I can download the themes and plugins I want and whenever I get the chance look over the files and functions.
This may sound pretty common sense, but having my local server and using it regularly has really shaped the way I develop by allowing me to learn practically from others’ work in their code. And the great thing is that if I still haven’t understood something, I can come back to it later because it isn’t live and it isn’t affecting anyone.
Understand the Limitations of a Local Server
Now after all of the positive things, here are a few items that should be noted when working with a local server – primarily from my experiences with MAMP :
- Be prepared if the local servers won’t start. There was a time, specifically with my MacBook and MAMP, that every time I went to start on a site, MAMP would just freeze. I would spend the first 15 minutes of a project I was excited about trying to figure it out. Kind of killed the excitement a little! To remedy this, try “Force Quitting” MAMP. If that doesn’t work, OSX 10.5 and 10.6 users can usually open up Activity Monitor (located in Applications/Utilities), select “My Processes”, and look for multiple instances of “mysqld”. If there are multiple running, delete all but one. That should get things back to normal.
- For MAMP, the green lights to indicate the servers are on are not always reliable. To test this, just click on the “Start Page”, and if it comes up then you are good to go.
- Some form actions and advanced functions may not work properly. I have experienced this with an Amazon S3 plugin that I developed. For these things, I will often set up a custom WordPress page template or plugin folder, install it to my site via FTP, and test on a private page. You could even install a subdirectory to accomplish more testing or use Multipress.
Conclusion
Thanks for walking through the process of installing a local server, configuring a WordPress site on it, and then migrating that site to a production environment.
I would encourage any of you that have more experience than me to please post below any other local setups that you have, any more ideas of how to streamline the migrating process, and any other tips and tricks to working locally. I am just one voice of the community after all.
Thanks for reading!
In this article, we take a break from some of the more advanced ways to customize WordPress, and share some super-easy customization techniques for the WordPress Admin area.
If you’re just getting started with WordPress, or have been running with default functionality for a while and now want to dig in with some useful and easy ways to customize your WordPress site, a great place to start is the WordPress Admin area, or backend. One of the great things about WordPress is that each part of the backend is easily customized using simple PHP functions.
In this article, you’ll learn how to customize the login page with your own logo, add new widgets to the dashboard, add custom content to the admin footer, make it easier to get in and out of the Admin area, and more. When combined, these techniques can improve branding, accessibility, and usability of your WordPress-powered site.
Changing the Default WordPress Login URL
By default, logging in to the WordPress Admin area requires either /wp-admin or /wp-login.php in the URL, which isn’t a lot to type. You can, however, make it even easier by changing the login URL to something more memorable and better branded.
This technique requires .htaccess file manipulation. Usually, this is a file hidden in the root of your WordPress installation. It’s automatically created by WordPress after setting custom permalinks using URL rewriting.
First, check your SFTP/FTP client preferences to show hidden files—most FTP clients manage that. Then, check that the file .htaccess exists. If that is not the case, create it by using your favorite notepad. On Windows, use the Notepad++ software to create it. Open it and add this line on top:
RewriteRule ^login$ http://YOUR_SITE.com/wp-login.php [NC,L]Just replace the login keyword with one of your choice and your website’s URL.
Now, open your favorite browser and go to http://yoursite.com/login. You’ll be redirected to the WordPress login page. Remember that your clients are not supposed to know everything about WordPress usages—a user-friendly URL is far better to remember than /wp-login.php.
Easy to remember, easy to teach, easy to learn!
Changing the Default External Link of the WordPress Login Page
When you log into WordPress, the default logo links to WordPress.org. Let me show you a quick tip for using your own link. Open the functions.php file. Then, add the following lines of code. And be sure to remember the PHP tag enclosure.
// Use your own external URL logo link function wpc_url_login(){ return "http://wpchannel.com/"; // your URL here } add_filter('login_headerurl', 'wpc_url_login');Don’t forget to save the file. Log out to view the result. Better, no?
Customizing the Login logo Without a Plugin
Reinforce your brand by changing the default WordPress login logo. The logo is one of the most important elements of your brand! People will memorize it to find you quickly. Showcase it!
This is the default WordPress login screen:
To enhance it, add these lines of code in your functions.php:
// Custom WordPress Login Logo function login_css() { wp_enqueue_style( 'login_css', get_template_directory_uri() . '/css/login.css' ); } add_action('login_head', 'login_css');The third line points towards a separate stylesheet. Even though it’s possible to use that of your default CSS theme, I advise you to use Firebug—a useful Firefox add-on—or any other Web development tool that allows you to edit your website in real-time. As you can see, just one line of code is needed to change the default logo.
#login h1 a { background-image: url("http://YOUR-WEBSITE.com/wp-content/themes/YOUR_THEME/images/custom_logo.png") !important; }Feel free to change the logo URL if it’s not located in your theme folder. Now have a look at your login page: your custom logo appears!
If that is not the case, make sure that no white lines are present at the end of your functions.php file.
Changing the Footer of Your WordPress Administration
The default WordPress administration footer thanks you for using their content management system and links to WordPress.org. For professional use and website branding, you’ll want to customize this area.
Open the Appearance menu and click on Editor. Click on functions.php on the right side of your screen. You can also access the footer by using an FTP client to locate /wp-content/themes/NAME_OF_YOUR_THEME/functions.php.
Now, add the following lines of code, taking care to place them between PHP tags:
// Custom WordPress Footer function remove_footer_admin () { echo '© 2012 - WordPress Channel, Aurélien Denis'; } add_filter('admin_footer_text', 'remove_footer_admin');To customize the content, just change the second line inside the echo, between the quotes.
Finally, refresh your browser to see the result.
Adding Custom Widgets to Your Dashboard
It can be useful to add your own widget to provide general or commercial information. Adding a widget to the WordPress dashboard can be done very quickly. Again, open the functions.php file, then, add the following lines of code:
// Add a widget in WordPress Dashboard function wpc_dashboard_widget_function() { // Entering the text between the quotes echo "<ul> <li>Release Date: March 2012</li> <li>Author: Aurelien Denis.</li> <li>Hosting provider: my own server</li> </ul>"; } function wpc_add_dashboard_widgets() { wp_add_dashboard_widget('wp_dashboard_widget', 'Technical information', 'wpc_dashboard_widget_function'); } add_action('wp_dashboard_setup', 'wpc_add_dashboard_widgets' );In this example, add the desired text between the echo tag, after the quotes. You could also insert HTML; an unordered list for example. Name your widget—this will be the widget title—by replacing “Technical informations” with your title of choice. This is what it will look like.
If you do not see your custom widget, click on the Options menu screen located in the top right of the window to display it.
Hiding Unwanted WordPress Dashboard Widgets
The WordPress dashboard displays multiple widgets that you can easily move by dragging and dropping. To mask them definitively, just add the following lines in the functions.php file:
add_action('wp_dashboard_setup', 'wpc_dashboard_widgets'); function wpc_dashboard_widgets() { global $wp_meta_boxes; // Today widget unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']); // Last comments unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']); // Incoming links unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']); // Plugins unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']); }You can choose what widgets you’d like to hide. In this case, “Right Now”, “Recent comments”, “Incoming links” and “Plugins” have been removed from your WordPress dashboard. To learn more about this feature, have a look at the codex.
Creating Your Own Custom Admin Color Scheme
If you’re not totally satisfied with the WordPress admin color scheme, this is how you can customize it. All you need to do is create a new CSS stylesheet. In this example, we’ll call it admin.css and place it in a folder entitled/css. Once again, edit the functions.php file and add this snippet:
// Custom WordPress Admin Color Scheme function admin_css() { wp_enqueue_style( 'admin_css', get_template_directory_uri() . '/css/admin.css' ); } add_action('admin_print_styles', 'admin_css' );Your admin.css file must contain styles that are compatible with WordPress. Again, I recommend you use Firebug or Web Inspector to identify the right ones.
Conclusion
That’s all folks! I hope you have learned a few good tips to make WordPress act more like a white label CMS. Remember that customization is not just a branding technique, but also a way to boosting your productivity, by increasing user-friendliness.
If you’re not comfortable with PHP, you can make most of these changes with the White Label CMS WordPress plugin. Do you know any other great tips? Share them with us!
(jc)
Now that spring has arrived (at least in the Northern Hemisphere), it is an excellent time to clean up and decruft your WordPress site. In this post I will show you a number of plugins and techniques that you can use to do just that.
Note: Back up your database before running any of the plugins or queries presented below.
Delete inactive plugins and themes
Not only do inactive plugins and themes waste disk space, they also clutter your database with unused settings and other metadata. Remember: most plugins won’t delete their DB options and tables until you completely uninstall them. You will also continue to receive update notifications, which can be a distraction. Remove any plugins and themes you’re not using any more.
Delete orphaned DB options
As mentioned above, plugins should automatically clean up their database entries when you uninstall them. Unfortunately, not all of them do, which leads to some entries becoming “orphaned”. Use the Clean Options plugin to delete DB options left behind by those untidy plugins.
Delete orphaned database tables
First, use WP-DBManager to get a list of all tables in your database. Compare it to the list of WordPress core tables. Any table not on that list is part of a plugin. If you spot any tables that have been orphaned by uninstalled plugins, use the “drop” command to delete them.
Delete post revisions
The post revision feature can be useful, but it also tends to fill up your database pretty quickly since WordPress creates a new revision each time you edit a post. There are several ways to fix this problem.
Delete all post revisions
You can use WP-Cleanfix or WP-Optimize to get rid of any and all post revisions.
Delete only old post revisions
In some cases you may want to clean out old revisions while leaving the most recent – and thus most likely to be useful – revisions intact. This SQL query will delete only post revisions created before March 1st, 2012:
DELETE a, b, c FROM wp_posts a LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id) LEFT JOIN wp_postmeta c ON (a.ID = c.post_id) WHERE a.post_type = 'revision' AND a.post_date < '2012-03-1'Use WP-DBManager or a similar plugin to run this query.
Limit the number of revisions per post
Add this line to your wp-config.php file to limit the number of revisions to 5 per post:
define('WP_POST_REVISIONS', 5);Disable revisions
Add this line to your wp-config.php to completely disable post revisions:
define('WP_POST_REVISIONS', 0);Note that this does not remove existing revisions. Use one of the other techniques discussed above to do that.
Delete spam comments
Even small blogs can receive thousands of spam comments per month. If left unchecked, all the spam will gradually accumulate in your database, potentially slowing down comment queries and hurting your site’s performance. Make sure to regularly clean out the spam by clicking the “Empty Spam” button in Comments -> Spam.
Bonus tip: I strongy recommend the NoSpamNX plugin to anyone receiving large amounts of spam. It’s a great “first line of defence” and can be configured to discard spam comments immediately instead of storing them in the database.
Delete pingbacks
If your comments table still takes up a lot of space even after you’ve deleted all spam comments, consider removing some or all the received pingbacks. While pingbacks can be useful as a way to be notified when someone mentions your content, old pingbacks lose their relevance quickly. Pingbacks are also frequently abused by spammers.
This query will delete all pingbacks received before March 1st, 2012:
DELETE FROM wp_comments WHERE comment_type = 'pingback' AND comment_date < '2012-03-01';Scan your site for malware
Check that your blog is free from malware and suspicious code by scanning it with Sucuri.net.
Find and fix broken links
Use Broken Link Checker to check your site for broken links, missing images, removed YouTube videos and similar issues.
Delete unused post and comment meta
Unused post meta keys are another kind of database cruft that can be left behind by long-since-uninstalled plugins and themes. You can use the WP CleanFix plugin I mentioned before or WP-Cleanup to remove them.
Alternatively, if you would prefer to do it without a plugin, the following SQL query will also remove all instances of the specified post meta key:
DELETE FROM wp_postmeta WHERE meta_key = 'unused meta-key-name';And this query will do the same for the comment meta table:
DELETE FROM wp_commentmeta WHERE meta_key = 'unused-meta-key-name';Finally, if you have a lot of registered users, you might also want to check for and remove unused user meta keys. Here’s a query to delete an unused piece of user metadata:
DELETE FROM wp_usermeta WHERE meta_key = 'unused-meta-key-name';Also, see this tutorial for a more in-depth explanation of how to find and remove unused custom fields with phpMyAdmin.
Remove unused tags and categories
If you have a lot of unused tags or categories on your site, clean them up to reduce the database size and gain a little bit of performance. Both WP CleanFix and WP-Cleanup can help you get rid of unused tags.
Alternatively, this set of SQL queries will accomplish the same task (props to 4 Rapid Development):
DELETE FROM wp_terms WHERE term_id IN (SELECT term_id FROM wp_term_taxonomy WHERE COUNT = 0 ); DELETE FROM wp_term_taxonomy WHERE term_id NOT IN (SELECT term_id FROM wp_terms); DELETE FROM wp_term_relationships WHERE term_taxonomy_id NOT IN (SELECT term_taxonomy_id FROM wp_term_taxonomy);Remove unused shortcodes
If you’ve been blogging for a while, you’ve probably run into this problem: you uninstall a plugin or switch to a different theme, and now your site is full of shortcodes that no longer work. Obviously, going back and editing each post one-by-one is not going to work. You need a way to automatically remove the unused shortcodes.
Well, Search and Replace is just the ticket. It lets you search your posts for a piece of text and replace it something else.
Alternatively, here’s a query that will remove all instances of the specified [shortcode] from your posts (props to WPRecipes):
UPDATE wp_post SET post_content = replace(post_content, '[shortcode]', '' ) ;Note that the above only works with self-closing shortcodes. For self-closing shortcodes like “[shortcode] content [/shortcode]” you’ll need to use regular expression search.
Delete commenter’s user agent
For each comment your blog receives, WordPress also stores the comment author’s user agent (basically, the web browser fingerprint) along with the rest of the comment. This can be handy for advanced users, but most bloggers will never need this information. You can shrink your database a bit by removing the user agent records.
Run this query to remove the user agent information from your database (props to RSA Blog):
UPDATE wp_comments SET comment_agent = '';Delete unused images
Free up some disk space by deleting images not attached to any post or page. Go to Media -> Library -> Unattached, select all items, choose “Delete Permanently” from the “Bulk Action” drop-down and click “Apply”.
Another option is to use Upload Janitor or WP CleanFix to automate the process.
Optimize database tables
It’s good practice to optimize your tables regularly. Database optimization helps keep site performance steady and is especially useful after you’ve just made large change to the DB (like cleaning up all post revisions and unused meta keys). You can use WP-DBManager to schedule automatic DB optimization. WP-Optimize also includes the database optimization feature, but does not support scheduling.
Resources
For reference, here’s a list of all plugins mentioned in this post (in alphabetical order):
- Broken Link Checker – scan your site for broken links.
- Clean Options – detect and remove orphaned DB options.
- NoSpamNX – block spam comments.
- Search and Replace - find & replace text in your posts, comments, etc.
- Search Regex – find & replace with regular expression support.
- Upload Janitor – find and delete unused images.
- WP CleanFix – delete post revisions, unused meta, and much more.
- WP-Cleanup – delete revisions, unused tags, post meta, etc.
- WP-DBManager – manage and optimize your database.
- WP-Optimize – remove revisions, auto-draft posts, optimize tables, etc.
Final note: As you may have noticed, many of the “clean up” plugins – WP-Cleanup, WP-CleanFix, and so on – have a very similar feature set. So which should you use? Overall, WP CleanFix seems to be the most comprehensive solution, so I would recommend that one.
a href=”http://wordpress.org/extend/plugins/broken-link-checker/”
Related posts :
WordPress is without doubt the most popular CMS at this moment in time, dwarfing other options such as Joomla and Drupal.
While this is a good thing for WordPress, it now has a very large and active community contributing plug-ins, themes and fixes, but with this growth it now also has its bad points … When anything becomes this big, people will find ways to attack the CMS in question for whatever reason they see fit.
Our job as WordPress users (aside from contributing to the WordPress community) is keeping our installs safe from people we do not want to access our sites.
There are numerous plug-ins to help shore up our WordPress defenses such as Login LockDown which records IP address and blocks them after a set number of login attempts which helps against brute force attacks.
Another is WP Security Scan which checks your install for vulnerabilities and suggests possible methods for fixing anything it may find.
One of the most ignored methods of keeping your install safe is updating your install when updates become available which ensures all of the latest patches and fixes are applied to your site. (You can also remove the readme.html and license.txt files from the root directory as they display the version number of WordPress you have installed.)
Advertisement
Configuring the .htaccess file
Aside from plug-ins there are a number of additions you can make to your .htaccess file which in conjunction with plug-ins and regular updates will tighten up your site’s security and give you that extra level of protection.
I'm going to cover a few of these that I feel protect some of the essentials in your WordPress install and show you how and where to add the code snippets; you don't have to use every single one, just whatever you feel would help you secure your site.
The typical WordPress .htaccess file looks similar to this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I would suggest any additions to the .htaccess file to be added after # END WordPress.
This will ensure you don’t break any of the WordPress based .htaccess functions. Before making any changes to your .htaccess file I strongly recommend backing it up and keeping it stored in a safe place!
Protect wp-config.php
wp-config.php is the file in your root directory that stores information about your site as well as database details, this file in particular we would not want to fall into the wrong hands.
In your .htaccess add the following to prevent any access to the wp-config.php file:
<Files wp-config.php>
order allow,deny
deny from all
</Files>
Admin access from your IP only
You can limit who can access your admin folder by IP address, to do this you would need to create a new .htaccess file in your text editor and upload to your wp-admin folder.
The following snippet denies access to the admin folder for everyone, with the exception of your IP address, but please note if you have a dynamic IP, you might have to regularly alter this file otherwise you will be denied access yourself!
order deny,allow
allow from 202.090.21.1 (replace with your IP address)
deny from all
Banning bad users
If you have the same IP address trying to access your content or trying to brute force your admin pages, you can ban this person using .htaccess with this simple snippet:
<Limit GET POST>
order allow,deny
deny from 202.090.21.1
allow from all
</Limit>
This person will now not be able to access your site. You can add more by replicating the deny line, for example:
<Limit GET POST>
order allow,deny
deny from 202.090.21.1
deny from 204.090.21.2
allow from all
</Limit>
No directory browsing
As WordPress is now so popular many people know the structure of a WordPress install and know where to look to discover what plug-ins you may use or any other files that might give away too much information about your site, one way to combat this is to prevent directory browsing.
# directory browsing
Options All -Indexes
Prevent Access To wp-content
The wp-content folder contains images, themes and plug-ins and it's a very important folder within your WordPress install, so it makes sense to prevent outsiders accessing it.
This requires it's very own .htaccess file which must be added to the wp-content folder, it allows users to see images, CSS etc … but protects the important PHP files:
Order deny,allow
Deny from all
<Files ~ ".(xml|css|jpe?g|png|gif|js)$">
Allow from all
</Files>
Individual File Protection
There are certain files you might want to protect individually rather than blocking a whole folder or selection. The example snippet shows how you would prevent access to the .htaccess file and will throw a 403 if accessed by anyone. The file name can be changed to whatever file you wish to protect:
# Protect the .htaccess
<files .htaccess="">
order allow,deny
deny from all
</files>
Protect .htaccess
Sounds crazy, huh? We spend so much time worrying whether we have the right plug-ins and fixes installed, we overlook the fact the .htaccess file is still open to attack.
This snippet basically stops anyone viewing any file on your site that begins with "hta", this will protect it and make it somewhat safer.
<Files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>
We have covered how to ban users, prevent anyone but you accessing your admin folder, how to prevent directory browsing, protecting your wp-config.php file, protecting your wp-content folder, protecting individual files and even protect your .htaccess file.
This list of snippets is by no means exhausted, there are a number of other things you can do to protect your site via .htaccess, but the items I have covered help to protect some of the key files and folders on your site and keep them away from prying eyes.
Recently while working on a membership site, we had to create multiple level of users. We did not want the users to have access to the WP-Admin panel because it was not customized for their experience. Rather we had put everything necessary (such as edit profile page), user dashboard etc, on the front-end. While S2 Membership Plugin allowed for us to disable wp-admin access for all users except for admins, there was no option to disable the admin bar by default. In this article, we will show you how to disable WordPress admin bar for all users except for Administrators.
Disable Admin Bar for All Users Except for Administrators
Paste this code in your theme’s functions.php file or your site-specific plugin.
/* Disable WordPress Admin Bar for all users but admins. */ if (!current_user_can('administrator')): show_admin_bar(false); endif;Disable Admin Bar for All Users
If you want to disable it for all users, then simply put use this code in your theme’s functions.php file or your site-specific plugin.
/* Disable WordPress Admin Bar for all users but admins. */ show_admin_bar(false);
Infinite scroll pagination is inspired from Facebook and Twitter. This is just pagination where the user will need to scroll to bottom of the page to read more articles. This is one way to improve the user experience on a website, but if you do it wrong, it can give a bad experience too. If you’re going to implement this type of pagination, make sure you don’t include important links at the bottom of the page. The reason for this is that when a user tries to click on that particular link, the page will auto load new entries and push the link off the screen each time. You can either set a fixed position footer area or make your sidebar visible all the time.
Step 1 Plan Your Pagination
It is important that you plan ahead with your pagination, where you want to include it, and how you are going to process it. A common way of doing pagination is by listing the page numbers at the bottom of the page. Using this method however, no more page numbers will appear at the end of your article list, as they’re no longer needed. This pagination can be use on all themes as long as you don’t include loads of information in your footer section, as it may not give the desired effect.
Our infinite scroll pagination will use jQuery and ajax functionality to make the request and retrieve more articles to be shown to the user. In this tutorial, I will use the Twenty Ten theme as an example, you can view the working demo of the infinite scroll here.
Step 2 Building the Ajax Function
We will use WordPress’ ajax functionality to make the call for this pagination. First we prepare the basic function for our pagination, please insert the following code to your theme’s functions.php
function wp_infinitepaginate(){ $loopFile = $_POST['loop_file']; $paged = $_POST['page_no']; $posts_per_page = get_option('posts_per_page'); # Load the posts query_posts(array('paged' => $paged )); get_template_part( $loopFile ); exit; }This function will be used to make the call for our pagination, basically we send two variables to this function via ajax, one is the page number and another is the file template we are going to use for our pagination. To enable this function to be used with WordPress ajax, we need the following code.
add_action('wp_ajax_infinite_scroll', 'wp_infinitepaginate'); // for logged in user add_action('wp_ajax_nopriv_infinite_scroll', 'wp_infinitepaginate'); // if user not logged inThe default action for WordPress ajax would be wp_ajax_(our action name), hence why the name infinite_scroll being used in the code example. We need to add two actions, one for logged in users and another is for users that are not logged in.
Next we will need to build the ajax function that will send the two variables we need for our pagination. You can use WordPress hooks to insert this jQuery ajax function or straight away insert it into your theme header.php
<script type="text/javascript"> function loadArticle(pageNumber) { $.ajax({ url: "<?php bloginfo('wpurl') ?>/wp-admin/admin-ajax.php", type:'POST', data: "action=infinite_scroll&page_no="+ pageNumber + '&loop_file=loop', success: function(html){ $("#content").append(html); // This will be the div where our content will be loaded } }); return false; } </script>This will be the basic ajax call that we are going to make and we use “infinite_scroll” as our action name. WordPress will automatically call our function wp_infinitepaginate(); because we define it in our theme functions.php previously.
Step 3 Determine When the User Scroll to Bottom of Page
To enable the infinite scroll pagination, we need to determine when the user hits the bottom of the page. This can be achieved easily via jQuery using the following code.
<script type="text/javascript"> $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ // run our call for pagination } }); </script>Now we can know when the user hits the bottom of the page. Next we need to call the loadArticle function within the scroll function. I’m adding a counter to be used as the page number of our call.
<script type="text/javascript"> var count = 2; $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ loadArticle(count); count++; } }); function loadArticle(pageNumber){ $.ajax({ url: "<?php bloginfo('wpurl') ?>/wp-admin/admin-ajax.php", type:'POST', data: "action=infinite_scroll&page_no="+ pageNumber + '&loop_file=loop', success: function(html){ $("#content").append(html); // This will be the div where our content will be loaded } }); return false; } </script>Each time the user scrolls to bottom of the page, the counter will increase and this will enable us to have the page number pass to our wp_infinitepage() function within our theme’s functions.php. With the scroll and loadArticle functions, we can now do the ajax function call within our WordPress theme, but the result may not appear if we haven’t defined the loop file within our theme folder.
Step 4 Setting Up Our Theme
Most important thing, we need to setup the div that will hold the new content that’s been requested using our ajax function. In the Twenty Ten theme, there is already a div we can use, which is the div with id="content" so we will include the div id in our ajax function. If you use other themes that don’t wrap their loop in a div, you can simply wrap the loop function like the example code below to achieve the same result.
<div id="content"> loop content </div>Next we will need a loop file for this. The Twenty Ten theme already has a loop file included, this is the main reason why I chose Twenty Ten for this example, because it is easier for anyone who wants to reference this later. If you don’t have any loop.php, simply create a new loop file, and copy the loop function within your index.php into the new file and uploaded it into your theme’s folder. For anyone using the Twenty Ten theme, you would want to comment out the pagination included in the file because we won’t need it anymore (please refer to the tutorial source file on how to do this).
Step 5 Adding Ajax Loader
This is optional, just to give a nice touch to our infinite scroll pagination. We will add an ajax loader image as we hit the bottom of the page. You can add the following code to your footer.php
<a id="inifiniteLoader">Loading... <img src="<?php bloginfo('template_directory'); ?>/images/ajax-loader.gif" /></a>and then add the following CSS to your stylesheet.
a#inifiniteLoader{ position: fixed; z-index: 2; bottom: 15px; right: 10px; display:none; }Next we will add a few lines of code to our jQuery function to show and hide this ajax loader element.
<script type="text/javascript"> jQuery(document).ready(function($) { var count = 2; $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ loadArticle(count); count++; } }); function loadArticle(pageNumber){ $('a#inifiniteLoader').show('fast'); $.ajax({ url: "<?php bloginfo('wpurl') ?>/wp-admin/admin-ajax.php", type:'POST', data: "action=infinite_scroll&page_no="+ pageNumber + '&loop_file=loop', success: function(html){ $('a#inifiniteLoader').hide('1000'); $("#content").append(html); // This will be the div where our content will be loaded } }); return false; } }); </script>The ajax loader will be shown once the user hits the bottom of the page and will be hide once the ajax request has finished.
Step 6 Additional Limitation to Enhance the Infinite Scroll
Up till now, we already have a working infinite scroll, but one thing is missing. The function will keep triggering each time a user hits the bottom page even though there are no more post to be shown. This is something we don’t want to have. We will add a control in our scroll function so when there no more pages to be shown, it will stop.
<script type="text/javascript"> var count = 2; var total = <?php echo $wp_query->max_num_pages; ?>; $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ if (count > total){ return false; }else{ loadArticle(count); } count++; } }); </script>We add a new var total to the function which will return the total pages available on our site. This will be used to ensure no additional calls will be made to the page if the maximum page has been reached. Another thing we would want to add is a restriction where this function will be loaded. We just want this on our home page, archive or maybe search, but not on our single post and page. So we wrap a simple PHP if else function in our jQuery code.
if (!is_single() || !is_page()): // our jQuery function here endif;That’s pretty much everything you need for the pagination, please refer to the source files for example code used in this tutorial. The files are based on the Twenty Ten theme.
Conclusion
By now you should be able to use this function in any of your theme, if you have any additional suggestions or questions regarding this tutorial, feel free to leave a comment or contact me via twitter. Would love to share any ideas with you guys.
Fun fact of the day: about 37% of WordPress downloads are for non-English, localized versions.
So as a plugin or theme author, you should be thinking of localization and internationalization (L10N and I18N) as pretty much a fact of life by this point.
Fun total guess of the day: based on my experience in browsing through the thing, roughly, ohh… all plugins and themes in the directory are doing-it-wrong in some manner.
Yes friends, even my code is guilty of this to some degree.
It’s understandable. When you’re writing the thing, generally you’re working on the functionality, not form. So you put strings in and figure “hey, no biggie, I can come back and add in the I18N stuff later.” Sometimes you even come back and do that later.
And you know what? You probably still get it wrong. I did. I still often do.
The reason you are getting it wrong is because doing I18N right is non-obvious. There’s tricks there, and rules that apply outside of the normal PHP ways of doing things.
So here’s the unbreakable laws of I18N, as pertaining to WordPress plugins and themes.
Note: This is not a tutorial, as such. You are expected to already be translating your code in some way, and to have a basic grasp on it. What I’m going to show you is stuff you are probably already doing, but which is wrong. With any luck, you will have much slapping-of-the-head during this read, since I’m hoping to give you that same insight I had, when I finally “got it”.
Also note: These are laws, folks. Not suggestions. Thou shalt not break them. They are not up for debate. What I’m going to present to you here today is provably correct. Sorry, I like a good argument as much as the next guy, but arguing against these just makes you wrong.
Basic I18N functions
First, lets quickly cover the two top translation functions. There’s more later, and the laws apply to them too, but these are the ones everybody should know and make the easiest examples.
The base translation function is __(). That’s the double-underscore function. It takes a string and translates it, according to the localization settings, then returns the string.
Then there’s the shortcut function of _e(). It does the same, but it echoes the result instead.
There’s several functions based around these, such as esc_attr_e() for example. These functions all behave identically to their counterparts put together. The esc_attr_e() function first runs the string through __(), then it does esc_attr() on it, then it echo’s it. These are named in a specific way so as to work with existing translation tools. All the following laws apply to them in the exact same way.
So, right down to it then.
Law the First: Thou shalt not use PHP variables of any kind inside a translation function’s strings.
This code is obviously wrong, or it should be:
$string = __($string, 'plugin-domain');The reason you never do this is because translation relies on looking up strings in a table and then translating them. However, that list of strings to be translated is built by an automated process. Some code scans your PHP code, without executing it, and pulls out all the __()’s it finds, then builds the list of strings to be translated. That scanning code cannot possibly know what is inside $string.
However, sometimes it’s more subtle than that. For example, this is also wrong:
$string = __("You have $number tacos", 'plugin-domain');The translated string here will be something like ‘You have 12 tacos’, but the scanning code can’t know what $number is in advance, nor is it feasible to expect your translators to translate all cases of what $number could be anyway.
Basically, double quoted strings in translation functions are always suspect, and probably wrong. But that rule can’t be hard and fast, because using string operations like ‘You have ‘.$number.’ tacos’ is equally wrong, for the exact same reason.
Here’s a couple of wrongs that people like to argue with:
$string = __('You have 12 tacos', $plugin_domain); $string = __('You have 12 tacos', PLUGIN_DOMAIN);These are both cases of the same thing. Basically, you decided that repetition is bad, so you define the plugin domain somewhere central, then reference it everywhere.
Mark Jaquith went into some detail on why this is wrong on his blog, so I will refer you to that, but I’ll also espouse a general principle here.
I said this above, and I’m going to repeat it: “that list of strings to be translated is built by an automated process“. When I’m making some code to read your code and parse it, I’m not running your code. I’m parsing it. And while the general simplistic case of building a list of strings does not require me to know your plugin’s text domain, a more complicated case might. There are legitimate reasons that we want your domain to be plain text and not some kind of variable.
For starters, what if we did something like make a system where you could translate your strings right on the wordpress.org website? Or build a system where you could enlist volunteer translators to translate your strings for you? Or made a system where people could easily download localized versions of your plugin, with the relevant translations already included?
These are but a few ideas, but for all of them, that text domain must be a plain string. Not a variable. Not a define.
Bottom line: Inside all translation functions, no PHP variables are allowed in the strings, for any reason, ever. Plain single-quoted strings only.
Law the Second: Thou shalt always translate phrases and not words.
One way people often try to get around not using variables is like the following:
$string = __('You have ', 'plugin') . $number . __(' tacos', 'plugin-domain');No! Bad coder! Bad!
English is a language of words. Other languages are not as flexible. In some other languages, the subject comes first. Your method doesn’t work here, unless the localizer makes “tacos” into “you have” and vice-versa.
This is the correct way:
$string = sprintf( __('You have %d tacos', 'plugin-domain'), $number );The localizer doing your translation can then write the equivalent in his language, leaving the %d in the right place. Note that in this case, the %d is not a PHP variable, it’s a placeholder for the number.
In fact, this is a good place to introduce a new function to deal with pluralization. Nobody has “1 tacos”. So we can write this:
$string = sprintf( _n('You have %d taco.', 'You have %d tacos.', $number, 'plugin-domain'), $number );The _n function is a translation function that picks the first string if the $number (third parameter to _n) is one, or the second one if it’s more than one. We still have to use the sprintf to replace the placeholder with the actual number, but now the pluralization can be translated separately, and as part of the whole phrase. Note that the last argument to _n is still the plugin text domain to be used.
Note that some languages have more than just a singular and a plural form. You may need special handling sometimes, but this will get you there most of the time. Polish in particular has pluralization rules that have different words for 1, for numbers ending in 2, 3, and 4, and for numbers ending in 5-1 (except 1 itself). That’s okay, _n can handle these special cases with special pluralization handling in the translator files, and you generally don’t need to worry about it as long as you specify the plural form in a sane way, using the whole phrase.
You might also note that _n() is the one and only translation function that can have a PHP variable in it. This is because that third variable is always going to be a number, not a string. Therefore no automated process that builds strings from scanning code will care about what it is. You do need to take care than the $number in _n is always a number though. It will not be using that $number to insert into the string, it will be selecting which string to use based on its value.
Now, using placeholders can be complex, since sometimes things will have to be reversed. Take this example:
$string = sprintf( __('You have %d tacos and %d burritos', 'plugin-domain'), $taco_count, $burrito_count );What if a language has some strange condition where they would never put tacos before burritos? It just wouldn’t be done. The translator would have to rewrite this to have the burrito count first. But he can’t, the placeholders are such that the $taco_count is expected to be first in the sprintf. The solution:
$string = sprintf( __('You have %1$d tacos and %2$d burritos', 'plugin-domain'), $taco_count, $burrito_count );The %1$d and such is an alternate form that PHP allows called “argument swapping“. In this case, the translator could write it correctly, but put the burritos before the tacos by simply putting %2$d before %1$d in the string.
Note that when you use argument swapping, that single-quoted string thing becomes very important. If you have “%1$s” in double quotes, then PHP will see that $s and try to put your $s variable in there. In at least one case, this has caused an accidental Cross-Site-Scripting security issue.
So repeat after me: “I will always only use single-quoted strings in I18N functions.” There. Now you’re safe again. This probably should be a law, but since it’s safe to use double-quoted strings as long as you don’t use PHP variables (thus breaking the first law), I’ll just leave you to think about it instead.
Law the Third: Thou shalt disambiguate when needed.
When I say “comment” to you, am I talking about a comment on my site, or am I asking you to make a comment? How about “test”? Or even “buffalo”?
English has words and phrases that can have different meanings depending on context. In other languages, these same concepts can be different words or phrases entirely. To help translators out, use the _x() function for them.
The _x() function is similar to the __() function, but it has a comment section where the context can be specified.
$string = _x( 'Buffalo', 'an animal', 'plugin-domain' ); $string = _x( 'Buffalo', 'a city in New York', 'plugin-domain' ); $string = _x( 'Buffalo', 'a verb meaning to confuse somebody', 'plugin-domain' );Though these strings are identical, the translators will get separated strings, along with the explanation of what they are, and they can translate them accordingly.
And just like __() has _e() for immediate echoing, _x() has _ex() for the same thing. Use as needed.
Finally, this last one isn’t a law so much as something that annoys me. You’re free to argue about it if you like.
Annoyance the First: Thou shalt not put unnecessary HTML markup into the translated string.
$string = sprintf( __('<h3>You have %d tacos</h3>', 'plugin-domain'), $number );Why would you give the power to the translator to insert markup changes to your code? Markup should be eliminated from your translated strings wherever possible. Put it outside your strings instead.
$string = '<h3>'.sprintf( __('You have %d tacos', 'plugin-domain'), $number ).'</h3>';Note that sometimes though, it’s perfectly acceptable. If you’re adding emphasis to a specific word, then that emphasis might be different in other languages. This is pretty rare though, and sometimes you can pull it out entirely. If I wanted a bold number of tacos, I’d use this:
$string = sprintf( __('You have %d tacos', 'plugin-domain'), '<strong>'.$number.'</strong>' );Or more preferably, the _n version of same that I discussed above.
Conclusion
Like I said at the beginning, we’ve all done these. I’ve broken all these laws of I18N in the past (I know some of my plugins still do), only to figure out that I was doing-it-wrong. Hopefully, you’ve spotted something here you’ve done (or are currently doing) and have realized from reading this exactly why your code is broken. The state of I18N in plugins and themes is pretty low, and that’s something I’d really like to get fixed in the long run. With any luck, this article will help.
Disclaimer: Yes, I wrote this while hungry.
When working with a non-technical client, you often end up telling them well the login url is yourdomain.com/wp-login.php. Some folks suggest /wp-admin/ instead of the wp-login.php url. Wouldn’t it be so much better if you can just tell your clients to go to yoursite.com/login/. Well, in this article, we will show you how to create simpler login URL in WordPress for your clients.
Open the .htaccess file and paste the following code above the WordPress rewrite rule
RewriteRule ^login$ http://yoursite.com/wp-login.php [NC,L]Don’t forget to replace the domain name to your site’s domain. That’s it. Now you can suggest your clients to go to yourname.com/login/ rather than wp-login.php
Lately there have been a lot of WordPress sites compromised only due to the bots that roam the world wide web! There are a lot of plugins out there which can protect your WordPress baby by blocking these “roguish” bots!
In this article you will be learning an easy and useful method of adeptly configuring your .htaccess file to filter these bots which can infect your website and can eat up your server resources. So get your .htaccess file ready for editing!
Step 1 Preparing the Code
The code mainly consists of bot names. I have added the most famous bots in here that I can think of. If there is some bot missing, please mention it in the comments.
The code is pretty straightforward. Go ahead and copy the code below and paste it in your .htaccess file.
# Bot Blocker <IfModule mod_setenvif.c> SetEnvIfNoCase User-Agent ^$ keep_out SetEnvIfNoCase User-Agent (pycurl|casper|cmsworldmap|diavol|dotbot) keep_out SetEnvIfNoCase User-Agent (flicky|ia_archiver|jakarta|kmccrew) keep_out SetEnvIfNoCase User-Agent (purebot|comodo|feedfinder|planetwork) keep_out <Limit GET POST PUT> Order Allow,Deny Allow from all Deny from env=keep_out </Limit> </IfModule>Step 2 Testing the Code
To see whether the code is doing its job, I using recommend this website Bots VS Browsers. This website is a good place to simulate these types of attacks. Once on their website all you have to do is select any bot from the code, which you just added to your .htaccess file, and use that as the user agent. Enter the URL of your site and hit enter. If you see a “403 Error” this means that the code is doing its job. If not the code must’ve gotten messed up while being copied into your .htaccess file, so try again.
Step 3 Adding More Bots
Now you are familiar with the code and how to test it, we can add more bots to the code. You must have noticed the repetition in the code, and by using the same logic, you can add a dozen more bots to be blocked by setting the same parameters. Cool huh!
SetEnvIfNoCase User-Agent (i-IS-evilBOT) keep_outAs you can see in the code above, now I am blocking the “i-IS-evilBOT” (which I just made up). Other than that the name of the bot is not case sensitive and you can add it as per your liking. Go to the Bots VS Browsers page and this time enter the user agent which I just created, and voila, you’ll see that this user agent which was added to my .htaccess file is also blocked! You can add as many bots as you want to be blocked separated with a pipe character “|”
Conclusion
I said in the beginning that there are many plugins which can do the same thing and you can avoid this editing. But by manually editing the .htaccess file you can effectively block bad user-agents and bots with better efficiency and better site performance!
I was looking for a solution to optimize my site, in a very cheap way. Often a Content Delivery Network is a good solution but not cheap, so I used Google App Engine as a CDN with Ubuntu.
Step 0: A Little Bit of Theory
Things like stylesheets, images and videos are often the major hit taken by a webserver when a webpage is loaded. It’s been proven that loading these assets from different domains helps the browser with multi-tasking, because it doesn’t have to wait until Asset 1 on the domain example.com is loaded to start downloading Asset 2 on the same domain. There are a number of approaches to this, and in this tutorial we’ll analyze three of them.
The First Approach
Most people simply create sub-domains such as “images.domain.com”, “styles.domain.com” and so on. The assets are then called from the sub-domains, so the browser ‘thinks’ it’s coming from a different location, when in reality, they normally always target the same structure.
This approach is useful, and there’s a noticeable difference in loading times. A downside to it is that you’re still hitting your webserver, and now even harder, as you’re making multiple connections at once to it. If you are loading images or small files, that’s OK, but things will start to get uglier if you try to load videos or heavier files; and also, especially for cheap hosting, it’s not always possible to create sub-domains.
The Second Approach
This consists of having a second webserver only to load assets while your main webserver deals with the other calls. You have two webservers using two different ports. The main webserver is the one responsible for all the requests, but will redirect every asset call to your second webserver. What people normally do here is use two different kinds of webservers. Most commonly Apache (as the main webserver) and lighttpd as the secondary webserver.
The concept is really pretty, but it also means you’ll now have to maintain two webservers. The second one (lighttpd) should really be a one off, as once it’s configured, it will just serve static content. Still, it’s two webservers on your server, and if anything goes wrong, it’s a bit difficult to troubleshoot.
The Third Approach
Basically it consists of hosting your assets somewhere else, where you won’t have to maintain or keep an eye on performance, as this server’s primary task is to serve static content. This heaven is called “Cloud Computing” and it’s a “buzz word” at the moment. Basically it consists of a network of servers in strategic places. We call it strategic places, as the servers are located near you. Well, not near you, but from your IP, it redirects you to the closest server, from where you’re going to be picking up the assets as they are needed.
It works pretty much as a load balancer, but based on location, instead of number of connections. It makes sure that the bits travel the shortest distance in order to get to you. In other words, if you’re in Italy (like me), why should you have to wait for the data to travel from the USA, if there’s a server just next door to you. There are some companies offering CDN for a very reasonable price, but today we’re going to be talking about free stuff!
Before We Start
Before I start with this tutorial, I have to make it clear that the form of CDN we’re going to be using here, is not truly CDN, as it doesn’t offer a very high scalability, and hasn’t been developed for the sole purpose of serving static files. This means it won’t have the same high performance of a service designated specifically for this task. For some (like myself), it won’t make such a huge difference, as this method is still better than nothing, and is immensely faster than many servers around. Also for most people who use Hosting Companies and have limited bandwidth, this will be a huge improvement.
Step 1: Google Is Your Friend
Create a Google Account. If you have a Gmail account that will do. I won’t explain it in detail, but visit here to create one. Sign up for a Google App Engine Application. And now…
Step 2: Let’s go! Create our CDN
Simply login to your newly created App Engine Account and click the button Create an Application, I named mine “mynewcdn”. I use Python with Ubuntu (but some steps are the same for Windows users) so:
With the default installation of Ubuntu, Python interpreter is already present in the system. Otherwise just install Python. If you’re Windows users you can download Python from Python.org.
Download the latest Google App Engine SDK for Python (currently at 1.5.5);
Create a folder called Projects and extract Google App Engine SDK for Python into it
fabrizio@fabrix:~/Projects$ unzip google_appengine_1.5.5.zip fabrizio@fabrix:~/Projects$ cd google_appengine fabrizio@fabrix:~/Projects/google_appengine$ mkdir mynewcdnand now you should have this (the name of the folder SHOULD to be the same as the name of the application)
fabrizio@fabrix:~/Projects/google_appengine$ ls appcfg.py dev_appserver.py mynewcdn tools BUGS gen_protorpc.py new_project_template VERSION bulkload_client.py google README bulkloader.py lib RELEASE_NOTES demos LICENSE remote_api_shell.pyNow inside of your folder (for me mynewcdn) you should copy all the folders with the static contents of your website (for example the folder /wp-content/uploads/). In my case I created a folder inside mynewcdn called fdicarlo with all data. Inside a folder with the name of the application that you created, make a file app.yaml. The content of this file should look as follows:
application: mynewcdn version: 1 runtime: python api_version: 1 handlers: - url: /fdicarlo static_dir: fdicarlo threadsafe: trueOf course you must replace mynewcdn with the name of your application and fdicarlo with the name of the folder of your static content. You can find more info about the app.yaml file on the Python Application Configuration page. Now the situation looks like this:
fabrizio@fabrix:~/Projects/google_appengine/mynewcdn$ ls app.yaml fdicarloAnd now:
fabrizio@fabrix:~/Projects/google_appengine/mynewcdn$ cd .. fabrizio@fabrix:~/Projects/google_appengine$ python appcfg.py update mynewcdnOnce the upload has finished, your CDN is ready at the address nameofapp.appspot.com, mine for example is http://mynewcdn.appspot.com/fdicarlo. To verify the CDN is working correctly try to view some pictures and/or files from the CDN.
Step 3: Configuration of CDN
When you have created the instance on the Google app engine, and have the URL of the app, the only thing left to do is to add it to the settings in WP Super Cache and test how the page works. If somewhere in those steps you have a feeling that nothing is happening, then try to clear your cached pages from enabled cache, in the other tab called “Contents” and save the settings. I used WP Super Cache because it’s useful (and powerful) also for the cache but you can use other plugins like CDN linker and the steps are similar.
In the field “Off-site URL” I insert http://mynewcdn.appspot.com/fdicarlo. Of course, you should to replace mynewcdn and fdicarlo with your name.
In the field “Include dirs” I put wp-content.
And in the last field “Exclude if substring” I suggest you to insert “php” to exclude php files. Set your parameters how you like, save and now you have configured your CDN. Now when you add pictures or other data in WordPress you should also copy to the local folder and update all with:
fabrizio@fabrix:~/Projects/google_appengine$ python appcfg.py update mynewcdnConclusion
I hope that has helped someone to create and start using Google CDN. Using a CDN is just one aspect of SEO and a slow performance is often caused by many factors. If you use a CDN, minifying and caching you can have good improvements to your blog so there’s really no reason not to try them.
Nothing hard here: simply paste the following code where you need to execute a custom query to the database. Don't forget to update the query on line 5!
<?php // Get any existing copy of our transient data if ( false === ( $special_query_results = get_transient( 'special_query_results' ) ) ) { // It wasn't there, so regenerate the data and save the transient $special_query_results = new WP_Query( 'cat=5&order=random&tag=tech&post_meta_key=thumbnail' ); set_transient( 'special_query_results', $special_query_results ); } // Use the data like you would have normally... ?>This code is using WordPress Transients API. Click here to view more useful examples of this API!
Credits: WordPress Codex.
While working on a project where we created a very cool gallery powered totally by WordPress attachments and a custom post type, we found a need to add additional fields to the WordPress media uploader. These additional fields allowed us to give each photographer credit by adding photographer name, and their URL on each image page. WordPress stores images as posts in the attachment post type, so adding meta data is just like adding custom fields. Because the WordPress attachments does not have a custom fields UI, we have to add a custom fields to the media uploader in order to collect the meta data. In this article, we will show you how to add additional fields to the WordPress Media Uploader.
We will be using the following filters to make the change: attachment_fields_to_edit and attachment_fields_to_save
For a project like this, we highly recommend that you create a site-specific plugin and add the following code. However, you can still add the codes in your theme’s functions.php file to make it work.
/** * Add Photographer Name and URL fields to media uploader * * @param $form_fields array, fields to include in attachment form * @param $post object, attachment record in database * @return $form_fields, modified form fields */ function be_attachment_field_credit( $form_fields, $post ) { $form_fields['be-photographer-name'] = array( 'label' => 'Photographer Name', 'input' => 'text', 'value' => get_post_meta( $post->ID, 'be_photographer_name', true ), 'helps' => 'If provided, photo credit will be displayed', ); $form_fields['be-photographer-url'] = array( 'label' => 'Photographer URL', 'input' => 'text', 'value' => get_post_meta( $post->ID, 'be_photographer_url', true ), 'helps' => 'Add Photographer URL', ); return $form_fields; } add_filter( 'attachment_fields_to_edit', 'be_attachment_field_credit', 10, 2 ); /** * Save values of Photographer Name and URL in media uploader * * @param $post array, the post data for database * @param $attachment array, attachment fields from $_POST form * @return $post array, modified post data */ function be_attachment_field_credit_save( $post, $attachment ) { if( isset( $attachment['be-photographer-name'] ) ) update_post_meta( $post['ID'], 'be_photographer_name', $attachment['be-photographer-name'] ); if( isset( $attachment['be-photographer-url'] ) ) update_post_meta( $post['ID'], 'be_photographer_url', esc_url( $attachment['be-photographer-url'] ) ); return $post; } add_filter( 'attachment_fields_to_save', 'be_attachment_field_credit_save', 10, 2 ); ?>The code above will add two text fields to the Media Uploader called Photographer Name and Photographer URL. You can see that in the screenshot below:
Explanation of the code: In the first function, we are simply using an array to specify the field’s label, input type, value, and help text. The second function is checking to see if a value has been set for those fields. IF the value is set, then the post metadata is updated.
If you want to display the fields in your attachments template, then simply paste the following codes inside the loop:
echo get_post_meta($post->ID, 'be_photographer_url', true);If you want to display the fields for your featured image in your archive template or any other template, then simply use:
echo get_post_meta(get_post_thumbnail_id(), 'be_photographer_url', true);We hope that you enjoyed this article. For those who don’t know how to create an attachment’s template, don’t worry. In the next article, we will cover how to create an attachment’s template in WordPress.
Hat Tip to Bill Erickson for showing us how to do this.
Paste this code into your functions.php file. Save the file, and you're done.
function modify_post_mime_types( $post_mime_types ) { // select the mime type, here: 'application/pdf' // then we define an array with the label values $post_mime_types['application/pdf'] = array( __( 'PDFs' ), __( 'Manage PDFs' ), _n_noop( 'PDF <span class="count">(%s)</span>', 'PDFs <span class="count">(%s)</span>' ) ); // then we return the $post_mime_types variable return $post_mime_types; } // Add Filter Hook add_filter( 'post_mime_types', 'modify_post_mime_types' );Note that this code snippet can be used for other file types as well as .swf, .avi, .mov, etc.
Thanks to WP Tuts for the nice code snippets!