Важный отказ от ответственности: правильный способ сделать это - НЕ изменять структуру таблицы, а использовать wp_usermeta. Тогда вам не нужно будет создавать какой-либо пользовательский SQL для запроса ваших сообщений (хотя вам все равно понадобится некоторый пользовательский SQL для получения списка всех, кто отчитывается перед конкретным супервизором - например, в разделе Admin). Тем не менее, поскольку OP спросил о написании пользовательского SQL, в настоящее время рекомендуется внедрить пользовательский SQL в существующий запрос WordPress.
Если вы выполняете сложные объединения, вы не можете просто использовать фильтр posts_where, потому что вам нужно будет изменить объединение, выбор и, возможно, группирование или упорядочение по разделам запроса.
Лучше всего использовать фильтр «posts_clauses». Это очень полезный фильтр (которым не следует злоупотреблять!), Который позволяет вам добавлять / изменять различные части 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-> prefix}. 'user_relationship', и это таблица пересечений. (Кстати, я рекомендую вам обобщить эту структуру таблицы и превратить ее в правильную таблицу пересечений со следующими полями: 'отношение_идентификатора', 'идентификатор_пользователя', 'связанный_пользователь_идентификатор', 'тип_отношения'; это гораздо более гибкий и мощный инструмент. .. но я отвлекся)
Если я понимаю, что вы хотите сделать, вы хотите передать идентификатор лидера, а затем просматривать только сообщения от подписчиков этого лидера. Я надеюсь, что понял это правильно. Если это неправильно, вам придется взять то, что я говорю, и адаптировать его к вашим потребностям. Я придерживаюсь вашей структуры таблицы: у нас есть leader_id
и follower_id
. Таким образом, JOIN будет {$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;
}