Важлива відмова від відповідальності: правильний спосіб зробити це НЕ змінювати структуру таблиці, а використовувати wp_usermeta. Тоді вам не потрібно буде створювати будь-який користувацький SQL для запиту ваших публікацій (хоча вам все одно знадобиться певний спеціальний SQL, щоб отримати список усіх, хто звітує перед певним керівником - наприклад, у розділі Адміністратор). Однак, оскільки ОП запитала про написання користувальницького SQL, ось поточна найкраща практика введення спеціального SQL в існуючий WordPress Query.
Якщо ви робите складні приєднання, ви не можете просто використовувати фільтр posts_where, тому що вам потрібно буде змінити об'єднання, вибір і, можливо, групу, або упорядкувати за розділами запиту.
Краще всього скористатися фільтром "posts_clause". Це надзвичайно корисний фільтр (який не слід зловживати!), Який дозволяє додавати / змінювати різні частини SQL, які автоматично генеруються безліччю багатьох рядків коду в ядрі WordPress. Підпис зворотного дзвінка фільтра такий:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
і він очікує повернення $clauses
.
Статті
$clauses
- масив, який містить такі ключі; кожен ключ - це рядок SQL, який буде безпосередньо використаний у підсумковому операторі SQL, відправленому до бази даних:
- де
- груповий
- приєднатися
- Сортувати по
- виразний
- поля
- межі
Якщо ви додаєте таблицю в базу даних (зробіть це лише в тому випадку, якщо ви абсолютно не можете використовувати post_meta, user_meta або таксономії), можливо, вам доведеться торкнутися більше одного з цих пунктів, наприклад, fields
("SELECT" частина заяви SQL), то join
(все ваші таблиці, інші , ніж у вашому «FROM» статті), і можливо orderby
.
Зміна застережень
Найкращий спосіб зробити це - перенаправити відповідний ключ з $clauses
масиву, який ви отримали з фільтра:
$join = &$clauses['join'];
Тепер, якщо ви модифікуєте $join
, ви насправді будете безпосередньо модифікувати, $clauses['join']
так що зміни будуть, $clauses
коли ви повернете їх.
Збереження оригінальних статей
Швидше за все, (ні, серйозно, слухайте) ви захочете зберегти існуючий SQL, який WordPress створив для вас. Якщо ні, то, напевно, слід подивитися на posts_request
фільтр - це повний запит mySQL безпосередньо перед тим, як він буде відправлений у базу даних, тож ви можете повністю заглушити його власним. Чому б ти хотів це зробити? Ви, мабуть, ні.
Отже, щоб зберегти існуючий SQL у застереженнях, не забудьте додати до них пункти, а не призначати їх (тобто: $join .= ' {NEW SQL STUFF}';
не використовувати $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-> префікс}. 'user_relationship', і це таблиця перетину. (До речі, я рекомендую вам генерізувати цю структуру таблиці та перетворити її у відповідну таблицю перетину з такими полями: 'Relationship_id', 'user_id', 'related_user_id', 'Relations_type'; це набагато більш гнучко та потужно. .. але я відволікаюсь).
Якщо я розумію, що ви хочете зробити, ви хочете передати посвідчення лідера, а потім побачити лише повідомлення підписників цього лідера. Я сподіваюся, що я отримав це право. Якщо це неправильно, вам доведеться взяти те, що я кажу, і адаптувати це до ваших потреб. Я дотримуюся вашої структури столу: у нас є leader_id
а follower_id
. Таким чином, ПРИЄДНАЙТЕ буде працювати {$wpdb->posts}.post_author
як зовнішній ключ до "follower_id" у вашій таблиці "user_relationship".
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;
}