Привіт @ user2041:
Зрозуміло, що вам відомо, що вам потрібно змінити пошук, який виконується, змінивши значення в екземплярі WP_User_Search
класу, який використовується для пошуку (ви можете знайти вихідний код, /wp-admin/includes/user.php
якщо ви хочете його вивчити.)
WP_User_Search
об'єкта
Ось що print_r()
виглядає цей об’єкт у WordPress 3.0.3 під час пошуку терміна " TEST
" та без будь-яких інших плагінів, які можуть вплинути на нього:
WP_User_Search Object
(
[results] =>
[search_term] => TEST
[page] => 1
[role] =>
[raw_page] =>
[users_per_page] => 50
[first_user] => 0
[last_user] =>
[query_limit] => LIMIT 0, 50
[query_orderby] => ORDER BY user_login
[query_from] => FROM wp_users
[query_where] => WHERE 1=1 AND (user_login LIKE '%TEST%' OR user_nicename LIKE '%TEST%' OR user_email LIKE '%TEST%' OR user_url LIKE '%TEST%' OR display_name LIKE '%TEST%')
[total_users_for_query] => 0
[too_many_total_users] =>
[search_errors] =>
[paging_text] =>
)
pre_user_search
Hook
Для зміни значень WP_User_Search
об’єкта ви будете використовувати 'pre_user_search'
гачок, який отримує поточний екземпляр об'єкта; Я закликав print_r()
всередині цього гака, щоб отримати доступ до його значень, які я відображав вище.
Наступний приклад, який ви можете скопіювати у functions.php
файл вашої теми або ви можете використовувати у файлі PHP для плагіна, який ви пишете, додає можливість пошуку за описом користувача а також можливість пошуку в інших полях. Функція змінює query_from
і query_where
властивості $user_search
об'єкта, які вам потрібні, щоб зручно розуміти SQL.
Ретельна зміна SQL в гачках
Код у yoursite_pre_user_search()
функції передбачає, що жоден інший плагін не змінив query_where
положення до нього; якщо інший плагін змінив пункт де таке, що замінює'WHERE 1=1 AND ('
з "WHERE 1=1 AND ({$description_where} OR"
більше не працює , то це порушить теж. Набагато складніше написати надійне доповнення, яке не може бути зламане іншим плагіном при зміні SQL, як це, але воно є таким.
Додайте провідні та кінцеві простори, коли вставляєте SQL в гачки
Також зверніть увагу , що при використанні SQL , як це в WordPress , це завжди гарна ідея , щоб включати в себе початкові і кінцеві пробіли такої з " INNER JOIN {$wpdb->usermeta} ON "
іншим ваш запит може містити наступну команду, де немає простору перед тим "INNER"
, що буде, звичайно , НЕ в змозі : " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON "
.
Використовуйте "{$wpdb->table_name"}
замість імен таблиць жорсткого кодування
Далі обов'язково використовуйте $wpdb
властивості для посилання на назви таблиць у випадку, якщо сайт змінив префікс таблиці 'wp_'
на щось інше. Таким чином, краще звернутися до них "{$wpdb->users}.ID"
(з подвійними цитатами, а не поодинокими) замість жорсткого кодування "wp_users.ID"
.
Обмежте запит лише тоді, коли існують пошукові терміни
Нарешті, слід змінювати запит лише тоді, коли є пошуковий термін, який ви можете перевірити, перевіривши search_term
властивістьWP_User_Search
об’єкта.
yoursite_pre_user_search()
функція для'pre_user_search'
add_action('pre_user_search','yoursite_pre_user_search');
function yoursite_pre_user_search($user_search) {
global $wpdb;
if (!is_null($user_search->search_term)) {
$user_search->query_from .= " INNER JOIN {$wpdb->usermeta} ON " .
"{$wpdb->users}.ID={$wpdb->usermeta}.user_id AND " .
"{$wpdb->usermeta}.meta_key='description' ";
$description_where = $wpdb->prepare("{$wpdb->usermeta}.meta_value LIKE '%s'",
"%{$user_search->search_term}%");
$user_search->query_where = str_replace('WHERE 1=1 AND (',
"WHERE 1=1 AND ({$description_where} OR ",$user_search->query_where);
}
}
Для пошуку кожної пари мета-значення потрібен SQL JOIN
Звичайно, ймовірна причина, що WordPress не дозволяє шукати на полях користувачів, полягає в тому, що кожен додає SQL JOIN
до запиту, а запит із занадто великою кількістю приєднань справді може бути повільним. Якщо вам дійсно потрібно здійснити пошук у багатьох полях, тоді я створив би '_search_cache'
поле в usermeta, яке збирає всю іншу інформацію в одне поле usermeta, щоб вимагати лише одного об’єднання для пошуку в ньому.
Провідні підкреслення в мета-ключах говорять WordPress не відображатись
Зауважте, що підкреслення підкреслює в '_search_cache'
WordPress, що це внутрішнє значення, а не те, що коли-небудь відображатиметься користувачеві.
Створіть кеш-пошук за допомогою 'profile_update'
і 'user_register'
гачок
Таким чином, вам потрібно буде підключити 'profile_update'
і 'user_register'
те, і інше, що спрацьовує при збереженні користувача та реєстрації нового користувача відповідно. Ви можете схопити всі мета-ключі та їх значення у цих гачках (але опустити ті зі значеннями, які є серіалізованими або масивами, кодованими URL-адресою), а потім з'єднати їх у сховище як одне довге мета-значення, використовуючи'_search_cache'
ключа.
Зберігайте мета як '|'
розділені пари ключових значень
Я вирішив схопити всі ключові імена та всі їхні значення та об'єднати їх у одну велику рядок із двокрапками (":"), що відокремлюють ключі від значень та вертикальні смуги ("|"), розділяючи пари ключових значень, як це (я обернув їх через кілька ліній, щоб ви могли їх прокручувати праворуч):
nickname:mikeschinkel|first_name:mikeschinkel|description:This is my bio|
rich_editing:true|comment_shortcuts:false|admin_color:fresh|use_ssl:null|
wp_user_level:10|last_activity:2010-07-28 01:25:46|screen_layout_dashboard:2|
plugins_last_view:recent|screen_layout_post:2|screen_layout_page:2|
business_name:NewClarity LLC|business_description:WordPress Plugin Consulting|
phone:null|last_name:null|aim:null|yim:null|jabber:null|
people_lists_linkedin_url:null
Вмикає спеціалізовані пошуки з використання мета key:value
Додавання ключа та значень, як ми робили, дозволяє вам здійснювати пошук типу " rich_editing:true
", щоб знайти всіх, хто має багате редагування чи пошук "phone:null
", щоб знайти тих, у яких немає номера телефону.
Але остерігайтеся пошукових артефактів
Звичайно, використання цієї методи створює можливі небажані артефакти пошуку, такі як пошук "бізнесу", і всі будуть в списку. Якщо це проблема, то, можливо, ви не хочете використовувати такий складний кеш.
yoursite_profile_update()
Функція для 'profile_update'
і'user_register'
Для функції yoursite_profile_update()
, як yoursite_pre_user_search()
описано вище, можна скопіювати у functions.php
файл вашої теми або ви можете використовувати у PHP-файл для написаного вами плагіна:
add_action('profile_update','yoursite_profile_update');
add_action('user_register','yoursite_profile_update');
function yoursite_profile_update($user_id) {
$metavalues = get_user_metavalues(array($user_id));
$skip_keys = array(
'wp_user-settings-time',
'nav_menu_recently_edited',
'wp_dashboard_quick_press_last_post_id',
);
foreach($metavalues[$user_id] as $index => $meta) {
if (preg_match('#^a:[0-9]+:{.*}$#ms',$meta->meta_value))
unset($metavalues[$index]); // Remove any serialized arrays
else if (preg_match_all('#[^=]+=[^&]\&#',"{$meta->meta_value}&",$m)>0)
unset($metavalues[$index]); // Remove any URL encoded arrays
else if (in_array($meta->meta_key,$skip_keys))
unset($metavalues[$index]); // Skip and uninteresting keys
else if (empty($meta->meta_value)) // Allow searching for empty
$metavalues[$index] = "{$meta->meta_key }:null";
else if ($meta->meta_key!='_search_cache') // Allow searching for everything else
$metavalues[$index] = "{$meta->meta_key }:{$meta->meta_value}";
}
$search_cache = implode('|',$metavalues);
update_user_meta($user_id,'_search_cache',$search_cache);
}
Оновлена yoursite_pre_user_search()
функція, що включає єдиний SQLJOIN
для пошуку всіх цікавих мета-значень
Звичайно, yoursite_profile_update()
щоб мати будь-який ефект, вам потрібно буде змінити, yoursite_pre_user_search()
щоб використовувати '_search_cache'
мета-ключ замість опису, який ми маємо тут (з тими ж застереженнями, як зазначено вище):
add_action('pre_user_search','yoursite_pre_user_search');
function yoursite_pre_user_search($user_search) {
global $wpdb;
if (!is_null($user_search->search_term)) {
$user_search->query_from .= " INNER JOIN {$wpdb->usermeta} ON " .
"{$wpdb->users}.ID={$wpdb->usermeta}.user_id AND " .
"{$wpdb->usermeta}.meta_key='_search_cache' ";
$meta_where = $wpdb->prepare("{$wpdb->usermeta}.meta_value LIKE '%s'",
"%{$user_search->search_term}%");
$user_search->query_where = str_replace('WHERE 1=1 AND (',
"WHERE 1=1 AND ({$meta_where} OR ",$user_search->query_where);
}
}