Please vote on the question and any answers you find useful by clicking on the UP arrow on the left hand side of the question or answer.

As with many others who are now viewing this post, I have been reading various blogs, forums, and discussion groups to learn and improve my wordpress skills. Over the past 12 months I have been on a mission to substitute my use of plugins by adding code to my functions.php file instead. While I completely agree that plugins are very useful in many situations my experience proved that in 90% of usage cases although a plugin might exist, actually utilizing it could create unnecessary complications and compatibility issues. Additionally in a great deal of cases such plugins added menus and other admin elements which I don't want or need.

More often than not I have found that by analyzing the code of plugins I was able to strip out the piece of code I wanted and hard code it into my functions.php. This provided me with the exact functionality I needed without having to include unnecessary elements.

So, the purpose of this post is my attempt to engage you, the reader/admin/developer, to share with me and other here any code bits which you find useful and have added to your theme's function.php file to extend or enhance WordPress without utilizing a plugin.

When you submit a response here please kindly give each code bit a title, let us know if with what version of wordpress you know its compatible with, include whatever description you feel best describes its function and (if applicable) include a link to the original plugin or source where you found the information.

I am looking forward to all your responses and will of course continually add my own new finds whenever I find them.

closed as not constructive by Rarst Feb 15 '12 at 12:44

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 13
    Considering the first 5 answers were by the OP and the question seems more geared at collecting an array of responses rather than a single, definitive answer, this should be a community wiki. – EAMann Sep 9 '10 at 14:43
  • 17
    All answers not related to a theme should be removed. This thread is a good example for bad coding practices. – fuxia Jun 13 '11 at 12:09
  • 17
    I think it'd be better to encourage people to create a custom functionality plugin instead of using their theme's functions.php – Ian Dunn Jan 16 '12 at 18:49
  • 3 The pure number of page views is not an indicator for quality. We should encourage specific questions with specific answers and good coding practices. This thread is the opposite. – fuxia Feb 22 '12 at 2:44
  • 6 Discuss it on Meta where people can see your arguments better. :) – fuxia Feb 24 '12 at 17:10

108 Answers 108

Add custom styles to TinyMCE editor

Sometimes users and clients get confused about how their content is displayed in the editor versus how it is displayed on the front-end. Copying just a few relevant lines from your main stylesheet into your new tinymce.css can help a lot:

function custom_mce_css($wp) {
    return $wp .= ',' . get_bloginfo('stylesheet_directory') . '/css/tinymce.css';
add_filter( 'mce_css', 'custom_mce_css' );
  • Nice. Ive just discoverd there is a solution by Seamus Leahy that extends all this one step further by adding a body class to tinymce. – Michal Mau Jan 20 '11 at 2:03
  • Isn't this already covered by core & editor styles? – kaiser Feb 1 '11 at 7:52
  • I prefer to create a stylesheet for both front-end and TinyMCE in one go. Then I use core functionality of the add_editor_style() function to include the stylesheet and ensure it's loaded when TinyMCE loads. Codex article at – Philip Downer Sep 13 '11 at 20:42

Display Posts from Different Custom Post Types on homepage

By dropping the following code on the bottom of this post into your functions.php file you can get wordpress to automatically display posts from different custom post types you have created. Currently by default wordpress only display posts which belong to the default "posts" post type.

In the example provided below you will need to change the section which calls:

$query->set( 'post_type', array('post', 'page', 'services', 'attachment'));

With your own custom post types which you would like to include in the homepage post list results. In this case we are asking wordpress to return to us all posts belonging to the default "post" and "page" post_type then asking wordpress to also include the custom post type we created for "services" and finally the default wordpress post type of "attachment" which just means that anytime something is added to the media library it will automatically get displayed on the homepage as a separate entry.

// make sure to edit the post types you wanted included in the list below
add_filter( 'pre_get_posts', 'my_homepage_post_list' );
function my_homepage_post_list ( $query ) {
    if ( is_home() && false == $query->query_vars['suppress_filters'] )
        $query->set( 'post_type', array('post', 'page', 'services', 'attachment'));
    return $query;

You can also utilize this custom query in different locations, such as in a custom feed through something like this

if (( is_home() && false == $query->query_vars['suppress_filters'] ) || is_feed())

Enable Numeric Pagination

Tested on: Wordpress 3.0.1

/* Numeric Pagination ********************************************/

function numeric_pagination ($pageCount = 9, $query = null) {

 if ($query == null) {
  global $wp_query;
  $query = $wp_query;

 if ($query->max_num_pages <= 1) {

 $pageStart = 1;
 $paged = $query->query_vars['paged'];

 // set current page if on the first page
 if ($paged == null) {
  $paged = 1;

 // work out if page start is halfway through the current visible pages and if so move it accordingly
 if ($paged > floor($pageCount / 2)) {
  $pageStart = $paged - floor($pageCount / 2);

 if ($pageStart < 1) {
  $pageStart = 1;

 // make sure page start is
 if ($pageStart + $pageCount > $query->max_num_pages) {
  $pageCount = $query->max_num_pages - $pageStart;

 <div id="archive_pagination">
 if ($paged != 1) {
 <a href="<?php echo get_pagenum_link(1); ?>" class="numbered page-number-first"><span>&lsaquo; <?php _e('<< First', 'global'); ?></span></a>
 // first page is not visible...
 if ($pageStart > 1) {
  //echo 'previous';
 for ($p = $pageStart; $p <= $pageStart + $pageCount; $p ++) {
  if ($p == $paged) {
  <span class="numbered page-number-<?php echo $p; ?> current-numeric-page"><?php echo $p; ?></span>
<?php } else { ?>
  <a href="<?php echo get_pagenum_link($p); ?>" class="numbered page-number-<?php echo $p; ?>"><span><?php echo $p; ?></span></a>

 // last page is not visible
 if ($pageStart + $pageCount < $query->max_num_pages) {
  //echo "last";
 if ($paged != $query->max_num_pages) {
  <a href="<?php echo get_pagenum_link($query->max_num_pages); ?>" class="numbered page-number-last"><span><?php _e('>> Last', 'global'); ?> &rsaquo;</span></a>
<?php } ?>


Auto Include Google Analytics Code

Tested on: Wordpress 3.1 RC3

I've been using this script on all of my sites since WordPress 2.3.0 ... it just adds the standard Google tracking scripts to the footer.

// Add Google Analytics Tracking Code
function add_google_analytics() {
<script type="text/javascript">
    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
    document.write(unescape("%3Cscript src='" + gaJsHost + "' type='text/javascript'%3E%3C/script%3E"));
<script type="text/javascript">
    try {
        var pageTracker = _gat._getTracker("UA-XXXXXXX-X");
    } catch(err) {}</script>

add_action('wp_footer', 'add_google_analytics');

Just be sure to replace UA-XXXXXXX-X with your own Google tracking code...

  • thanks for the share. I have been using this one as well but I would be curious to know if you are aware how this can be modified so that specific tags, post type pages or even posts themself can be passed additional values automatically making use of the campaign tracking var capabilities google provides. Additionally, what would need to be added if we wanted to add this to the footer of all admin pages to track admin activity? – Sep 17 '10 at 6:53
  • 1
    Not sure about adding campaign tracking variables only because I haven't had a need for that yet. But to add the same scripts to admin pages, you'd just use add_action('admin_footer', 'add_google_analytics'); to hook on to the footer of admin pages. – EAMann Sep 17 '10 at 13:08

Check if a post has embedded content.

Check if a post has embedded content, works inside the loop using the current post's ID, or alternatively can be passed an ID to determine the post to check for embedded content.

function has_embed( $post_id = false ) {
    if( !$post_id ) $post_id = get_the_ID();
    else $post_id = absint( $post_id );
    if( !$post_id ) return false;

    $post_meta = get_post_custom_keys( $post_id );
    $post_meta = array_map( 'trim' , $post_meta );

    foreach( $post_meta as $meta ) {
        if( '_oembed' != substr( $meta , 0 , 7 ) )
        return true;
    return false;

You'd use the function in the same way you check if a post has a tag..

if( has_embed() ) {
   // do whatever

Function returns true if an embed is found, false on fail.

  • Interesting, but I'm wondering, why would you use it? What kind of applications does it have? – matt Dec 5 '10 at 5:08
  • Checking if a post has an embed on a page that displays excerpts would be one use(and it's the original use case i wrote it for). Other possible use cases would be with users who write their own theme templates and want to provide functionality dependant on whether a post(or type) has embedded content, without the need for a filter on the_content or numerous get_post_custom_keys calls. – t31os Dec 5 '10 at 9:34

Use figure and figcaption for captions

Tested on: WordPress 3.1.3

(Credits to WP Engineer:

function mytheme_caption( $attr, $content = null ) {
    $output = apply_filters( 'img_caption_shortcode', '', $attr, $content );
    if ( $output != '' )
        return $output;

    extract( shortcode_atts ( array(
    'id' => '',
    'align' => 'alignnone',
    'width'=> '',
    'caption' => ''
    ), $attr ) );

    if ( 1 > (int) $width || empty( $caption ) )
        return $content;

    if ( $id ) $id = 'id="' . $id . '" ';

    return '<figure ' . $id . 'class="wp-caption ' . $align . '" style="width: ' . $width . 'px">'
. do_shortcode( $content ) . '<figcaption class="wp-caption-text">' . $caption . '</figcaption></figure>';

add_shortcode( 'wp_caption', 'mytheme_caption' );
add_shortcode( 'caption', 'mytheme_caption' );

List all constants for information and debugging

Tested on: Wordpress 3.0.1

Will only display the information if you are a logged in user

if ( is_user_logged_in() ) {
    print_r( @get_defined_constants() );

Here is version with optional filter that will partially match constant names and values:

function constants($filter = false) {

        $constants = get_defined_constants();

        if( $filter ) {

            $temp = array();

            foreach ( $constants as $key => $constant )
                if( false !== stripos( $key, $filter ) || false !== stripos( $constant, $filter ) )
                    $temp[$key] = $constant;

            $constants = $temp;

        ksort( $constants );
        var_dump( $constants );

Here are some nice shortcodes for you to use:

1. Easy to add twitter & facebook share button Shortcode

function shreplz() {
   return '
    <div class="sharebox">
    <div class="twittme"><a href="" class="twitter-share-button" data-count="horizontal">Tweet</a><script type="text/javascript" src="//"></script></div>
    <div class="shareface"><a name="fb_share"></a> <script src="" type="text/javascript"></script></div>
    <br style="clear: left;" />
add_shortcode('sharethis', 'shreplz');
// how to use: [sharethis]

2. Easy Remote site snapshot using Wordpress API shortcode

function wpr_snap($atts, $content = null) {
            "snap" => '',
            "url" => '',
            "alt" => 'My image',
            "w" => '400', // width
            "h" => '300' // height
        ), $atts));

    $img = '<img src="' . $snap . '' . urlencode($url) . '?w=' . $w . '&h=' . $h . '" alt="' . $alt . '"/>';
        return $img;

add_shortcode("snap", "wpr_snap");
//how to use: [snap url="" alt="Cool Site!" w="300px" h="200px"]

3. Easy to use & embed iFrame Shortcode

function GenerateIframe( $atts ) {
    extract( shortcode_atts( array(
        'href' => 'http://the-url',
        'height' => '550px',
        'width' => '600px',     
    ), $atts ) );

    return '<iframe src="'.$href.'" width="'.$width.'" height="'.$height.'"> <p>Your Browser does not support Iframes.</p></iframe>';
add_shortcode('iframe', 'GenerateIframe');
// how to use: [iframe href="" height="480" width="640"]

4. Easy to include remote file / doc with Shortcode

function getfile_content( $atts ) {
  extract( shortcode_atts( array(
    'fileurl' => ''
  ), $atts ) );

  if ($fileurl!='')
    return @file_get_contents($fileurl);

add_shortcode( 'getfile', 'getfile_content' );
// how to use: [getfile fileurl=""]

Here are some Comments Related Snippets:

1. close the ability to comment globaly

function closeCommentsGlobaly($data) { return false; }
add_filter('comments_number', 'closeCommentsGlobaly');
add_filter('comments_open', 'closeCommentsGlobaly');

2. Give admin a different Css Class for he's comments

if (1 == $comment->user_id)
echo 'siteadmin'; // pick your class here

3. a really cool rich with data list of comments - gr8 for custom locked page

$comments = get_comments( array(
    'number'    => 10, // how many comments
    'status'    => 'approve' // type of comments
) );

foreach($comments as $eachComment){

// collect the data and assign it
$commentID = comment_ID;
$commentAuthorEmail = $eachComment->comment_author_email;
$commentPostId = $eachComment->comment_post_ID;
$commentPostTitle = get_the_title( $commentPostId );
$commentPostUrl = get_permalink( $commentPostId );
$comment_sidebarnumber = get_comments_number( $commentPostId );

global $wpdb;
$userCommentCount = $wpdb->get_var('SELECT COUNT('.$commentID.') FROM ' . $wpdb->comments. ' WHERE comment_author_email = "' . $commentAuthorEmail . '"');

    echo    '<div style="border: 1px solid #ccc; padding: 10px;">';
    echo    '<ul style="margin: 0px;">';
    echo    '<li>Name: '. $eachComment->comment_author .'</li>';
    echo    '<li>Commented about: <a href="'.$commentPostUrl.'">'. $commentPostTitle .'</a></li>';
    echo    '<li>Commented On: '. $eachComment->comment_date .'</li>';
    echo    '<li>Commneter Site: '. $eachComment->comment_author_email .'</</li>';
    echo    '<li>Commenter Email: '. $eachComment->comment_author_email .'</</li>';
    echo    '<li>This Commenter'. $eachComment->comment_author .' Commented '. $userCommentCount .' on your site</</li>';
    echo    '</ul>';
    echo    '<p style="padding: 10px;"><strong>'. $eachComment->comment_author .' wrote</strong>: '. $eachComment->comment_content .'</p>';
    echo    '</div>';


Conditional to check for hierarchy descendant

A conditional function to check if the current page is a descendant of the ID given to it. Useful for determining if a page is a grandchild, great-grandchild or father down the hierarchy tree.

function is_tree($pid) {      // $pid = The ID of the page we're looking for pages underneath
    global $post;         // load details about this page

    $anc = get_post_ancestors( $post->ID );
    foreach($anc as $ancestor) {
        if(is_page() && $ancestor == $pid) {
            return true;
               return true;   // we're at the page or at a sub page
               return false;  // we're elsewhere
  • I've been looking for this for awhile. Thanks for putting it together! Can I ask for a bit of clarification on use case. Ideally, I would like to use this in my menu listings so that if i have a top level parent menu across the top of the site that only shows Gen 1 elements. When I'm on a Gen 2-3 element, the Gen1 element can be highlighted via a "current-parent" css attribute. Is this possible? – Scott B Feb 11 '11 at 5:48

Create a conditional tag for custom taxonomies

In this example, 'student' was a custom post type, and 'stud_cat' was the custom taxonomy. Use has_student(null) for the conditional

    function has_student( $student, $_post = null ) {
    if ( !empty( $student ) )
        return false;
    if ( $_post )
        $_post = get_post( $_post );
        $_post =& $GLOBALS['post'];
    if ( !$_post )
        return false;
    $r = is_object_in_term( $_post->ID, 'studcat', $student );
    if ( is_wp_error( $r ) )
        return false;
    return $r;
  • 1
    I think this gets replaced with has_term() now that 3.1 is released? – Rarst Feb 25 '11 at 23:32

Make WordPress Editor Allow iFrames

// make TinyMCE allow iframes
add_filter('tiny_mce_before_init', create_function( '$a',
'$a["extended_valid_elements"] = "iframe[id|class|title|style|align|frameborder|height|longdesc|marginheight|marginwidth|name|scrolling|src|width]"; return $a;') );

Add auto-update/plugin-installer on you localhost

define ('FS_METHOD', 'direct');

Put this in your wp-config.php.

  • so this automatically updates any/all of your plugins whenever something new is available? – Nov 5 '10 at 15:44
  • Nope, you just don't need a ftp login to update your core or plugins locally – Horttcore Nov 9 '10 at 8:11

Resize large image on upload

Image will be resize according to the large size in your media settings.

/**resize on upload to the largest size in media setting */

function replace_uploaded_image($image_data) {
// if there is no large image : return
if (!isset($image_data['sizes']['large'])) return $image_data;

// path to the uploaded image and the large image
$upload_dir = wp_upload_dir();
$uploaded_image_location = $upload_dir['basedir'] . '/' .$image_data['file'];
$large_image_location = $upload_dir['path'] . '/'.$image_data['sizes']['large']['file'];

// delete the uploaded image

// rename the large image

// update image metadata and return them
$image_data['width'] = $image_data['sizes']['large']['width'];
$image_data['height'] = $image_data['sizes']['large']['height'];

return $image_data;
  • Does this mean that the original large file uploaded is actually replaced? My php is not great, but the answer seems to be yes? – davemac Feb 20 '11 at 1:26
  • @davemac I realise this is very old now, but from what I understand of the code, the original image file is resized to the same dimensions as the 'large' image size set in the WordPress settings screen. Which is great but then you just end up with 2 images of the same size. I'd suggest manually setting the values to make the original image only as big as the largest file you will ever realistically use on your site. Then you have an almost original image to work with in future. – Phill Healey Nov 25 '16 at 19:22
  • That makes more sense, thanks Phill – davemac Feb 28 '17 at 3:41

Easy WordPress Security Fixes

Security through obscurity is the name of the game here. These functions do three different things.

  1. Remove the version string from the code. No point in telling folks what version we're running.
  2. Removes any error messages (Wrong Password, No Such User, etc.) from admin login screens
  3. When the admin posts a comment, a CSS class is added. This removes the admin name in comments.

    remove_action('wp_head', 'wp_generator');
    //HIDE LOGIN ERROR MESSAGES (Wrong Password, No Such User etc.)
    add_filter('login_errors',create_function('$a', "return null;"));
    // Remove admin name in comments class
    // Source:
    function remove_comment_author_class( $classes ) {
        foreach( $classes as $key => $class ) {
            if(strstr($class, "comment-author-")) {
                unset( $classes[$key] );
        return $classes;
    add_filter( 'comment_class' , 'remove_comment_author_class' );
  • Removing the Wordpress version number is bad practice. It is much safer to keep your Wordpress updated with the latest security fixes AT ALL TIMES. Added bonus: wanna-be script kiddies will move along to older versions. – knutole Jan 12 '14 at 16:30
  • 2
    @knotole, it is not bad practice. It is your opinion... albeit this is pretty standard. – Jeremy Oct 20 '14 at 20:13

Replace Default Gravatar with Custom Image

All you'll need to customize is the path to your default image.

function custom_gravatar($avatar_defaults) {
    $logo = get_bloginfo('template_directory') . '/images/icons/gravatar_logo.jpg'; //Change to whatever path you like.
    $avatar_defaults[$logo] = get_bloginfo('name');
    return $avatar_defaults;
add_filter( 'avatar_defaults', 'custom_gravatar' );

Show template files being included

Display inline comment with Template File and get_template_part files being included when rendering pages. Handy for troubleshooting multipart templates.

function template_snoop(){
    $args = func_get_args();
    if( !is_admin() and $args[0] ){
        if( $args[0] == 'template_include' ) {
            echo "<!-- Base Template: {$args[1]} -->\n";
        } elseif( strpos($args[0],'get_template_part_') === 0 ) {
            global $last_template_snoop;
            if( $last_template_snoop )
                echo "\n\n<!-- End Template Part: {$last_template_snoop} -->";
            $tpl = rtrim(join('-',  array_slice($args,1)),'-').'.php';
            echo "\n<!-- Template Part: {$tpl} -->\n\n";
            $last_template_snoop = $tpl;

Exclude child categories of a specific category.

Pretty straight forward, but I couldn't find anyone doing exactly what I needed. Also it will display the post if the parent category is selected, except if that post has a child category of that parent selected.

   /* this code excludes all of the children of (category id = 20) posts
       on the HOME page, but allows parent (category id = 20) to be shown. */

    function exclude_category_children($query) {
        $child_cats = (array) get_term_children('20', 'category');
        if ( $query->is_home ) {
        $query->set('category__not_in', $child_cats);
        return $query;
    add_filter('pre_get_posts', 'exclude_category_children');

Auto Clean SEO Slugs without removing functionality

Tested on: Wordpress 3.0.1

By adding this code to your functions.php file wordpress will automatically clean up the slug URL title by removing all unnecessary words. I have also extended the capabilities with additional customizations which hide the screen option for slug as well as the metabox. By including the code below any new post you create will automatically get shortened and you will still have the ability to manually edit the slug by clicking on the url under the post title and saving the post.

   add_filter('name_save_pre', 'seo_slugs', 0);
   function seo_slugs($slug) {
    // We don't want to change an existing slug
 if ($slug) return $slug;
 global $wpdb;
 $seo_slug = strtolower(stripslashes($_POST['post_title']));
 $seo_slug = preg_replace('/&.+?;/', '', $seo_slug); // kill HTML entities
    // kill anything that is not a letter, digit, space or apostrophe
 $seo_slug = preg_replace ("/[^a-zA-Z0-9 \']/", "", $seo_slug);
    // Turn it to an array and strip common words by comparing against c.w. array
 $seo_slug_array = array_diff (split(" ", $seo_slug), seo_slugs_stop_words());
    // Turn the sanitized array into a string
 $seo_slug = join("-", $seo_slug_array);
 return $seo_slug;
   function seo_slugs_stop_words () {
   return array ("a", "able", "about", "above", "abroad", "according", "accordingly", "across", "actually", "adj", "after", "afterwards", "again", "against", "ago", "ahead", "ain't", "all", "allow", "allows", "almost", "alone", "along", "alongside", "already", "also", "although", "always", "am", "amid", "amidst", "among", "amongst", "an", "and", "another", "any", "anybody", "anyhow", "anyone", "anything", "anyway", "anyways", "anywhere", "apart", "appear", "appreciate", "appropriate", "are", "aren't", "around", "as", "a's", "aside", "ask", "asking", "associated", "at", "available", "away", "awfully", "b", "back", "backward", "backwards", "be", "became", "because", "become", "becomes", "becoming", "been", "before", "beforehand", "begin", "behind", "being", "believe", "below", "beside", "besides", "best", "better", "between", "beyond", "both", "brief", "but", "by", "c", "came", "can", "cannot", "cant", "can't", "caption", "cause", "causes", "certain", "certainly", "changes", "clearly", "c'mon", "co", "co.", "com", "come", "comes", "concerning", "consequently", "consider", "considering", "contain", "containing", "contains", "corresponding", "could", "couldn't", "course", "c's", "currently", "d", "dare", "daren't", "definitely", "described", "despite", "did", "didn't", "different", "directly", "do", "does", "doesn't", "doing", "done", "don't", "down", "downwards", "during", "e", "each", "edu", "eg", "eight", "eighty", "either", "else", "elsewhere", "end", "ending", "enough", "entirely", "especially", "et", "etc", "even", "ever", "evermore", "every", "everybody", "everyone", "everything", "everywhere", "ex", "exactly", "example", "except", "f", "fairly", "far", "farther", "few", "fewer", "fifth", "first", "five", "followed", "following", "follows", "for", "forever", "former", "formerly", "forth", "forward", "found", "four", "from", "further", "furthermore", "g", "get", "gets", "getting", "given", "gives", "go", "goes", "going", "gone", "got", "gotten", "greetings", "h", "had", "hadn't", "half", "happens", "hardly", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "hello", "help", "hence", "her", "here", "hereafter", "hereby", "herein", "here's", "hereupon", "hers", "herself", "he's", "hi", "him", "himself", "his", "hither", "hopefully", "how", "howbeit", "however", "hundred", "i", "i'd", "ie", "if", "ignored", "i'll", "i'm", "immediate", "in", "inasmuch", "inc", "inc.", "indeed", "indicate", "indicated", "indicates", "inner", "inside", "insofar", "instead", "into", "inward", "is", "isn't", "it", "it'd", "it'll", "its", "it's", "itself", "i've", "j", "just", "k", "keep", "keeps", "kept", "know", "known", "knows", "l", "last", "lately", "later", "latter", "latterly", "least", "less", "lest", "let", "let's", "like", "liked", "likely", "likewise", "little", "look", "looking", "looks", "low", "lower", "ltd", "m", "made", "mainly", "make", "makes", "many", "may", "maybe", "mayn't", "me", "mean", "meantime", "meanwhile", "merely", "might", "mightn't", "mine", "minus", "miss", "more", "moreover", "most", "mostly", "mr", "mrs", "much", "must", "mustn't", "my", "myself", "n", "name", "namely", "nd", "near", "nearly", "necessary", "need", "needn't", "needs", "neither", "never", "neverf", "neverless", "nevertheless", "new", "next", "nine", "ninety", "no", "nobody", "non", "none", "nonetheless", "noone", "no-one", "nor", "normally", "not", "nothing", "notwithstanding", "novel", "now", "nowhere", "o", "obviously", "of", "off", "often", "oh", "ok", "okay", "old", "on", "once", "one", "ones", "one's", "only", "onto", "opposite", "or", "other", "others", "otherwise", "ought", "oughtn't", "our", "ours", "ourselves", "out", "outside", "over", "overall", "own", "p", "particular", "particularly", "past", "per", "perhaps", "placed", "please", "plus", "possible", "presumably", "probably", "provided", "provides", "q", "que", "quite", "qv", "r", "rather", "rd", "re", "really", "reasonably", "recent", "recently", "regarding", "regardless", "regards", "relatively", "respectively", "right", "round", "s", "said", "same", "saw", "say", "saying", "says", "second", "secondly", "see", "seeing", "seem", "seemed", "seeming", "seems", "seen", "self", "selves", "sensible", "sent", "serious", "seriously", "seven", "several", "shall", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "since", "six", "so", "some", "somebody", "someday", "somehow", "someone", "something", "sometime", "sometimes", "somewhat", "somewhere", "soon", "sorry", "specified", "specify", "specifying", "still", "sub", "such", "sup", "sure", "t", "take", "taken", "taking", "tell", "tends", "th", "than", "thank", "thanks", "thanx", "that", "that'll", "thats", "that's", "that've", "the", "their", "theirs", "them", "themselves", "then", "thence", "there", "thereafter", "thereby", "there'd", "therefore", "therein", "there'll", "there're", "theres", "there's", "thereupon", "there've", "these", "they", "they'd", "they'll", "they're", "they've", "thing", "things", "think", "third", "thirty", "this", "thorough", "thoroughly", "those", "though", "three", "through", "throughout", "thru", "thus", "till", "to", "together", "too", "took", "toward", "towards", "tried", "tries", "truly", "try", "trying", "t's", "twice", "two", "u", "un", "under", "underneath", "undoing", "unfortunately", "unless", "unlike", "unlikely", "until", "unto", "up", "upon", "upwards", "us", "use", "used", "useful", "uses", "using", "usually", "v", "value", "various", "versus", "very", "via", "viz", "vs", "w", "want", "wants", "was", "wasn't", "way", "we", "we'd", "welcome", "well", "we'll", "went", "were", "we're", "weren't", "we've", "what", "whatever", "what'll", "what's", "what've", "when", "whence", "whenever", "where", "whereafter", "whereas", "whereby", "wherein", "where's", "whereupon", "wherever", "whether", "which", "whichever", "while", "whilst", "whither", "who", "who'd", "whoever", "whole", "who'll", "whom", "whomever", "who's", "whose", "why", "will", "willing", "wish", "with", "within", "without", "wonder", "won't", "would", "wouldn't", "x", "y", "yes", "yet", "you", "you'd", "you'll", "your", "you're", "yours", "yourself", "yourselves", "you've", "z", "zero");

When adding the additional code below to your functions.php file it will remove/hide the slug option for the screen options dropdown as well as the metabox.

   function hide_slug_options() {
 global $post;
 global $pagenow;
 $hide_slugs = "<style type=\"text/css\">#slugdiv, #edit-slug-box, [for=\"slugdiv-hide\"] { display: none; }</style>\n";
 if (is_admin() && $pagenow=='post-new.php' OR $pagenow=='post.php') print($hide_slugs);
   add_action( 'admin_head', 'hide_slug_options'  );

is_tree() conditional Function

/* Adapted from csstricks with addition of
ancestors .... use = if(is_tree($id)) { // do stuff } ... Returns true if the
page is  = $id OR any of it's children OR descendants */

function is_tree($pid) {      // $pid = The ID of the page we're looking for pages underneath
  global $post;         // load details about this page
  $ancestors = get_post_ancestors($post);
    return true;   // we're at the page or at a sub page
    return false;  // we're elsewhere 

Display the users that have submitted the most comments without a plugin

function top_comment_authors($amount = 5) {
global $wpdb;
$results = $wpdb->get_results('
    COUNT(comment_author_email) AS comments_count, comment_author_email, comment_author, comment_author_url
    FROM '.$wpdb->comments.'
    WHERE comment_author_email != "" AND comment_type = "" AND comment_approved = 1
    GROUP BY comment_author_email
    ORDER BY comments_count DESC, comment_author ASC
    LIMIT '.$amount
$output = "<ul>";
foreach($results as $result) {
    $output .= "<li>".$result->comment_author."</li>";
$output .= "</ul>";
echo $output;

Other options you can call: $result->comment_author_email $result->comments_count $result->comment_author_url

Automatically create a new page upon activating a theme

if (isset($_GET['activated']) && is_admin()){
    $new_page_title = 'This is the page title';
    $new_page_content = 'This is the page content';
    $new_page_template = ''; //ex. template-custom.php. Leave blank if you don't want a custom page template.

//don't edit under this line
$page_check = get_page_by_title($new_page_title);
$new_page = array(
    'post_type' => 'page',
    'post_title' => $new_page_title,
    'post_content' => $new_page_content,
    'post_status' => 'publish',
    'post_author' => 1,
    $new_page_id = wp_insert_post($new_page);
        update_post_meta($new_page_id,'_wp_page_template', $new_page_template);

Automatically adding header images from directory location

Within the default them which comes with wordpress you will notice an additional theme menu which gets activated that lets you select a header image to be utilized. Within the default theme code these images are hardcoded into the functions.php file. The code below allows wordpress to automatically pick up new images based upon a specific header image directly you can create on your server (or within your themes folder).

It will automatically include any .jpg or .jpeg files. Every image must have a associating thumbnail file but this can just be a copy of the original with a different name with a file name that has to end in "-thumbnail". The associating name is used as the description in the headers appearance settings and underscores are automatically replaced with spaces. (e.g. My_Header_Image_A.jpg, My_Header_Image_A=thumbnail.jpg will have a description automatically presented a “My Header Image A”)

if ($handle = opendir( TEMPLATEPATH . '/images/headers/') ) {
    $headers = array();
    while (false !== ($file = readdir($handle))) {
        $pos = strrpos( $file, '.' );
        if( $pos !== false && $pos > 0 ) {
            $file_name = substr( $file, 0, $pos );
            if( strpos( $file_name, "-thumbnail" ) === false ) {
                $file_ext = substr( $file, $pos+1 );
                $file_ext_low = strtolower( $file_ext );
                if( $file_ext_low == "jpg" || $file_ext_low == "jpeg" ) {
                    $headers[$file_name] = array (
                    'url' => '%s/images/headers/' . $file,
                    'thumbnail_url' => '%s/images/headers/' . $file_name ."-thumbnail." . $file_ext,
                    'description' => __( str_replace( "_", " ", $file_name ), 'twentyten' )
register_default_headers( $headers );

Get the Users Real IP Address whenever possible

Tested on: Wordpress 3.0.1

If you're using a proxy or load balancer, adding this to your wp-config.php file or functions.php

// Gets the user's real IP address

$_SERVER['REMOTE_ADDR'] = getRealIpAddress();
function getRealIpAddress( $validate = true ) {
    if ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $ip = trim($ips[count($ips) - 1]);
    } elseif ( isset($_SERVER['HTTP_X_REAL_IP']) && !empty($_SERVER['HTTP_X_REAL_IP']) ) {
        $ip = $_SERVER['HTTP_X_REAL_IP'];
    } elseif ( isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP']) ) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];

    if ( $validate && function_exists('filter_var') &&  filter_var($ip, FILTER_VALIDATE_IP, array('flags' => FILTER_FLAG_IPV4, FILTER_FLAG_NO_PRIV_RANGE, FILTER_FLAG_NO_RES_RANGE)) )
        return $ip;
    elseif ( $validate )
        return long2ip(ip2long($ip));

    return $ip;
  • 1
    what does this do exactly? – Sep 14 '10 at 2:21
  • When a user is behind a proxy or load balancer, then anything that grabs that user's IP address using the superglobal $_SERVER['REMOTE_ADDR'] will see the proxy or load balancer's IP address. The proxy/lb in return puts the user's original IP address in the X-Forwarded-For X-Real-Ip, or Client-Ip headers (depending on the proxy/lb configuration). Thus, when commenting (or posting, but that's less relevant) WP will see a lot of users coming from the same IP address. This fixes that by replacing $_SERVER['REMOTE_ADDR'] with the original IP. – gabrielk Sep 19 '10 at 18:02
  • Those are easy to trick by adding the HTTP_X_FORWARDED_FOR header manually into each browser request. My favorite is to set it which will then set $_SERVER['REMOVE_ADDR'] to an empty value with that example. – hakre Nov 5 '10 at 21:41

List all SubCategories

Tested on: Wordpress 3.0.1

$echo = '<ul>' . "\n";
$childcats = get_categories('child_of=' . $cat . '&hide_empty=1');
foreach ($childcats as $childcat) {
    if (1 == $childcat->category_parent) {
        $echo .= "\t" . '<li><a href="' . get_category_link($childcat->cat_ID).'" title="' . $childcat->category_description . '">';
        $echo .= $childcat->cat_name . '</a>';
        $echo .= '</li>' . "\n";
$echo .= '</ul>' . "\n";
echo $echo;

also here, more informations and functins in the post

Remove Admin Backend Menus for all users, except User #1 (usually the first Admin)

/*  Restrict access
function remove_menus () {
global $menu;
$user = wp_get_current_user();
    if ($user->ID!=1) { // Is not administrator,

        $restricted = array(__('Dashboard'), __('Posts'), __('Media'), __('Links'), __('Pages'), __('Appearance'), __('Tools'), __('Users'), __('Settings'), __('Comments'), __('Plugins'));
        end ($menu);
        while (prev($menu)){
            $value = explode(' ',$menu[key($menu)][0]);
            if(in_array($value[0] != NULL?$value[0]:"" , $restricted)){unset($menu[key($menu)]);}
add_action('admin_menu', 'remove_menus');
  • User 1 may be the first admin. But after adding new administrators the first one may be just a regular user. Ask for capabilities, not for numbers. Plus, this code belongs into a plugin, not in the functions.php. There is zero relation to the theme. – fuxia Jun 13 '11 at 11:55
  • This way you can allow all admins to act as normal but at the same time hide the first admin and reserve it to system administrator / support team. I disagree that this code belongs to a plugin. Functions.php is a plugin. This file basically acts like a plugin Theme_Development#Functions_File – Daniel Sachs Jun 13 '11 at 12:12
  • But the functions.php contains logic which is tied to the theme, because if you switch themes the whole code is gone. So, unless the code depends on the theme and vice versa – do not use the functions.php as a mu-plugin. – fuxia Jun 13 '11 at 13:00
  • Yes. But let's consider this: You are developing a website for a client. This website will always use only one theme, the one designed by the designer. The theme is the website. You add custom post types, metaboxes, load additional functions, etc. Now you do want to give some users the admin capabilities, but you want to hide some sections of the site that your client will never use or confuse them (Links, Tools, Comments, are the best examples) and to give the support team a sort of "SuperAdmin" so they can see the whole admin area. – Daniel Sachs Jun 13 '11 at 13:24
  • 1
    If you look at the linked plugin, then it allows you to set access groups per "whatever a user offers (login name, role, ID)". Relying on IDs generally is a "not best practice" concept. That's all i wanted to point out. – kaiser Jun 13 '11 at 14:32

Disable browser upgrade warning in wordpress 3.2

enter image description here

//Disable browser upgrade warning in wordpress 3.2
function disable_browser_upgrade_warning() {
    remove_meta_box( 'dashboard_browser_nag', 'dashboard', 'normal' );
add_action( 'wp_dashboard_setup', 'disable_browser_upgrade_warning' );
  • Pure plugin material. – fuxia Aug 19 '11 at 16:51
  • @toscho So what? Still its working. Isn't it? – Giri Aug 19 '11 at 16:55
  • 4
    Not after switching themes. Themes are for frontends. – fuxia Aug 19 '11 at 17:29

Adds a custom dropdown option to WP_NAV_MENUS where the user can select a predefined css class for each menu item

<?php function menu_item_class_select(){
    global $pagenow;
    if ($pagenow == "nav-menus.php"){

    function create_dd(v){
        //create dropdown
        var dd = jQuery('<select class="my_class"></select>');
        //create dropdown options
        //array with the options you want
        var classes = ["","class1","class2","class3"];
        jQuery.each(classes, function(i,val) {
            if (v == val){
                dd.append('<option value="'+val+'" selected="selected">'+val+'</option>');
                dd.append('<option value="'+val+'">'+val+'</option>');
        return dd;
    jQuery(".edit-menu-item-classes").each(function() {
        //add dropdown
        var t = create_dd(jQuery(this).val());
        //hide all inputs
    //update input on selection
    jQuery(".my_class").bind("change", function() {
        var v = jQuery(this).val();
        var inp = jQuery(this).next();

<?php } }


Displaying information for logged in users

if ( is_user_logged_in() ) {


is not working in functions.php file. You can use this code:

if ( !function_exists('is_user_logged_in') ) :

 function is_user_logged_in() {
$user = wp_get_current_user();

if ( $user->id == 0 ){
// This section if user is not logged in
} else {
// This section if user is logged in
  • if( !current_user_can('read') ) should catch guests (ie. non-logged in users) .. – t31os Dec 7 '10 at 10:19
  • 2
    I just tested it and is_user_logged_in() seems to work just fine in functions.php?.. Any background info on why it's not supposed to? – Rarst Jan 26 '11 at 13:48

Exclude default category from public pages

Excludes the default category from the front-facing side of the website.
Code excludes the admin area, else you'll have no way to manage posts assigned with the default category.

add_filter( 'list_terms_exclusions', 'exclude_default_cat' );

function exclude_default_cat( $exclusions ) {
    if( !is_admin() )
        $exclusions .=  "AND t.term_id != " . get_option( 'default_category' ) . " ";
    return $exclusions;

Remove "Comments" link from admin bar if comment status is closed

You can set the default comment status to 'closed', but the comments link will stay. Simply drop the following into your functions.php file to get rid of it based on the condition. Offers 2 different approaches.

 * Disable 'Comments' link if default status is _closed_
function remove_comments() 
    $default_comment_status = get_option( 'default_comment_status' );

    if ( $default_comment_status == 'closed' ) 
        remove_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 50 );

        // optional solution using the WP_Admin_Bar class from /wp-includes/class-wp-admin-bar.php
        # global $wp_admin_bar;
        # $wp_admin_bar->remove_menu( 'comments' );

Not the answer you're looking for? Browse other questions tagged or ask your own question.