Ich muss einen WP_Query
mit einem LIKE
auf dem post_title
machen.
Ich habe mit diesem regulären WP_Query
angefangen:
$wp_query = new WP_Query(
array (
'post_type' => 'wp_exposants',
'posts_per_page' => '1',
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC',
'paged' => $paged
)
);
Aber was ich eigentlich machen möchte, sieht in SQL so aus:
$query = "
SELECT *
FROM $wpdb->posts
WHERE $wpdb->posts.post_title LIKE '$param2%'
AND $wpdb->posts.post_type = 'wp_exposants'
ORDER BY $wpdb->posts.post_title
";
$wpdb->get_results($query);
Die Ausgabe druckt die Ergebnisse, die ich erwarte, aber ich benutze die reguläre Funktion <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
, um die Ergebnisse anzuzeigen.
Und das funktioniert nicht mit $wpdb->get_results()
.
Wie kann ich das erreichen, was ich hier beschrieben habe?
Ich würde das mit einem Filter für WP_Query
lösen. Eine, die eine zusätzliche Abfragevariable erkennt und diese als Präfix für den Titel verwendet.
add_filter( 'posts_where', 'wpse18703_posts_where', 10, 2 );
function wpse18703_posts_where( $where, &$wp_query )
{
global $wpdb;
if ( $wpse18703_title = $wp_query->get( 'wpse18703_title' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( $wpdb->esc_like( $wpse18703_title ) ) . '%\'';
}
return $where;
}
Auf diese Weise können Sie weiterhin WP_Query
aufrufen. Sie übergeben lediglich den Titel als wpse18703_title
-Argument (oder ändern den Namen in einen kürzeren Namen).
Vereinfacht:
function title_filter( $where, &$wp_query )
{
global $wpdb;
if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( $search_term ) ) . '%\'';
}
return $where;
}
$args = array(
'post_type' => 'product',
'posts_per_page' => $page_size,
'paged' => $page,
'search_prod_title' => $search_term,
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC'
);
add_filter( 'posts_where', 'title_filter', 10, 2 );
$wp_query = new WP_Query($args);
remove_filter( 'posts_where', 'title_filter', 10, 2 );
return $wp_query;
Wollte diesen Code aktualisieren, an dem ihr für WordPress 4.0 und höher gearbeitet habt, da esc_sql () in 4.0 höher veraltet ist.
function title_filter($where, &$wp_query){
global $wpdb;
if($search_term = $wp_query->get( 'search_prod_title' )){
/*using the esc_like() in here instead of other esc_sql()*/
$search_term = $wpdb->esc_like($search_term);
$search_term = ' \'%' . $search_term . '%\'';
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE '.$search_term;
}
return $where;
}
Der Rest des Zeugs ist dasselbe.
Ich möchte auch darauf hinweisen, dass Sie s variable in WP_Query-Argumenten verwenden können, um Suchbegriffe zu übergeben, die auch nach dem Titel des Beitrags suchen, glaube ich.
So was:
$args = array(
'post_type' => 'post',
's' => $search_term,
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC'
);
$wp_query = new WP_Query($args);
Da hier eine verwundbare Lösung veröffentlicht wurde, habe ich eine etwas vereinfachte und bereinigte Version.
Zunächst erstellen wir eine Funktion für den posts_where
-Filter, mit der Sie nur Posts anzeigen können, die bestimmten Bedingungen entsprechen:
function cc_post_title_filter($where, &$wp_query) {
global $wpdb;
if ( $search_term = $wp_query->get( 'cc_search_post_title' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . $wpdb->esc_like( $search_term ) . '%\'';
}
return $where;
}
Jetzt fügen wir cc_search_post_title
in unsere Abfrageargumente ein:
$args = array(
'cc_search_post_title' => $search_term, // search post title only
'post_status' => 'publish',
);
Und schließlich wickeln Sie den Filter um die Abfrage:
add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$query = new WP_Query($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );
Bestimmte Funktionen, die Posts abrufen, führen keine Filter aus, sodass die von Ihnen angehängten posts_where-Filterfunktionen die Abfrage nicht ändern. Wenn Sie get_posts()
zum Abfragen Ihrer Posts verwenden möchten, müssen Sie suppress_filters
in Ihrem Argumentarray auf false setzen:
$args = array(
'cc_search_post_title' => $search_term,
'suppress_filters' => FALSE,
'post_status' => 'publish',
);
Jetzt können Sie get_posts()
verwenden:
add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$posts = get_posts($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );
s
?Der Parameter s
ist verfügbar:
$args = array(
's' => $search_term,
);
Wenn Sie Ihren Suchbegriff in den Parameter work s
einfügen und der Beitragstitel durchsucht wird, durchsucht er auch den Inhalt des Beitrags.
title
, der mit WP 4.4 hinzugefügt wurde?Übergeben eines Suchbegriffs an den Parameter title
:
$args = array(
'title' => $search_term,
);
Ist case sensitive und LIKE
, nicht %LIKE%
. Diese mittlere Suche nach hello
gibt keinen Beitrag mit dem Titel Hello World
oder Hello
zurück.
Aufbauend auf anderen Antworten vor mir, um Flexibilität in der Situation zu bieten, in der Sie einen Beitrag suchen möchten, der ein Wort in einem Metafeld OR im Titel des Beitrags enthält, gebe ich diese Option über das Argument " title_filter_relation. " In dieser Implementierung erlaube ich nur "OR" - oder "AND" -Eingaben mit dem Standardwert "AND".
function title_filter($where, &$wp_query){
global $wpdb;
if($search_term = $wp_query->get( 'title_filter' )){
$search_term = $wpdb->esc_like($search_term); //instead of esc_sql()
$search_term = ' \'%' . $search_term . '%\'';
$title_filter_relation = (strtoupper($wp_query->get( 'title_filter_relation'))=='OR' ? 'OR' : 'AND');
$where .= ' '.$title_filter_relation.' ' . $wpdb->posts . '.post_title LIKE '.$search_term;
}
return $where;
}
Hier ist ein Beispiel für den Code in Aktion für einen sehr einfachen Beitragstyp "faq", bei dem die Frage der Beitragstitel selbst ist:
add_filter('posts_where','title_filter',10,2);
$s1 = new WP_Query( array(
'post_type' => 'faq',
'posts_per_page' => -1,
'title_filter' => $q,
'title_filter_relation' => 'OR',
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'faq_answer',
'value' => $q,
'compare' => 'LIKE'
)
)
));
remove_filter('posts_where','title_filter',10,2);