WP Query Args - Titlu sau Valoare Meta
Cum pot face o interogare după meta_value sau titlu?
Dacă setez meta_values,
$args['meta_query'] = array(
'relation' => 'OR',
array(
'key' => 'model_name',
'value' => $thesearch,
'compare' => 'like'
)
);
acestea sunt adăugate automat ca AND.
Această căutare ar fi:
WHERE title = 'Search' AND (model_name = 'Search' OR ...)
Am nevoie de
WHERE title = 'Search' OR (model_name = 'Search' OR ...)

Rețineți că partea relation
din argumentul meta_query
este folosită doar pentru a defini relația între sub interogările meta.
Puteți încerca această configurație:
$args = [
'_meta_or_title' => $thesearch, // Argumentul nostru personalizat nou!
'meta_query' => [
[
'key' => 'model_name',
'value' => $thesearch,
'compare' => 'like'
]
],
];
unde am introdus un argument personalizat _meta_or_title
pentru a activa interogarea meta SAU titlu.
Aceasta este susținută de următorul plugin:
<?php
/**
* Plugin Name: Interogare Meta SAU Titlu în WP_Query
* Description: Activă prin argumentul '_meta_or_title' al 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;
// Rulează doar o singură dată:
static $nr = 0;
if( 0 != $nr++ ) return $sql;
// Modifică partea 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;
});
}
});

Răspunsul m-a ajuns pe jumătate. http://wordpress.stackexchange.com/questions/178574/acf-relationship-field-search-filtering Ai vreo idee pentru următoarea problemă?

Am folosit acest răspuns pentru a crea o interogare pentru o valoare meta specifică pe pagina edit.php pentru un tip de postare personalizat. Nu interoghez deloc titlul, deoarece tipul meu de postare personalizat nu are titlu. Prin urmare, am înlocuit " AND ( %s OR %s ) "
cu " OR ( %s ) "
în interogarea SQL și am eliminat complet linia $wpdb->prepare( "{$wpdb->posts}.post_title = '%s'", $title ),
. Este aceasta o abordare validă?

@BdN3504 Mă bucur să aud că ți s-a părut oarecum util. Dacă te-am înțeles corect, modificările tale ar trebui să funcționeze.

mulțumesc pentru răspuns. modificările mele funcționează, dar nu sunt sigur dacă este abordarea corectă. de fapt, vreau să scap de parametrii de titlu și conținut din interogare și să interoghez doar meta. deși abordarea actuală funcționează, nu este cea mai practică

@BdN3504 ok grozav, nu știu de o metodă nativă (fără a folosi filtre) pentru a schimba AND -> OR pentru întreaga interogare meta, dar poți modifica relațiile interogării meta în multe feluri în cadrul meta_query
din WP_Query
.

Truc excelent. Dacă dorești să cauți un subșir în titlu, înlocuiește post_title = '%s'
cu post_title like '%%%s%%'
.

Cum aș putea executa o interogare cu titlul și valoarea taxonomiei în loc de valoarea meta?

@jeff Am scris odată un plugin pentru a combina interogări: https://github.com/birgire/wp-combine-queries. De asemenea, aici am experimentat cu căutarea (titlu, rezumat, conținut) sau interogarea taxonomiei. Aici am găsit un alt răspuns similar cu care am experimentat. De asemenea, putem scrie două interogări WP_Query
separate, apoi colecta și combina ID-urile postărilor rezultate într-o a treia interogare WP_Query
(dacă este necesar și dacă ordonarea PHP nu este suficientă) prin parametrul de intrare post__in
.

@birgire Am ales calea cu două interogări separate și a funcționat, mulțumesc.

@biergie Mulțumesc pentru această soluție minunată! Funcționează excelent, dar căutarea mea nu returnează niciun rezultat când folosesc _meta_or_title + meta query + tax query. Când utilizez filtrul tău personalizat și adaug un tax_query, elementul $sql['where']
este gol. Ai vreo idee cum să rezolv asta?

@biergie Mulțumesc. Nu am testat de ceva vreme, dar ar trebui să te asiguri că nu există alte plugin-uri/cod care să afecteze acest lucru și, de exemplu, să rulezi cu depanarea activată.

@birgire - doar mă întrebam dacă tu sau cineva puteți să indicați unde folosiți $args? mulțumesc.

Nu am găsit o soluție pentru a căuta mai multe cuvinte cheie care pot fi amestecate fie în titlul postării, descriere ȘI/SAU una sau mai multe metadate, așa că am creat propria mea adăugare la funcția de căutare.
Tot ce trebuie să faci este să adaugi următorul cod în function.php, și ori de câte ori folosești argumentul 's' în WP_Query() și vrei să caute și în una sau mai multe metadate, pur și simplu adaugi un argument 's_meta_keys' care este un array cu cheile meta în care dorești să cauți:
/************************************************************************\
|** **|
|** Permite funcției de căutare WP_Query() să caute mai multe **|
|** cuvinte cheie în metadate în plus față de post_title și **|
|** post_content **|
|** **|
|** De rAthus @ Arkanite **|
|** Creat: 2020-08-18 **|
|** Actualizat: 2020-08-19 **|
|** **|
|** Folosește argumentul obișnuit 's' și adaugă un argument **|
|** 's_meta_keys' conținând un array cu cheile meta în care **|
|** dorești să cauți :) **|
|** **|
|** Exemplu : **|
|** **|
|** $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'); // adaugă funcția specială de căutare la fiecare interogare get_posts (asta 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']) { // dacă căutăm folosind argumentul 's' și am adăugat un argument 's_meta_keys'
global $wpdb;
$search = $query->query_vars['s']; // obține șirul de căutare
$ids = array(); // inițializează array-ul de ID-uri de postări potrivite per cuvânt cheie căutat
foreach (explode(' ',$search) as $term) { // despachetează cuvintele cheie și caută rezultate potrivite pentru fiecare
$term = trim($term); // elimină spațiile inutile
if (!empty($term)) { // verifică dacă cuvântul cheie nu este gol
$query_posts = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status='publish' AND ((post_title LIKE '%%%s%%') OR (post_content LIKE '%%%s%%'))", $term, $term); // caută în titlu și conținut ca funcția normală
$ids_posts = [];
$results = $wpdb->get_results($query_posts);
if ($wpdb->last_error)
die($wpdb->last_error);
foreach ($results as $result)
$ids_posts[] = $result->ID; // adună ID-urile postărilor potrivite
$query_meta = [];
foreach($query->query_vars['s_meta_keys'] as $meta_key) // acum construiește o interogare de căutare pentru fiecare cheie meta dorită
$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; // adună ID-urile postărilor potrivite
$merged = array_merge($ids_posts,$ids_metas); // combină ID-urile din titlu, conținut și metadate rezultate din ambele interogări
$unique = array_unique($merged); // elimină duplicatele
if (!$unique)
$unique = array(0); // dacă nu sunt rezultate, adaugă un ID "0" altfel vor fi returnate toate postările
$ids[] = $unique; // adaugă array-ul de ID-uri potrivite în array-ul principal
}
}
if (count($ids)>1)
$intersected = call_user_func_array('array_intersect',$ids); // dacă sunt mai multe cuvinte cheie, păstrează doar ID-urile găsite în toate array-urile de potriviri
else
$intersected = $ids[0]; // altfel păstrează array-ul unic de ID-uri potrivite
$unique = array_unique($intersected); // elimină duplicatele
if (!$unique)
$unique = array(0); // dacă nu sunt rezultate, adaugă un ID "0" altfel vor fi returnate toate postările
unset($query->query_vars['s']); // elimină interogarea normală de căutare
$query->set('post__in',$unique); // adaugă un filtru după ID-ul postării în schimb
}
}
Exemplu de utilizare:
$search= "cuvinte cheie pentru căutare";
$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);
Acest exemplu va căuta cuvintele cheie "cuvinte cheie pentru căutare" în titlurile postărilor, descrieri și cheile meta 'short_desc' și 'tags'.
Cuvintele cheie pot fi găsite într-unul sau mai multe dintre câmpuri, în orice ordine, va returna orice postare care are toate cuvintele cheie în oricare dintre câmpurile desemnate.
Poți evident forța căutarea într-o listă de chei meta pe care le incluzi în funcție și să scapi de argumentele suplimentare dacă vrei ca TOATE interogările de căutare să includă aceste chei meta :)
Sper că acest lucru va ajuta pe oricine se confruntă cu aceeași problemă ca mine!

Sunt destul de nou în WordPress, nu am testat prea mult această abordare la care am ajuns. Poate mă puteți ajuta să verific dacă am dreptate. Soluția pe care am găsit-o până acum este să implementez aceeași logică meta_query, făcând câteva înlocuiri.
În primul rând, modul de utilizare:
$args = array(
'lang' => 'pt', //această funcție nu intră în conflict (exemplu: polylang)
'post_type' => 'produtos',
'post_status' => 'publish',
'posts_per_page' => 10,
'paged' => 1,
'fields' => 'ids',
);
$args['meta_query] = [
['relation'] => 'OR'; //orice relație doriți
[
'key' => 'acf_field', //orice câmp personalizat (utilizare normală)
'value' => $search, //orice valoare (utilizare normală)
'compare' => 'LIKE', //orice comparație (utilizare normală)
],
[
'key' => 'post_title', //setați conținutul implicit al postării WordPress dorit ('post_content', 'post_title' și 'post_excerpt')
'value' => $search, //orice valoare
'compare' => 'LIKE', //testat cu 'LIKE' și '=', funcționează excelent și nu-mi pot imagina alte nevoi.
],
[
'key' => 'post_exerpt', //puteți adăuga de câte ori aveți nevoie
'value' => $search_2,
'compare' => 'LIKE',
],
];
$the_query = new WP_Query( $args ); //doar interogare
wp_reset_postdata(); //curățați interogarea
Pentru a funcționa, adăugați această funcție în fișierul functions.php al temei dumneavoastră:
function post_content_to_meta_queries($where, $wp_query){
global $wpdb;
//dacă nu există metaquery, pa!
$meta_queries = $wp_query->get( 'meta_query' );
if( !$meta_queries || $meta_queries == '' ) return $where;
//dacă există o singură relație
$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);
//pentru relații imbricate
//numarați câte meta queries există pentru posibile înlocuiri
$number_of_relations = count($meta_queries);
//înlocuiți 'WHERE' folosind logica de denumire multidimensională a postmeta folosită de nucleul 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);
Sunt sigur că poate fi îmbunătățit! Sper să vă fie de folos!
