영어 + 숫자에 사용되는 문자로 검색을 제한하고 싶습니다. 그 이유는 mysql 로그에서 가장 느린 쿼리를 보면서 아랍, 러시아어 및 중국어 문자로 검색 한 결과 가장 빠르기 때문에 건너 뛰고 대신 오류 메시지를 표시하고 싶습니다.
영어 + 숫자에 사용되는 문자로 검색을 제한하고 싶습니다. 그 이유는 mysql 로그에서 가장 느린 쿼리를 보면서 아랍, 러시아어 및 중국어 문자로 검색 한 결과 가장 빠르기 때문에 건너 뛰고 대신 오류 메시지를 표시하고 싶습니다.
답변:
이 솔루션은 공통 및 라틴 유니 코드 스크립트의 문자 만 일치하는 정규식을 적용하여 검색 문자열을 필터링합니다.
방금 스택 오버플로에서 마음이 터졌습니다 . 알 수 있듯이 정규 표현식에는 유니 코드 "스크립트" 전체를 지정하는 값을 포함하여 전체 유니 코드 범주와 일치 하는 메커니즘 이 있습니다 . 각 유니 코드 "스크립트" 는 서로 다른 쓰기 시스템에서 사용되는 문자 그룹에 해당합니다.
\p
메타 문자 다음에 중괄호로 묶은 유니 코드 범주 식별자를 사용하여 수행됩니다. 따라서 라틴어 또는 공통 스크립트[\p{Common}\p{Latin}]
의 단일 문자와 일치합니다. 여기에는 구두점, 숫자 및 기타 기호가 포함됩니다.
따라 @ 폴 '참새 호크'곤 지적 의 u
패턴 수정 플래그 로 주제 문자열을 처리하는 PHP의 PCRE 기능을 위해서는 정규 표현식의 끝에서 설정해야합니다 UTF-8
유니 코드 인코딩.
모두 함께, 패턴
/^[\p{Latin}\p{Common}]+$/u
라틴 및 일반 유니 코드 스크립트에서 하나 이상의 문자로 구성된 전체 문자열과 일치합니다.
검색 문자열을 차단하는 좋은 장소입니다 행동 은 워드 프레스 쿼리를 실행하기 직전에 발사한다. 으로 더주의 , 이것은 또한 사용하여 수행 할 수 필터를 .pre_get_posts
request
function wpse261038_validate_search_characters( $query ) {
// Leave admin, non-main query, and non-search queries alone
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Check if the search string contains only Latin/Common Unicode characters
$match_result = preg_match( '/^[\p{Latin}\p{Common}]+$/u', $query->get( 's' ) );
// If the search string only contains Latin/Common characters, let it continue
if( 1 === $match_result )
return;
// If execution reaches this point, the search string contains non-Latin characters
//TODO: Handle non-Latin search strings
//TODO: Set up logic to display error message
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );
검색 문자열에 라틴 문자가 아닌 문자가 포함 된 것으로 확인되면 WP_Query::set()
이름을 query vars 로 변경하여 쿼리를 수정하는 데 사용할 수 있습니다 . 따라서 SQL 쿼리에 영향을 미칩니다. WordPress는 그 후 작성하고 실행합니다.
가장 관련성이 높은 쿼리 변수는 다음과 같습니다.
s
검색 문자열에 해당하는 쿼리 변수입니다. 이 값을 설정 null
하거나 빈 문자열 ( ''
)로 설정 하면 WordPress에서 더 이상 쿼리를 검색으로 처리하지 않습니다. 종종이 값은 다른 게시물의 값에 따라 모든 게시물 또는 사이트의 첫 페이지를 표시하는 아카이브 템플릿이됩니다. 검색어 변수 ' '
그러나 단일 공백 ( )으로 설정하면 WordPress에서 검색으로 인식하여 search.php
템플릿 을 표시하려고합니다 .page_id
사용자를 선택한 특정 페이지로 안내하는 데 사용될 수 있습니다.post__in
검색어를 특정 게시물로 제한 할 수 있습니다. 불가능한 게시물 ID를 가진 배열로 설정 하면 쿼리가 절대적으로 아무것도 반환하지 않도록 측정하는 역할을 할 수 있습니다 .위의 사항을 염두에두고 search.php
결과없이 템플릿을 로드하여 잘못된 검색에 응답하기 위해 다음을 수행 할 수 있습니다 .
function wpse261038_validate_search_characters( $query ) {
// Leave admin, non-main query, and non-search queries alone
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Check if the search string contains only Latin/Common Unicode characters
$match_result = preg_match( '/^[\p{Latin}\p{Common}]+$/u', $query->get( 's' ) );
// If the search string only contains Latin/Common characters, let it continue
if( 1 === $match_result )
return;
$query->set( 's', ' ' ); // Replace the non-latin search with an empty one
$query->set( 'post__in', array(0) ); // Make sure no post is ever returned
//TODO: Set up logic to display error message
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );
실제로 오류 메시지를 표시하는 방법은 응용 프로그램 및 테마 기능에 따라 크게 달라집니다.이 작업을 수행하는 방법에는 여러 가지가 있습니다. 테마가 get_search_form()
검색 템플리트를 호출 하는 경우 가장 쉬운 해결책은 pre_get_search_form
조치 후크를 사용 하여 검색 양식 바로 위에 오류를 출력하는 것입니다.
function wpse261038_validate_search_characters( $query ) {
// Leave admin, non-main query, and non-search queries alone
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Check if the search string contains only Latin/Common Unicode characters
$match_result = preg_match( '/^[\p{Latin}\p{Common}]+$/u', $query->get( 's' ) );
// If the search string only contains Latin/Common characters, let it continue
if( 1 === $match_result )
return;
$query->set( 's', ' ' ); // Replace the non-latin search with an empty one
$query->set( 'post__in', array(0) ); // Make sure no post is ever returned
add_action( 'pre_get_search_form', 'wpse261038_display_search_error' );
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );
function wpse261038_display_search_error() {
echo '<div class="notice notice-error"><p>Your search could not be completed as it contains characters from non-Latin alphabets.<p></div>';
}
오류 메시지를 표시 할 수있는 다른 가능성은 다음과 같습니다.
wp_enqueue_script
후크 를 추가하십시오. 로모그래퍼 $priority
큰 것보다하는 대기열에 자바 스크립트 및 사용은 wp_localize_script()
귀하의 오류 메시지를 포함하는 변수를 설정합니다.wp_redirect()
원하는 URL로 사용자를 보내 (이 방법은 추가 페이지로드 필요).s
에 쿼리 변수를 ''
대신 ' '
사용 page_id
대신에 post__in
사용자가 선택한 페이지를 반환하기 위해.loop_start
후크 를 사용 WP_Post
하여 오류를 포함 하는 가짜 개체를 쿼리 결과에 삽입하십시오. 이는 가장보기 흉악한 해킹이며 특정 테마에는 맞지 않을 수 있지만 "결과 없음"메시지를 억제하는 데 잠재적으로 바람직한 부작용이 있습니다.template_include
필터 후크를 사용 하여 테마 또는 플러그인에서 오류를 표시하는 사용자 정의 템플리트로 검색 템플리트를 교체하십시오.문제의 주제를 조사하지 않으면 어느 경로를 밟아야할지 결정하기가 어렵습니다.
아래의 내 솔루션 은 문자열을 구성하는 바이트 배열을보고 마법의 신성한 알파벳을 찾으려고 PHP의 mbstring 함수 를 악용하는 해킹입니다 . 이것은 정말 나쁜 생각이며 오류가 발생하기 쉽습니다. .
훨씬 간단하고 훨씬 안정적인 솔루션에 대한 다른 답변 을 참조하십시오 .
비 라틴 문자를 사용하는 검색을 방지하는 한 가지 방법은 PHP의 mb_detect_encoding()
기능 을 사용 하여 검색 문자열이 사용자 정의 된 문자 인코딩 중 하나를 따르는 지 확인하는 것입니다. 이것을하기에 좋은 곳 은pre_get_posts
작업 action 입니다. 쿼리가 실행되기 직전에 실행됩니다.
검색에서 유효하지 않은 인코딩을 사용하고 있다고 판단한 후 실제로 수행하는 작업은 실제로 응용 프로그램마다 다릅니다. 여기에서는 WordPress가 여전히 쿼리를 검색으로 해석하여 search.php
템플릿을 로드하도록 검색 쿼리를 단일 공간으로 설정했습니다 (검색 문자열이 빈 문자열). 또한 설정에 대한 추가 예방 조치를 취 합니다.'post__in'
아무 것도 반환되지 않도록하기 위해 포스트 ID가 불가능한 배열로 .
또는, 당신은에 검색 문자열을 설정하는 것이 좋습니다 null
및 설정 page_id
사용자 지정 오류 메시지가있는 페이지로 사용자를 위해.
function wpse261038_validate_search_query_encoding( $query ) {
$valid_encodings = array( 'Windows-1252' );
// Ignore admin, non-main query, and non-search queries
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Retrieve the encoding of the search string (if it's one listed in $valid_encodings)
$search_encoding = mb_detect_encoding( $query->get( 's' ), $valid_encodings, true );
// If the search encoding is one in $valid_encodings, leave the query as-is
if( in_array( $search_encoding, $valid_encodings ) )
return;
// If it wasn't, sabotage the search query
$query->set( 's', ' ' );
$query->set( 'post__in', array(0) );
// Set up your error message logic here somehow, perhaps one of the following:
// - Add a template_include filter to load a custom error template
// - Add a wp_enqueue_scripts hook with a greater priority than your theme/plugin's, and
// use wp_localize_script() in the hook to pass an error message for your JavaScript
// to display
// - Perform a wp_redirect() to send the user to the URL of your choice
// - Set a variable with an error message which your theme or plugin can display
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_query_encoding' );
PHP에서 지원하는 모든 기본 인코딩 과 다른 알파벳의 더미 문자열을 비교하는 적용 범위 테스트를 작성했습니다 . 그것은 어떤 스트레칭으로도 완벽하지는 않습니다 (내 더미 문자열이 얼마나 현실적인지 전혀 알지 못하고 일본어 감지에 질식하는 것처럼 보입니다).하지만 후보자를 결정하는 데 다소 유용합니다. 당신은 그것을 실제로 볼 수 있습니다여기 .
해당 테스트에서 플래그가 지정된 잠재적 문자 인코딩을 조사한 후 다음과 같습니다. Windows-1252
는 라틴 알파벳과 일반적인 라틴 언어의 악센트를 포함하여 필요에 맞는 완벽한 선택 인 .
의 선택 ISO-8859
문자 세트는 해야 하지만 이유는 내가 주위에 내 머리를 정리 할 수없는 또 다른 실행 가능한 선택의 mb_
기능을 구별하지 않는 것ISO-8859
별도의 인코딩로 목록에도 불구하고,의 다른 문자 집합.
다른 일반적인 문자를 허용하려면 추가를 고려할 수도 있습니다 HTML-ENTITIES
.
ISO-8859
인코딩 을 구별 할 수없는 것 같습니다 .
@MichaelRogers가 며칠 전에 비슷한 질문을 게시했을 때 @MichaelRogers에게 설명하려고 시도했을 때 문자열에 사용 된 문자 세트 (또는 스크립트)를 아는 것만으로 는 해당 문자열 의 언어 를 감지하기에 충분 하지 않습니다 .
따라서 @bosco 가 자세히 설명 한 방법 은 러시아어 등의 문자열을 제거하지만 (아래 2 수정) 검색을 영어로 제한 하지는 않습니다 .
이것을 보려면 다음을 시도하십시오.
$strings = array (
'I\'m sorry', // English
'Je suis désolé', // French
'Es tut mir Leid', // German
'Lorem ipsum dolor sit amet', // Lorem ipsum
'أنا سعيد', // Arabic
'я счастлив', // Russian
'我很高兴', // Chinese (Simplified)
'我很高興', // Chinese (Traditional)
) ;
foreach ($strings as $s) {
if (preg_match ('/^[\p{Latin}\p{Common}]+$/u', $s) === 1) {
echo "$s: matches latin+common\n" ;
}
else {
echo "$s: does not match latin+common\n" ;
}
}
[ 참고 : @bosco가 제공 한 내용에 대해 위에서 언급 한 2 가지 수정 사항은 다음과 같습니다.
/u
수정 자 추가 (패턴 및 주제를 UTF-8 인코딩으로 처리해야 함, PHP : 정규식 패턴 수정 자 참조 )그것은 생산할 것이다 :
I'm sorry: matches latin+common
Je suis désolé: matches latin+common
Es tut mir Leid: matches latin+common
Lorem ipsum dolor sit amet: matches latin+common
أنا سعيد: does not match latin+common
я счастлив: does not match latin+common
我很高兴: does not match latin+common
我很高興: does not match latin+common
[ 참고 : 나는 영어, 프랑스어 및 일부 독일어 (그리고 약간의 Lorem ipsum) :-)를 사용하지만 아랍어, 러시아어 및 중국어는 Google Translate에 의존합니다.]
보시다시피 라틴 스크립트 확인에만 의존하는 것은 아닙니다 한다고해서 영어가 확실 .
StackOverflow 에는 주제에 대한 자세한 정보를 제공하는 많은 스레드가 있습니다 (예 : PHP의 문자열에서 언어 감지 ).