it-swarm.com.de

Suche, die in verwendetem Feld, Beitragstitel und Beitragsinhalt angezeigt wird

Ich suche nach einer Möglichkeit, eine Suche durchzuführen. Während der Suche wird ein benutzerdefiniertes Feld mit dem Namen "Keywords", der Beitragstitel und der Beitragsinhalt überprüft. Wenn eines dieser Felder Ergebnisse enthält, die den Suchergebnissen des Benutzers entsprechen, wird der benutzerdefinierte Beitragstyp (Programme) auf der Ergebnisseite angezeigt.

Ich brauche keine Hilfe für das End-Anzeige-Ergebnis (es macht derzeit das, was ich will), aber ich muss es so machen, wenn es nach allen drei Feldern sucht (Titel des Beitrags, Inhalt des Beitrags und Schlüsselwörter für benutzerdefinierte Felder). und wenn eines von ihnen ein Ergebnis wie das Gesuchte hat, werden die Ergebnisse angezeigt. Dies ist der Code, den ich bisher habe. Derzeit wird nur im benutzerdefinierten Feld für Schlüsselwörter gesucht:

elseif($program_search) {
    // search by program search text
    query_posts(array(
    'post_type' => 'program',
    'meta_query' => array(
        array(
            'key' => 'keywords',
            'value' => $program_search,
            'compare' => 'LIKE'
        ),      
    )
    ));             
    if ( have_posts() ) : 
        while ( have_posts() ) : 
            the_post();
            $l.= "<div class='program-item'>";
                $l.= "<div class='program-item-image'><a href='".get_permalink($post->ID)."'>". get_the_post_thumbnail($post->ID, 'thumbnail')."</a></div>";
                $l.= "<div class='program-item-title'><a href='".get_permalink($post->ID)."'>".get_the_title($post->ID)."</a></div>";
                $l.= "<div class='program-item-content'>".get_the_excerpt()."</div>";
                $l.= "<div style='clear:both;'></div>";
            $l.= "</div>";
         endwhile; 
    else:
    endif;
}
4
Brandon

Verwenden Sie zunächst nicht query_posts.

Zweitens können Sie einen s-Parameter übergeben, um den größten Teil des Weges dorthin zu schaffen.

$program_search = 'test';
$args = array(
  'post_type' => 'program',
  's' => $program_search,
  'meta_query' => array(
    array(
      'key' => 'keywords',
      'value' => $program_search,
      'compare' => 'LIKE'
    ),      
  )
);
$t = new WP_Query($args);
var_dump($t->request);

Mit diesem s-Parameter werden die üblichen Suchmechanismen aktiviert, und der Titel und der Inhalt werden durchsucht. Wenn Sie sich diese generierte Abfrage ansehen, werden Sie sehen ...

SELECT 
  SQL_CALC_FOUND_ROWS 
  wp_posts.ID 
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) 
WHERE 1=1 
AND (((wp_posts.post_title LIKE '%test%') OR (wp_posts.post_content LIKE '%test%'))) 
AND (wp_posts.post_password = '') 
AND wp_posts.post_type = 'program' 
AND (wp_posts.post_status = 'publish') 
AND ((wp_postmeta.meta_key = 'keywords' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%test%')) 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0, 5

Das ist das Meiste, was du willst. Die LIMIT ist, sofern nicht anders angegeben, das unter wp-admin-> Einstellungen-> Allgemein festgelegte Limit. Es gibt jedoch ein Problem.

AND ((wp_postmeta.meta_key = 'keywords' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%test%')) 

Ich bin mir ziemlich sicher, dass Sie wollen, dass das OR ((wp_postmeta.meta_key ... ist, und Sie wollen es wirklich mit dem post_title und dem post_content. Etwas wie das:

AND (
  (
    (wp_posts.post_title LIKE '%test%') 
    OR 
    (wp_posts.post_content LIKE '%test%')
    OR 
    (wp_postmeta.meta_key = 'keywords' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%test%')
  )
) 

WP_Query macht das nicht, deshalb müssen wir es mit einigen Filtern machen. Konzeptioneller Beweiß:

function add_join_wpse_99849($joins) {
  global $wpdb;
  return $joins . " INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)";
}

function alter_search_wpse_99849($search,$qry) {
  global $wpdb;
  $add = $wpdb->prepare("({$wpdb->postmeta}.meta_key = 'keywords' AND CAST({$wpdb->postmeta}.meta_value AS CHAR) LIKE '%%%s%%')",$qry->get('s'));
  $pat = '|\(\((.+)\)\)|';
  $search = preg_replace($pat,'(($1 OR '.$add.'))',$search);
  return $search;
}

$program_search = 'test';
$args = array(
  'post_type' => 'program',
  's' => $program_search
);

add_filter('posts_join','add_join_wpse_99849');
add_filter('posts_search','alter_search_wpse_99849',1,2);
$t = new WP_Query($args);
remove_filter('posts_join','add_join_wpse_99849');
remove_filter('posts_search','alter_search_wpse_99849',1,2);

// dump some data
var_dump($t->request);
var_dump($t->posts);

Beachten Sie, dass ich den meta_query weggelassen und die Funktionalität weitgehend dupliziert habe. Das soll verhindern, dass diese lästige AND generiert wird.

Sie wenden diese Filter an und entfernen sie sofort, damit keine anderen Abfragen beeinträchtigt werden. Es gibt andere Möglichkeiten, den Filter aus dem Weg zu räumen, oder andere Abfragen. Eine solche Methode wird hier umrissen . Sie können den remove_filter auch zum add_filter-Rückruf hinzufügen, damit sie sich selbst automatisch entfernen.

11
s_ha_dum