web-dev-qa-db-ja.com

Wordpressの検索プラグインの開発 - ベストプラクティス

私の質問に対する答えを見つけるために約2日間検索して、私はついにこのStackExchangeに登録しました。 :)

私の質問は単純ではないので、最初から始める必要があります。しかし、あなたにこのPostが何についてのものかについての考えを与えるために:その間私のPluginは働いています、しかし私はコードが好きではありません。私はこれを解決するより良い方法があると思うので、私は良いヒントとベストプラクティスで私を助けることができるwordpressの忍者を探しています。私は本当にワードプレスの深みに入り込もうとしますが、それはちょっと難しいです。前もって感謝します!


私のプラグインがすべきこと

このプラグインのユーザは、特定の投稿タイプの検索フォームを表示するためにショートコードを使うことができるはずです。プラグインはこのショートコードを含むページでのみ必要です。

投稿タイプはプラグイン設定ページで作成されます。このタイプのすべての投稿には、タイトル、コンテンツ、およびacfプラグインからのいくつかのカスタムフィールドがあります。投稿タイプごとに1つのショートコードがあります。検索フォームには、指定された投稿タイプのすべての投稿フィールドを検索するためのフィールドが1つあります。他の2つは、2つのキーワードで結果を制限するために使用できます(たとえば、location、acfフィールドです)。

結果はajaxを介してロードされ、検索フォームの下に表示されます。


私がもうしたこと

私はこの質問を大きくしすぎないようにしています。だから私はすべての側面を特定するわけではありません。以下はうまくいくはずです。

  • プラグインのphpファイルにポストタイプで作成します。現時点では、静的な投稿タイプが1つあります。
  • 検索フォームと結果の空のコンテナを印刷するショートコードを作成します。
  • Ajaxリクエストはjavascriptを介して機能しており、期待される結果が得られます。

カスタム項目の検索

これは非常に困難でしたが、私は実用的なコードスニペットを見つけ、それが何をしているのか理解しています。ここでの問題は、自分の特定の検索フォームでacfフィールドを検索したいということです。既存サイトの検索に触れたくありません。

まず、検索クエリを変更する前に、ユーザーがどのサイトにアクセスしているかを確認し、is_page()を使用してifステートメントを使用しました。しかし、私がajaxを使っているので、これはここではうまくいかないようです….

私の回避策は、すべてのajax検索クエリの最初にグローバル変数を設定することです。検索クエリを変更する前に、この変数が設定されているかどうかを確認します。私のajax関数の終わりに、この変数をfalseに戻しました。はい、私はこれを解決するためのより良い方法があると思いますが、私は方法がわかりません...

検索クエリを変更する機能は次のとおりです。

/** 
 *カスタムフィールドを含めるようにWordPressの検索を拡張する
 * 
 * http://adambalee.com 
 */[.____ [] 
/** 
 *投稿とポストメタテーブルを結合する
 * 
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join 
 */
関数cf_search_join($ join){
 global $ wpdb; 
 //$cwlistpage=(is_page('list'));
 
 global $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if($ cwlistpage){
 $ join。= 'LEFT JOIN'。 $ wpdb-> postmeta 「ON」 $ wpdb-> posts '.ID ='。 $ wpdb-> postmeta [.post_id '; 
} 
 return。$ join; 
} 
 add_filter(' posts_join '、' cf_search_join '); 
 
/** 
 * posts_where 
 * 
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where []で検索クエリを修正します。 */
関数cf_search_where($ where){
グローバル$ pagenow、$ wpdb; 
 // $ cwlistpage =(is_page( 'list')); [[ global $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if($ cwlistpage){
 $ where = preg_replace( 
 "/\(\s*".$wpdb-> posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/"、 [.____。 "("。 "$ wpdb-> posts。"。post_title LIKE $ 1)OR( "。$ wpdb-> postmeta。"。meta_value LIKE $ 1) "、$ where); [[ 
 
 
 return $ where; 
} 
 add_filter( 'posts_where'、 'cf_search_where'); 
 
 ]/** 
 *重複を防ぐ
 * 
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/ posts_distinct 
 */
関数cf_search_distinct($ where){
 global $ wpdb; 
 // $ cwlistpage =(is_page( 'list')); [。 global $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if($ cwlistpage){
 return "DISTINCT"; [] 
 
 
 return $ where; 
} 
 add_filter( 'posts_distinct'、 'cf_search_distinct'); 

カスタムフィールドで結果を制限する

フォームのすべてのフィールドはオプションです。空のフォームはこの投稿タイプのすべての投稿を返します。最初のフィールドは、投稿のすべてのフィールドでキーワードを検索します。 2番目と3番目のフィールドは、このキーワードを含むものに結果を制限する必要があります。私はこれをifステートメントで解決しました、そしてもっと良い解決策があるはずです。

/**
* Search with AJAX
*/
function cwlist_click_search() {
global $testcheck;
$testcheck = true;

$searchterm = $_POST['query'];
$searchlocation = $_POST['location'];
$searchdegree = $_POST['degree'];

// WP_Query arguments
$args = array (
    'post_type' => 'offers',
    'post_status' => 'publish',
    's' => $searchterm
);

$query = new WP_Query( $args );

ob_start();

// The Loop
if ( $query->have_posts() ) : ?>
  <br><br><p>
   <?php while ( $query->have_posts() ) : $query->the_post();
        if( ($searchlocation == NULL) || in_array(trim(strtolower($searchlocation)), array_map('strtolower', get_field('offer_location')))):
            if( ($searchdegree == NULL) || (trim(strtolower($searchdegree)) === strtolower(get_field('offer_degree')))):?>

     Titel: <?php the_title(); ?> <br>
     Abschluss: <?php the_field('offer_degree'); ?> <br>
     Ort: <?php the_field('offer_location'); ?> <br>
     Anbieter: <?php the_field('offer_provider'); ?> <br>
     <?php if(get_field('offer_subtitle')): ?>
     - <?php the_field('offer_subtitle'); ?> <br>
     <?php endif; ?>
     <br>

    <?php endif; endif; endwhile; ?>
    </p>
<?php else: ?>
    <!-- no posts found -->
    Keine Angebote gefunden
<?php endif;

// Restore original Post Data
wp_reset_postdata();

$content = ob_get_clean();

echo $content;
die();

$testcheck = false;
}
add_action( 'wp_ajax_nopriv_cwlist_click_search', 'cwlist_click_search' );
add_action( 'wp_ajax_cwlist_click_search', 'cwlist_click_search' );

WPデバッグ

プラグインを有効にすると、次のような多くの行がフロントページに表示されます。

Notice:C:\ Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp-includes\query.phpの4520行目で非オブジェクトのプロパティを取得しようとしています。 4522行目のUsers¥CWalt¥Documents¥gitlab¥steuerazubi¥wordpress¥wp-includes¥query.php注意:C:¥Users¥CWalt¥Documents¥gitlab¥steuerazubi¥wordpress¥wp-にある非オブジェクトのプロパティを取得しようとしています4524行目に\ query.phpが含まれています...

良いプラグインを作成するためにデバッグを有効にしました。私はどうすれば間違ったことができますか?


その他の投稿タイプ

Wordpressのバックエンドを使ってユーザーにもっと多くの投稿タイプを指定させるための良いアプローチを知っていますか?ユーザーは、ショートコードを使用して、投稿タイプごとに異なる検索ページを作成できるはずです。


お読みいただきありがとうございます。私はあらゆる小さなヒントに感謝しています。

7
Christoph

私はあなたの投稿全体を読んだことがありますが、特に問題はないと思いますが、レイアウトの仕方にイライラしたように思えます。

私は個人的に大きな反対指向のプログラミングのバックグラウンドを持っています、それは私が構造を確立することを可能にし、私のコードをはるかに再利用可能にします。あなたへの私の提案はあなたの次のプラグインのためのオブジェクト指向のアプローチ、またはあなたが最初の質問で書いたこのプラグインの再構築を試みることでしょう。

Wordpress Plugin Boiler Plateは私が心からお勧めするものです。私はたいてい wwpb.me に進んで自分自身のために機能するプラグインスケルトンを生成し、フォームに記入し、ダウンロードしてあなたのwordpressインストールのpluginsディレクトリに展開するだけです。

実行中のスケルトンを適切に配置したら、このチュートリアルを読んでおくことをお勧めします。これは、ダウンロードしたばかりのウォーキングスケルトンを作成する方法に関する優れた入門書です。

WordPressプラグインボイラープレートpt1を使用して開発をスピードアップ

WordPressプラグイン定型文パート2:プラグインの開発

WordPressプラグイン定型文パート3:最後のステップ

その中で簡単に読んだ後、私はたいてい私のカスタムデータベースクエリをすべて格納するデータクラスを作成したいと思います。

<?php 

class example_Events_Data {
  private $wpdb;

  public function __construct() {
    global $wpdb;
    $this->wpdb = $wpdb;
  }

  public function get_events($start_date = null, $end_date = null) {
    $query = "SELECT wp_example_event.id, wp_example_event.name, wp_example_event.description, wp_example_event.date, wp_example_event.end_date, wp_example_event_type.id as event_type_id, wp_example_event_type.type as event_type
              FROM wp_example_event
              JOIN wp_example_event_type on wp_example_event.type_id = wp_example_event_type.id
              ORDER BY wp_example_event.name ASC";
    $events = $this->wpdb->get_results($query, ARRAY_A);
    return $events;
  }

それからあなたのadmin/publicに直面しているコントローラの中でこれを使うのはそれがするのと同じくらい簡単です:

    <?php

class Example_Events_Admin {

/**
 * The ID of this plugin.
 *
 * @since    1.0.0
 * @access   private
 * @var      string    $plugin_name    The ID of this plugin.
 */
private $plugin_name;

/**
 * The version of this plugin.
 *
 * @since    1.0.0
 * @access   private
 * @var      string    $version    The current version of this plugin.
 */
private $version;

private $data;
private $utils;

/**
 * Initialize the class and set its properties.
 *
 * @since    1.0.0
 * @param      string    $plugin_name       The name of this plugin.
 * @param      string    $version    The version of this plugin.
 */
public function __construct( $plugin_name, $version ) {

    $this->plugin_name = $plugin_name;
    $this->version = $version;
    $this->data = new example_Events_Data();

}

私は自分のプラグイン全体で非常に一般的な機能を含むユーティリティクラスを自分で作成したいと思います。例えばフォームバリデーションルールはまったく同じ方法で実装され使用されています。

単にそれらをrequire_onceであなたのメインプラグインファイルに含めて、必要な場所にインスタンスを作成してください。

データクラスを使用することで、すべてのデータ呼び出しを1か所に集中させ、プラグイン開発全体でそれらを使用することができます。

これらのプラクティスを使うことは私の開発時間をかなり短縮し、私のプラグインをずっとずっとずっと簡単にしてくれました。

この回答が役に立つと思います。

1
Ryan Fletcher