WP Query Args - Titolo o Valore Meta
Come posso eseguire una query per meta_value o titolo?
Se imposto i meta_values,
$args['meta_query'] = array(
'relation' => 'OR',
array(
'key' => 'model_name',
'value' => $thesearch,
'compare' => 'like'
)
);
vengono automaticamente aggiunti come AND.
Questa ricerca sarebbe:
WHERE title = 'Search' AND (model_name = 'Search' OR ...)
Ho bisogno di
WHERE title = 'Search' OR (model_name = 'Search' OR ...)

Nota che la parte relation
nell'argomento meta_query
viene utilizzata solo per definire la relazione tra le query sub meta.
Puoi provare questa configurazione:
$args = [
'_meta_or_title' => $thesearch, // Il nostro nuovo argomento personalizzato!
'meta_query' => [
[
'key' => 'model_name',
'value' => $thesearch,
'compare' => 'like'
]
],
];
dove abbiamo introdotto un argomento personalizzato _meta_or_title
per attivare la query meta OR title.
Questo è supportato dal seguente plugin:
<?php
/**
* Plugin Name: Meta OR Title query in WP_Query
* Description: Attivato tramite l'argomento '_meta_or_title' di WP_Query
* Plugin URI: http://wordpress.stackexchange.com/a/178492/26350
* Plugin Author: Birgir Erlendsson (birgire)
* Version: 0.0.1
*/
add_action( 'pre_get_posts', function( $q )
{
if( $title = $q->get( '_meta_or_title' ) )
{
add_filter( 'get_meta_sql', function( $sql ) use ( $title )
{
global $wpdb;
// Esegui solo una volta:
static $nr = 0;
if( 0 != $nr++ ) return $sql;
// Modifica la parte WHERE:
$sql['where'] = sprintf(
" AND ( %s OR %s ) ",
$wpdb->prepare( "{$wpdb->posts}.post_title = '%s'", $title ),
mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
);
return $sql;
});
}
});

La risposta mi ha portato a metà strada. http://wordpress.stackexchange.com/questions/178574/acf-relationship-field-search-filtering Hai qualche idea per il prossimo passaggio?

Ho utilizzato questa risposta per creare una query per un valore meta specifico nella pagina edit.php di un custom post type. Non eseguo alcuna query sul titolo, perché il mio custom post type non ha un titolo. Quindi, ho sostituito " AND ( %s OR %s ) "
con " OR ( %s ) "
nella query SQL e ho completamente rimosso la riga $wpdb->prepare( "{$wpdb->posts}.post_title = '%s'", $title ),
. È un approccio valido?

@BdN3504 Sono contento che tu l'abbia trovato un po' utile. Se ho capito bene, le tue modifiche dovrebbero funzionare.

grazie per la risposta. le mie modifiche funzionano, ma non sono sicuro che sia l'approccio giusto. in realtà vorrei eliminare i parametri title e content dalla query e cercare solo i meta. anche se l'approccio attuale funziona, non è il più pratico

@BdN3504 ok perfetto, non sono a conoscenza di un modo nativo (senza usare filtri) per cambiare AND -> OR per l'intera meta query, ma puoi ovviamente modificare le relazioni della meta query in molti modi all'interno di meta_query
di WP_Query
.

Ottimo trucco. Se vuoi una ricerca di sottostringa per il titolo, sostituisci post_title = '%s'
con post_title like '%%%s%%'
.

Come posso eseguire una query con titolo e valore di tassonomia invece del valore meta?

@jeff Una volta ho scritto un plugin per combinare query: https://github.com/birgire/wp-combine-queries. Anche qui ho sperimentato con la ricerca (titolo, excerpt, contenuto) o tax query. Qui ho trovato un'altra risposta simile con cui ho sperimentato. Possiamo anche scrivere due WP_Query
separati, poi raccogliere e combinare gli ID dei post risultanti in una terza WP_Query
(se necessario e se l'ordinamento PHP non è sufficiente) tramite il parametro di input post__in
.

@birgire Ho optato per la strada delle due query separate e ha funzionato, grazie.

@biergie Grazie per questa fantastica soluzione! Funziona alla grande, ma la mia ricerca non restituisce risultati quando uso _meta_or_title + meta query + tax query. Quando uso il tuo filtro personalizzato e aggiungo una tax_query, l'elemento $sql['where']
risulta vuoto. Hai qualche idea su come risolvere?

@biergie Grazie. Non l'ho testato da un po', ma potresti assicurarti che non ci siano altri plugin/codici che lo influenzano e ad esempio eseguirlo con il debug attivo.

@birgire - mi chiedevo se tu o qualcun altro poteste indicare dove usi gli $args? grazie.

Non ho trovato una soluzione per cercare più parole chiave che possono essere mescolate nel titolo del post, nella descrizione E/O in una o più meta, quindi ho creato la mia aggiunta alla funzione di ricerca.
Tutto ciò che devi fare è aggiungere il seguente codice in function.php, e ogni volta che usi l'argomento 's' in WP_Query() e vuoi che cerchi anche in una o più meta, aggiungi semplicemente un argomento 's_meta_keys' che è un array delle chiavi meta in cui vuoi cercare:
/************************************************************************\
|** **|
|** Permette alla funzione di ricerca di WP_Query() di cercare **|
|** più parole chiave nelle meta oltre che in post_title e post_content **|
|** **|
|** Di rAthus @ Arkanite **|
|** Creato: 2020-08-18 **|
|** Aggiornato: 2020-08-19 **|
|** **|
|** Usa il solito argomento 's' e aggiungi un argomento 's_meta_keys' **|
|** contenente un array delle chiavi meta in cui vuoi cercare :) **|
|** **|
|** Esempio : **|
|** **|
|** $args = array( **|
|** 'numberposts' => -1, **|
|** 'post_type' => 'post', **|
|** 's' => $MY_SEARCH_STRING, **|
|** 's_meta_keys' => array('META_KEY_1','META_KEY_2'); **|
|** 'orderby' => 'date', **|
|** 'order' => 'DESC', **|
|** ); **|
|** $posts = new WP_Query($args); **|
|** **|
\************************************************************************/
add_action('pre_get_posts', 'my_search_query'); // aggiunge la funzione di ricerca speciale ad ogni query get_posts (include WP_Query())
function my_search_query($query) {
if ($query->is_search() and $query->query_vars and $query->query_vars['s'] and $query->query_vars['s_meta_keys']) { // se stiamo cercando usando l'argomento 's' e abbiamo aggiunto un argomento 's_meta_keys'
global $wpdb;
$search = $query->query_vars['s']; // ottieni la stringa di ricerca
$ids = array(); // inizializza l'array degli id dei post corrispondenti per ogni parola chiave cercata
foreach (explode(' ',$search) as $term) { // dividi le parole chiave e cerca risultati corrispondenti per ciascuna
$term = trim($term); // rimuovi spazi non necessari
if (!empty($term)) { // controlla che la parola chiave non sia vuota
$query_posts = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status='publish' AND ((post_title LIKE '%%%s%%') OR (post_content LIKE '%%%s%%'))", $term, $term); // cerca nel titolo e nel contenuto come fa normalmente la funzione
$ids_posts = [];
$results = $wpdb->get_results($query_posts);
if ($wpdb->last_error)
die($wpdb->last_error);
foreach ($results as $result)
$ids_posts[] = $result->ID; // raccogli gli id dei post corrispondenti
$query_meta = [];
foreach($query->query_vars['s_meta_keys'] as $meta_key) // ora costruisci una query di ricerca per cercare in ogni chiave meta desiderata
$query_meta[] = $wpdb->prepare("meta_key='%s' AND meta_value LIKE '%%%s%%'", $meta_key, $term);
$query_metas = $wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE ((".implode(') OR (',$query_meta)."))");
$ids_metas = [];
$results = $wpdb->get_results($query_metas);
if ($wpdb->last_error)
die($wpdb->last_error);
foreach ($results as $result)
$ids_metas[] = $result->post_id; // raccogli gli id dei post corrispondenti
$merged = array_merge($ids_posts,$ids_metas); // unisci gli id di titolo, contenuto e meta risultanti da entrambe le query
$unique = array_unique($merged); // rimuovi i duplicati
if (!$unique)
$unique = array(0); // se nessun risultato, aggiungi un id "0" altrimenti verranno restituiti tutti i post
$ids[] = $unique; // aggiungi l'array degli id corrispondenti nell'array principale
}
}
if (count($ids)>1)
$intersected = call_user_func_array('array_intersect',$ids); // se ci sono più parole chiave mantieni solo gli id presenti in tutti gli array corrispondenti
else
$intersected = $ids[0]; // altrimenti mantieni il singolo array di id corrispondenti
$unique = array_unique($intersected); // rimuovi i duplicati
if (!$unique)
$unique = array(0); // se nessun risultato, aggiungi un id "0" altrimenti verranno restituiti tutti i post
unset($query->query_vars['s']); // rimuovi la normale query di ricerca
$query->set('post__in',$unique); // aggiungi invece un filtro per id del post
}
}
Esempio di utilizzo:
$search= "parole chiave da cercare";
$args = array(
'numberposts' => -1,
'post_type' => 'post',
's' => $search,
's_meta_keys' => array('short_desc','tags');
'orderby' => 'date',
'order' => 'DESC',
);
$posts = new WP_Query($args);
Questo esempio cercherà le parole chiave "parole chiave da cercare" nei titoli dei post, nelle descrizioni e nelle chiavi meta 'short_desc' e 'tags'.
Le parole chiave possono essere trovate in uno o più campi, in qualsiasi ordine, restituirà qualsiasi post che abbia tutte le parole chiave in uno qualsiasi dei campi designati.
Ovviamente puoi forzare la ricerca in una lista di chiavi meta che includi nella funzione ed eliminare gli argomenti extra se vuoi che TUTTE le query di ricerca includano queste chiavi meta :)
Spero che questo aiuti chiunque si trovi ad affrontare lo stesso problema che ho avuto io!

Sono abbastanza nuovo in WP, non ho testato molto questo approccio che ho ideato. Forse potete aiutarmi a verificare se è corretto. La soluzione che ho trovato finora è implementare la stessa logica di meta_query, facendo solo alcune sostituzioni.
Prima di tutto, l'utilizzo:
$args = array(
'lang' => 'pt', //questa funzione non entra in conflitto (esempio: polylang)
'post_type' => 'produtos',
'post_status' => 'publish',
'posts_per_page' => 10,
'paged' => 1,
'fields' => 'ids',
);
$args['meta_query] = [
['relation'] => 'OR'; //qualsiasi relazione desideri
[
'key' => 'acf_field', //qualsiasi campo personalizzato (uso normale)
'value' => $search, //qualsiasi valore (uso normale)
'compare' => 'LIKE', //qualsiasi comparazione (uso normale)
],
[
'key' => 'post_title', //imposta il contenuto predefinito di WordPress che desideri ('post_content', 'post_title' e 'post_excerpt')
'value' => $search, //qualsiasi valore
'compare' => 'LIKE', //testato con 'LIKE' e '=', funziona bene e non vedo altre necessità.
],
[
'key' => 'post_exerpt', // puoi aggiungere quante volte vuoi
'value' => $search_2,
'compare' => 'LIKE',
],
];
$the_query = new WP_Query( $args ); //solo la query
wp_reset_postdata(); //pulisci la tua query
Per farlo funzionare, aggiungi questa funzione al tuo functions.php del tema
function post_content_to_meta_queries($where, $wp_query){
global $wpdb;
//se non c'è metaquery, ciao!
$meta_queries = $wp_query->get( 'meta_query' );
if( !$meta_queries || $meta_queries == '' ) return $where;
//se c'è solo una relazione
$where = str_replace($wpdb->postmeta . ".meta_key = 'post_title' AND " . $wpdb->postmeta . ".meta_value", $wpdb->posts . ".post_title", $where);
$where = str_replace($wpdb->postmeta . ".meta_key = 'post_content' AND " . $wpdb->postmeta . ".meta_value", $wpdb->posts . ".post_content", $where);
$where = str_replace($wpdb->postmeta . ".meta_key = 'post_excerpt' AND " . $wpdb->postmeta . ".meta_value", $wpdb->posts . ".post_excerpt", $where);
////per relazioni annidate
//conta il numero di meta query per possibili sostituzioni
$number_of_relations = count($meta_queries);
//sostituisce 'WHERE' usando la logica di denominazione multidimensionale postmeta usata dal core di WordPress
$i = 1;
while($i<=$number_of_relations && $number_of_relations > 0){
$where = str_replace("mt".$i.".meta_key = 'post_title' AND mt".$i.".meta_value", $wpdb->posts . ".post_title", $where);
$where = str_replace("mt".$i.".meta_key = 'post_content' AND mt".$i.".meta_value", $wpdb->posts . ".post_content", $where);
$where = str_replace("mt".$i.".meta_key = 'post_excerpt' AND mt".$i.".meta_value", $wpdb->posts . ".post_excerpt", $where);
$i++;
}
return $where;
}
add_filter('posts_where','post_content_to_meta_queries',10,2);
Sono abbastanza sicuro che possa essere migliorato! Spero sia utile!
