Okay so I'm trying to create a wordpress shortcode called chapter, i.e. [chapter]text[/chapter].

What this does is it first checks if the content entered is already in the database, if it's not it will add it to the database and will also add a count to another table. Then it outputs this in a div

This is the code I have

function chapters( $atts, $content ) {
    $postid = get_post($my_id);

    $result_chaptertitle = mysql_query("SELECT * FROM ltd_chapters_titles WHERE chaptertitle='$content' AND postid='$postid'");
    $num_rows_chaptertitle = mysql_num_rows($result_chaptertitle);

    $result_chaptercount = mysql_query("SELECT * FROM ltd_chapters WHERE postid='$postid'");
    $num_rows_chaptercount = mysql_num_rows($result_chaptercount);

    if ($num_rows_chaptertitle == 0) {
        mysql_query("INSERT INTO ltd_chapters_titles (postid, chaptertitle) VALUES ('$postid','$content')");

    if ($num_rows_chaptercount == 0) {
        mysql_query("INSERT INTO ltd_chapters (postid, chapter) VALUES ('$postid', 1)");
    } else {
        mysql_query("UPDATE ltd_chapters SET chapter=chapter+1 WHERE postid='$postid'");

    $chaptercount = mysql_query("SELECT chapter FROM table WHERE postid='$postid'");

    mysql_query("UPDATE ltd_chapters SET count='$chaptercount' WHERE postid='$postid' AND chaptertitle='$content'");

    return '<div id="chapter'.$chaptercount.'"><h3>'.$content.'</h3></div>';

add_shortcode('chapter', 'chapters');

When I apply this in a post, the entire content of the post doesn't show up on the page and everything afterwards isn't rendered as well (so no footer etc.) However the div that the the_content(); is in is closed of like it should though

Can anyone offer me any insight into what I have been doing wrong? I'm pretty new to PHP

2 Answers 2


Is the $my_id variable supposed to come from an attribute on the shortcode? E.g. [chapter my_id="123"]Lorum ipsum...[/chapter]

If so, at the beginning of your chapters() function, you need to retrieve the attributes out of the array being passed in. Something like:

extract( shortcode_atts( array(
    'foo' => 'something',
    'bar' => 'something else',
), $atts ) );

The values in that array are defaults which can be set if the keys don't exist in your $attr (which comes from the shortcode tag in your content).

Otherwise, we need to know more about where $my_id is getting set in the first place. If you're just trying to get the post ID of the current post that contains the shortcode, then maybe try this:

global $post;
$my_id = $post->ID;

Lastly, just as a best-practice, instead of directly calling MySQL functions, you might want to read up on the $wpdb interface, and use the core database access functions. It will help your code stay future-proof.

  • Hey there, I've copy pasted the get_post($my_id); from the WP codex site to get the ID of the post. I thought that this would then store the ID of the post into the $postid variable. Is that any help? Commented Jul 6, 2012 at 17:01
  • Give TheDeadMedic's code a try and see if it works for you. It's what I was suggesting to do. Commented Jul 6, 2012 at 18:38
  • No variable $my_id on line [3], $postid will default to the current post object
  • Unescaped data in queries, likely to fail
  • Use of object $postid as string, typically fatal error

I hope the code will speak for itself, but I highly recommend you improve your understanding of both WordPress & PHP - check out the manuals, read blogs, get a book if it suits!

function chapters( $atts, $content )
    // We need access to some variables outside the function, so globalise them.
    global $wpdb, $post;

    $chapter_title = $wpdb->get_row(
            'SELECT * FROM ltd_chapters_titles WHERE chaptertitle = %s AND postid= %d',
            $content, $post->ID

    if ( ! $chapter_title ) {
        // Make use of all the handy methods $wpdb has to offer!
        $wpdb->insert( 'ltd_chapters_titles',
            array( 'chaptertitle' => $content, 'postid' => $post->ID ),
            array( '%s', '%d' )

    // For sanity to inject straight into string rather than prepare()
    $post_id = absint( $post->ID );

    if ( $wpdb->get_var( "SELECT postid FROM ltd_chapters WHERE postid = $post_id" ) ) {
        $wpdb->query( "UPDATE ltd_chapters SET chapter=chapter+1 WHERE postid = $postid" );
    } else {
        $wpdb->insert( 'ltd_chapters',
            array( 'chapter' => 1, 'postid' => $post->ID ),
            array( '%d', '%d' )

    $chapter = $wpdb->get_var( "SELECT chapter FROM ltd_chapters WHERE postid = $post_id" );
    $wpdb->update( 'ltd_chapters',
        array( 'count', $count ),
        array( 'postid' => $post_id ),

    return sprintf( '<div id="chapter%d"<h3>%s</h3></div>', $chapter, $content );

Have faith, and don't give up!

  • That was amazing! After a lot of hard work and with the help of this code I have finally successfully added the feature. I have just been learning PHP since the past week, this was my first real own project; your code really helped me understand some of the concepts, thanks again Commented Jul 6, 2012 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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