WP_Query'yi sonuç döndürmemeye zorlayabilir miyim?


23

Kullanıcıların çok fazla meta sonrası arama yapmasını sağlayan bir arama özelliğine sahip bir web sitesinde çalışıyorum. Zorla sonuç alamadığım belirli bir arama modeli var. WP_Query teknik olarak veritabanında sonuçları bulacaktır, ancak if( $example->have_posts() )başarısızlığı tetiklemek için hiçbir sonuç döndürmemesi için bunu bir şekilde geçersiz kılmak istiyorum .

WP_Query'e iletebileceğim bir parametre var mı 'force_no_results' => true?


1
BT, kök sorununun nasıl çözüleceğini sormaktansa, daha önce belirlenmiş bir uygulamayı istiyor gibisin. Satır aralarını okumak, bence gerçekten sormanız gereken şey şudur: belirli bir arama modelini nasıl anlaşılmaz hale getirebilirim? . Mucip WP_Query()hiçbir sonuç döndürmesi veya bu soruyu cevaplamanın en iyi yolu olabilir veya olmayabilir. Eğer olsaydı Ayrıca yararlı olabilir arama deseni tanımlamak size unqueryable olmak istediğini. Arama modelini bilmek bir çözümün ortaya çıkmasına yardımcı olabilir.
Chip Bennett,

Yanıtlar:


28

Deneyin

'post__in' => array(0)

Basit ve konuya.


İlk düşüncem - bu bir yerlerde yanlış gitmeli, ama ilgili kodu gözden geçirmeden önce bu gerçekten iyi sonuç vermeli. :)
Rarst

5
Sıfır çok önemlidir, çünkü boş bir dizi son gönderileri döndürür.
Mark Kaplun

Teşekkürler! Bu benim için bir hatayı çözdü post__inve boş bir diziden geçerken gönderileri döndürüyordu ... array(0)harika çalışıyor! Bu çok garip ama aslında WP çekirdeğinde hata olarak ortaya çıkan bir sorunla takip edilebiliyor, ancak daha sonra olduğu gibi bırakıldı çünkü çok fazla tema / eklenti geliştiricisi onun etrafında işlevsellik kurdu
EranSch

3

Tuhaf bir şekilde, kısa devre için temiz / açık bir yolu yoktur WP_Query.

Eğer bu ana sorgunun etrafında bir şeyler bulabilirseniz WP->parse_request(), orada nispeten yeni (3.5) bir do_parse_requestfiltre var.

Ama için WP_Querykendisi kirli kesmek gibi, sırayla genellikle kısa devre ekleyerek SQL sorgusu AND 1=0aracılığıyla posts_wherefiltre, vb


2
Bilgi için teşekkürler. İkincil bir döngü btw oldu. Ve az önce "post_type" => "break_loop"olmayan bir post tipi olan ... ... kirli bir kesmekle bitirdim.
Brian,

2

Bir sorgu parametresini var olmayan değere ayarlamadaki sorunlar 2'dir:

  • Sorgu çalışır, bu nedenle zaten bir sonuç olmayacağını bilseniz bile, ödenecek küçük bir performans fiyatı vardır
  • WordPress sorgularında, sorguya etki eden 19 farklı 'posts_*'filtre kancası ( 'posts_where',, 'post_join'vb ..) vardır, bu nedenle, varolmayan bir param sorgusunun sonuç döndürmeyeceğinden, ORbir filtre tarafından döndürülen basit bir cümlenin bir şey döndürdüğünden asla emin olamazsınız .

Bir sorgunun sonuç döndürmediğinden ve hiçbir (veya çok küçük) performans sorunu olmadığından emin olmak için biraz zorlayıcı rutine ihtiyacınız var.

Bu rutini tetiklemek için her yöntemi kullanabilirsiniz, teknik olarak herhangi bir argümanı WP_Query, var olmayan olay argümanlarını iletebilirsiniz .

Öyleyse 'force_no_results' => true, onun gibi bir şeyi seviyorsanız , onun gibi kullanabilirsiniz:

$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );

ve 'pre_get_posts'zor iş yapan bir geri arama çalıştırarak ekleyin :

add_action( 'pre_get_posts', function( $q ) {
  if (array_key_exists('force_no_results', $q->query) && $q->query['force_no_results']) {
    $q->query = $q->query_vars = array();
    $added = array();
    $filters = array(
      'where', 'where_paged', 'join', 'join_paged', 'groupby', 'orderby', 'distinct',
      'limits', 'fields', 'request', 'clauses', 'where_request', 'groupby_request',
      'join_request', 'orderby_request', 'distinct_request','fields_request',
      'limits_request', 'clauses_request'
    );
    // remove all possible interfering filter and save for later restore
    foreach ( $filters as $f ) {
      if ( isset($GLOBALS['wp_filter']["posts_{$f}"]) ) {
        $added["posts_{$f}"] = $GLOBALS['wp_filter']["posts_{$f}"];
        unset($GLOBALS['wp_filter']["posts_{$f}"]);
      }
    }
    // be sure filters are not suppressed
    $q->set( 'suppress_filters', FALSE );
    $done = 0;
    // use a filter to return a non-sense request
    add_filter('posts_request', function( $r ) use( &$done ) {
      if ( $done === 0 ) { $done = 1;
        $r = "SELECT ID FROM {$GLOBALS['wpdb']->posts} WHERE 0 = 1";
      }
      return $r;
    });
    // restore any filter that was added and we removed
    add_filter('posts_results', function( $posts ) use( &$done, $added ) {
      if ( $done === 1 ) { $done = 2;
        foreach ( $added as $hook => $filters ) {
          $GLOBALS['wp_filter'][$hook] = $filters;
        }
      }
      return $posts;
    });
  }
}, PHP_INT_MAX );

Bu kodun yaptığı 'pre_get_posts'mümkün olduğunca geç çalıştırılıyor . Sorguda 'force_no_results' argümanı varsa, o zaman:

  1. önce sorguyu engelleyebilecek tüm olası filtreleri kaldırın ve bunları bir yardımcı dizi içinde saklayın
  2. Filtrenin tetiklendiğinden emin olduktan sonra, bu tür bir istek döndüren adda filtresi: SELECT ID FROM wp_posts WHERE 0 = 1bütün filtreler kaldırıldıktan sonra, bu sorgu değiştirilemez ve çok hızlıdır ve kesin bir sonucu yoktur.
  3. Bu sorgu çalıştırıldıktan hemen sonra, tüm orijinal filtreler (varsa) geri yüklenir ve izleyen tüm sorgular beklendiği gibi çalışır.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.