Sql syntax error

The error in the SQL statement is at the very end,

SELECT * 
FROM c_posts 
WHERE id = , 

There is no value being supplied to check against the id column. This is most likely because you didn’t check for a blank value in the ID field before forming and executing the query. Check the code in the function apt_publish_post to ensure that the value being inserted into the query for id is non-empty and a positive integer.

Update

Now that you’ve provided the code for apt_publish_post, it is clear why this could be happening.

  • apt_check_required_transition is hooked on the transition_post_status action, which accepts three arguments, $old_status, $new_status, and $post. If registered correctly with add_action, all three variables are guaranteed to be defined.

    add_action( 'transition_post_status', 'apt_check_required_transition', 10, 3);

    • It’s important that the last two arguments to add_action are provided: $priority and $num_arguments; here I have $priority = 10 and $num_arguments = 3, to correspond to the number of arguments the transition_post_status action supplies.
  • apt_check_required_transition thus will accept a $post object as the third argument, whose ID $post->ID should be passed to apt_publish_post

  • apt_publish_post should do some basic sanity checks on its argument, $post_id:

    if( ( $post_id = (int) $post_id ) < 1 )
    return;

    • This is just one of a whole variety of ways in PHP to check for type and domain validity.
  • Always use $wpdb->prepare() when creating SQL statements. This adds another layer of protection against injection attacks.

    $post = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE id = %d", $post_id ) );

    • Despite this, the get_post() WordPress API function is a much better way to obtain a post object given a post ID:

    $post = get_post( $post_id );

    • This differs from your current method in that you get a single post, rather than an array of posts as you do using $wpdb->get_results()
  • You could also just pass the $post object provided to apt_check_required_transition directly to apt_publish_post rather than getting its ID and then looking it up again. This would eliminate the need for sanity checks, as $post would always be defined in this situation.