重要な免責事項:これを行う適切な方法は、テーブル構造を変更するのではなく、wp_usermetaを使用することです。その後、投稿を照会するためのカスタムSQLを作成する必要はありません(ただし、特定のスーパーバイザーに報告する全員のリストを取得するには、たとえばAdminセクションでカスタムSQLが必要です)。ただし、OPがカスタムSQLの作成について質問したため、既存のWordPressクエリにカスタムSQLを挿入するための現在のベストプラクティスを以下に示します。
複雑な結合を行っている場合は、posts_whereフィルターを使用することはできません。クエリの結合、選択、および場合によってはgroup byまたはorder byセクションも変更する必要があるためです。
最善の方法は、「posts_clauses」フィルターを使用することです。これは非常に有用なフィルターであり(悪用されるべきではありません!)、WordPressコア内の多くのコード行によって自動的に生成されるSQLのさまざまな部分を追加/変更できます。フィルターコールバックのシグネチャは次のとおり
function posts_clauses_filter_cb( $clauses, $query_object ){ }
です$clauses
。
条項
$clauses
次のキーを含む配列です。各キーは、データベースに送信される最終的なSQLステートメントで直接使用されるSQL文字列です。
- どこで
- groupby
- 参加する
- 注文する
- 明確な
- 畑
- 限界
データベースにテーブルを追加する場合(post_meta、user_meta、またはtaxonomiesを絶対に活用できない場合にのみこれを実行してください)、たとえば、fields
( "SELECT" SQLステートメントの一部)、join
(「FROM」句のテーブル以外のすべてのテーブル)、およびorderby
。
句の変更
これを行う最良の方法は$clauses
、フィルターから取得した配列から関連するキーをサブリファレンスすることです。
$join = &$clauses['join'];
これで、を変更すると$join
、実際に直接変更される$clauses['join']
ため、変更$clauses
を返すときに変更が反映されます。
元の条項の保持
WordPressが生成した既存のSQLを保持する可能性があります(いや、真剣に聞いてください)。そうでない場合は、posts_request
代わりにフィルターを確認する必要があります。これは、データベースに送信される直前の完全なmySQLクエリであるため、独自のフィルターで完全に上書きできます。なぜあなたはこれをしたいのですか?おそらくないでしょう。
したがって、句の既存のSQLを保持するために、それらに割り当てるのではなく、句に追加することを忘れないでください(つまり:$join .= ' {NEW SQL STUFF}';
notを使用します$join = '{CLOBBER SQL STUFF}';
。$clauses
配列の各要素は文字列であるため、追加する場合は、他の文字トークンの前にスペースを挿入したい場合があります。そうしないと、SQL構文エラーが発生する可能性があります。
各句には常に何かがあると仮定することができます。したがって、次のように、スペースで新しい文字列を開始することを忘れないでください$join .= ' my_table
。または、必要な場合はスペースを追加するだけの小さな行をいつでも追加できます:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
それは何よりも文体的なことです。覚えておくべき重要な点は、すでにいくつかのSQLが含まれている句に追加する場合は、常に文字列の前にスペースを残すことです。
それを一緒に入れて
WordPress開発の最初のルールは、できるだけ多くのコア機能を使用することです。これは、作業を将来的に証明するための最良の方法です。コアチームが、WordPressでSQLiteまたはOracleまたはその他のデータベース言語を使用することにしたと仮定します。手書きのmySQLは無効になり、プラグインまたはテーマが破損する可能性があります!WPができるだけ多くのSQLを独自に生成し、必要な部分だけを追加する方が良いでしょう。
したがって、ビジネスの最初の順序はWP_Query
、可能な限り多くの基本クエリを生成することを活用しています。これを行うために使用する正確な方法は、投稿のこのリストが表示される場所に大きく依存します。ページのサブセクション(メインクエリではない)の場合は、を使用しget_posts()
ます。それがメインクエリである場合、あなたはそれを使用query_posts()
してそれを行うことができると思いますが、それを行う適切な方法は、データベースにヒットする前にメインクエリをインターセプトすることです(そしてサーバーサイクルを消費します)ので、request
フィルターを使用します。
さて、クエリを生成し、SQLを作成しようとしています。実際、データベースに送信されるのではなく、作成されています。posts_clauses
フィルターを使用して、従業員関係テーブルをミックスに追加します。このテーブルを{$ wpdb-> prefix}と呼びましょう。「user_relationship」、およびそれは交差テーブルです。(ところで、このテーブル構造を一般化し、次のフィールドを持つ適切な交差テーブルに変換することをお勧めします: 'relationship_id'、 'user_id'、 'related_user_id'、 'relationship_type'。これははるかに柔軟で強力です。 ..しかし、私は脱線します)。
あなたが何をしたいのか理解できたら、リーダーのIDを渡し、そのリーダーのフォロワーによる投稿のみを表示します。私はそれが正しいことを願っています。それが正しくない場合、あなたは私が言うことを受け入れ、あなたのニーズに合わせなければなりません。私はあなたのテーブル構造に固執します:a leader_id
とaがありfollower_id
ます。したがって、JOINは{$wpdb->posts}.post_author
、「user_relationship」テーブルの「follower_id」への外部キーとしてオンになります。
add_filter( 'posts_clauses', 'filter_by_leader_id', 10, 2 ); // we need the 2 because we want to get all the arguments
function filter_by_leader_id( $clauses, $query_object ){
// I don't know how you intend to pass the leader_id, so let's just assume it's a global
global $leader_id;
// In this example I only want to affect a query on the home page.
// This is where the $query_object is used, to help us avoid affecting
// ALL queries (since ALL queries pass through this filter)
if ( $query_object->is_home() ){
// Now, let's add your table into the SQL
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' '; // add a space only if we have to (for bonus marks!)
$join .= "JOIN {$wpdb->prefix}employee_relationship EMP_R ON EMP_R.follower_id = {$wpdb->posts}.author_id";
// And make sure we add it to our selection criteria
$where = &$clauses['where'];
// Regardless, you always start with AND, because there's always a '1=1' statement as the first statement of the WHERE clause that's added in by WP/
// Just don't forget the leading space!
$where .= " AND EMP_R.leader_id={$leader_id}"; // assuming $leader_id is always (int)
// And I assume you'll want the posts "grouped" by user id, so let's modify the groupby clause
$groupby = &$clauses['groupby'];
// We need to prepend, so...
if (! empty( $groupby ) ) $groupby = ' ' . $groupby; // For the show-offs
$groupby = "{$wpdb->posts}.post_author" . $groupby;
}
// Regardless, we need to return our clauses...
return $clauses;
}