Question

this is my code:

$terms = wp_get_post_terms( $listing_id,'job_listing_category' );    
     if(!empty($terms)){
         $sql_terms.=" AND (";
         foreach($terms as $term){       
         $sql_terms.="  category LIKE '%".$term->slug."%' OR";
         }
          $sql_terms.="  category IS NULL OR category=''";
        $sql_terms.=") ";
     }
$wpdb->get_results( 
                    $wpdb->prepare(     
                "SELECT DISTINCT user_id ,proximity,
                ( %s * IFNULL( acos( cos( radians(lat) ) * cos( radians( %s ) ) * cos( radians( %s ) - radians(lng) ) + sin( radians(lat) ) * sin( radians( %s ) ) ), 0 ) )
                AS distance
                FROM  ".$wpdb->prefix."a_filters  as f
                WHERE
                f.notify=1   AND lat!='false' AND lng!='false' AND listing_type='".$listing_type."' 
                
                ".($sql_terms?$sql_terms:"")."
                
                 HAVING distance < proximity
                        
                ORDER BY distance ASC"
                ,  $earth_radius, $lat, $lng, $lat) 
                );

One of the $terms is "special-purpose".

I get error wpdb::prepare was called incorrectly. The query does not contain the correct number of placeholders (5) for the number of arguments passed (4). And that is because it also counts the %s from '%special-purpose%'. How can I make it ignore the %s from '%special-purpose%' ?

Was it helpful?

Solution

Use double percent sign like so: %%special-purpose%%.

Or you could also use a placeholder, i.e. LIKE %s and then set the 6th parameter for $wpdb->prepare() to %special-purpose%, i.e.

$wpdb->prepare( "your SQL query", $earth_radius, $lat, $lng, $lat, '%special-purpose%' )

OTHER TIPS

This is covered in the documentation:

Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example, to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these cannot be inserted directly in the query string.

Along with an example:

$wpdb->prepare( "SELECT * FROM table WHERE column = %s AND field = %d OR other_field LIKE %s", array( ‘foo’, 1337, ‘%bar’ ) ); 

So you should have something like this:

$wpdb->prepare(     
    "SELECT DISTINCT 
        user_id,
        proximity,
        (
            3959 * acos (
                cos( radians( 78.3232 ) )
                * cos( radians( %f ) )
                * cos( radians( %f ) - radians( 65.3234 ) )
                + sin( radians( 78.3232 ) )
                * sin( radians( %f ) )
            )
        ) AS distance
    FROM
        {$wpdb->prefix}a_filters
    WHERE
        notify = 1 AND
        lat != 'false' AND 
        lng != 'false' AND 
        listing_type = %s AND
        ( 
            category LIKE %s OR 
            category IS NULL OR 
            category = ''
        )
    HAVING
        distance < proximity    
    ORDER BY 
        distance ASC",
    $lat, 
    $lng,
    $lng,
    $listing_type,
    '%special-purpose%'
);

Note:

  • category LIKE '%special-purpose%' has been replaced with category LIKE %s, and the string with wildcards was passed as a parameter.
  • listing_type='".$listing_type."' has been replaced with the proper usage of a placeholder.
  • I hardcoded the radius of the Earth, in miles. That's not going to change any time soon.
  • I cleaned up your formula for distance. You had left out the numbers that are important for it to function, and you had used string placeholders when the values should be floats.
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top