묻고답하기

검색할 때 정확히 일치하는 문자만 검색하고 싶습니다.  

예를 들면 이전 게시판에 있던 내용인데요, (https://www.xpressengine.com/qna/17081372)

male이란 단어의 검색 결과가 male과 female 다 나오는데 

이럴 경우 정확히 male만 가진 글을  어떻게 다중 검색 할 수 있나요?

 

https://xetown.com/rxe_point/1006439

위에 링크로 애드온(다중검색) 설치했습니다.  

작동방식은 기본 다중검색 방식 : AND , 다중선택 변수 검색방식 : AND 입니다. 

가능하다면 아래 코드로 수정 가능한지 확인 부탁드립니다. ㅠㅠ 

 

<?php

/**
 * @file ap_extra_search.addon.php
 * @author cydemo <cydemo@gmail.com>
 */

if ( !defined('__XE__') ) return;

if ( $called_position === 'after_module_proc' && $this->module === 'board' && $this->act === 'dispBoardContent' )
{
if ( array_map('trim', explode(',', $addon_info->position))[0] === '' )
{
return;
}
// 검색 방식 설정
$addon_info->type = $addon_info->type ? $addon_info->type : 'and';
$addon_info->type_multi = $addon_info->type_multi ? $addon_info->type_multi : 'or';
$addon_info->select2radio = $addon_info->select2radio ? $addon_info->select2radio : 'N';
$addon_info->basic = $addon_info->basic ? $addon_info->basic : 'N';
$addon_info->signature = $addon_info->signature ? $addon_info->signature : 'N';
$addon_info->range_search = $addon_info->range_search ? $addon_info->range_search : 'N';

// document 모듈의 모델 호출
$oDocumentModel = getModel('document');

// 현재 모듈의 확장변수 사용자정의 호출
$_extra_keys = $oDocumentModel->getExtraKeys($this->module_srl);

// document 모듈 쿼리 실행을 위한 기본 설정값 지정
$module_info = $this->module_info;
$args = new stdClass();
$args->module_srl = $module_info->module_srl;
$args->category_srl = Context::get('category');
$args->status = 'PUBLIC';

// 문서 목록 작업을 위한 배열 변수 정의
$cond = array();
$extra_keys = array();
$srl_list = array();
$is_search = false;
$search_session = false;

// 애드온이 게시판 기본검색까지도 다중검색에 포함하는 경우
if ( $addon_info->basic === 'Y' )
{
// 기본검색의 검색대상에서 확장변수를 제거
Context::set('search_option', array_intersect_key
(
Context::get('search_option'), array_flip($this->search_option)
)
);
// 기본검색의 쿼리 실행
if ( Context::get('search_target') && Context::get('search_keyword') )
{
$query_id = 'addons.ap_extra_search.getDocumentList';
$search_target = Context::get('search_target');
$search_keyword =  Context::get('search_keyword');
switch($search_target)
{
case 'title_content' :
$search_keyword = str_replace(' ', '%', $search_keyword);
$args->s_title = $search_keyword;
$args->s_content = $search_keyword;
break;
case 'comment' :
$args->s_comment = $search_keyword;
$query_id = 'addons.ap_extra_search.getDocumentListWithinComment';
break;
case 'tag' :
$args->s_tags = str_replace(' ', '%', $search_keyword);
break;
default :
$search_keyword = str_replace(' ', '%', $search_keyword);
$args->{'s_'.$search_target} = $search_keyword;
break;
}
$srl_list = executeQueryArray($query_id, $args)->data;
$search_session = true;
}
$is_search = true;
Context::set('search_keyword', str_replace('%', ' ', $search_keyword));
}

// 현재 모듈에 사용자정의된 확장변수가 있을 때만 실행
if ( count($_extra_keys) )
{
$is_range_date = false;
$is_range_data = false;

// 확장변수 다중검색
foreach ($_extra_keys as $key => $val)
{
// 파라미터에 지정된 변수값을 $cond에 저장
if ( Context::get('extra_vars' . $key) )
{
$cond[$key] = Context::get('extra_vars' . $key);
}

// 검색 가능한 확장변수만 $extra_keys에 저장 (이후 before_display_content 호출 시점에 재활용)
if ( $val->search === 'Y' )
{
// 범위 검색 적용되는 변수 여부 확인
if ( $addon_info->range_search === 'Y' && in_array($val->eid, array_map('trim', explode(',', $addon_info->range_search_target))) )
{
if ( $val->type === 'date' )
{
$is_range_date = true;
}
else
{
$is_range_data = true;
$args->var_eid = $eid = $val->eid;
$max_min = executeQueryArray('addons.ap_extra_search.getMaxAndMinValueWithinExtraVars', $args)->data;
$val->max = $max_min[0]->max;
$val->min = $max_min[0]->min;
}
}

$is_search = true;
$extra_keys[$key] = $val;
}

// 파라미터에 변수값이 있는 경우에만 검색된 document 정보를 $srl_list에 저장
if ( $cond[$key] )
{
// 해당 키값을 기본 설정값으로 저장, 그리고 해당 변수값이 담긴 문서의 총 개수를 구해서, 목록 개수 변수값으로 저장
$args->var_idx = $key;

// 확장변수 변수값이 배열인 경우 (즉, 다중선택 체크박스인 경우)
if ( is_array($cond[$key]) )
{
// 배열을 문자열로 바꿔 변수값을 서버에 저장. 이 값은 페이지 뒤로가기나 앞으로가기를 할 때 기억됨
$val->setValue(implode('|@|', $cond[$key]));

// AND 검색인 경우
if ( $addon_info->type === 'and' )
{
// 기본 검색은 AND이지만 다중선택 변수는 OR 검색으로 설정한 경우
if ( $addon_info->type_multi === 'or' )
{
// 다중선택 형식 확장변수의 OR 검색 결과값으로 이뤄진 별도의 문서 목록 생성
$_srl_list = array();
foreach ( $cond[$key] as $k => $v )
{
$args->var_value = $v;
$srls = executeQueryArray('addons.ap_extra_search.getDocumentListWithExtraVars', $args)->data;

// OR 검색에 맞게 중복 배열을 정리
$_srl_list = array_merge($_srl_list, $srls);
$_srl_list = array_values(array_map(
'unserialize',
array_unique(
array_map(
'serialize',
$_srl_list
)
)
));
}

// 출력할 문서 목록이 비어 있고 확장변수 검색 세션에서 현재 변수가 처음일 경우, 별도의 문서 목록 $_srl_list를 출력용 문서 목록 $srl_list에 병합
if ( $srl_list === array() && $search_session === false )
{
$srl_list = array_merge($srl_list, $_srl_list);
$search_session = true;
}

// AND 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_intersect(
array_map(
'serialize',
$srl_list
),
array_map(
'serialize',
$_srl_list
)
)
));
}
// 기본 검색과 마찬가지로 다중선택 변수도 AND 검색으로 설정한 경우
else
{
foreach ( $cond[$key] as $k => $v )
{
$args->var_value = $v;
$srls = executeQueryArray('addons.ap_extra_search.getDocumentListWithExtraVars', $args)->data;

// 출력할 문서 목록이 비어 있고 확장변수 검색 세션에서 현재 변수가 처음일 경우, 검색 결과값 $srls를 출력용 문서 목록 $srl_list에 병합
if ( $srl_list === array() && $search_session === false )
{
$srl_list = array_merge($srl_list, $srls);
$search_session = true;
}

// AND 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_intersect(
array_map(
'serialize',
$srl_list
),
array_map(
'serialize',
$srls
)
)
));
}
}
}
// OR Search
else
{
foreach ( $cond[$key] as $k => $v )
{
$args->var_value = $v;
$srls = executeQueryArray('addons.ap_extra_search.getDocumentListWithExtraVars', $args)->data;

// 결과값을 출력용 변수에 모두 병합
$srl_list = array_merge($srl_list, $srls);

// OR 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_unique(
array_map(
'serialize',
$srl_list
)
)
));
}
}
}
// 확장변수 변수값이 그냥 문자열인 경우
else
{
// 변수값을 서버에 저장. 이 값은 페이지 뒤로가기나 앞으로가기를 할 때 기억됨
$val->setValue($cond[$key]);
$args->var_value = $cond[$key];
// 범위 검색 여부에 따라 별도 쿼리 실행
if ( $addon_info->range_search === 'Y'
&& in_array($val->eid, array_map('trim', explode(',', $addon_info->range_search_target)))
&& (Context::get('extra_vars'.$val->idx) && Context::get('extra_vars'.$val->idx.'-2')) )
{
$args->var_eid = $val->eid;
$args->var_start_value = Context::get('extra_vars'.$val->idx);
$args->var_end_value = Context::get('extra_vars'.$val->idx.'-2');
$srls = executeQueryArray('addons.ap_extra_search.getDocumentListWithinExtraVars', $args)->data;
}
else
{
$srls = executeQueryArray('addons.ap_extra_search.getDocumentListWithExtraVars', $args)->data;
}

// AND Search
if ( $addon_info->type === 'and' )
{
// 출력할 문서 목록이 비어 있고 검색 세션에서 현재 변수가 처음일 경우, 검색 결과값 $srls를 출력용 문서 목록 $srl_list에 병합
if ( $srl_list === array() && $search_session === false )
{
$srl_list = array_merge($srl_list, $srls);
$search_session = true;
}

// AND 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_intersect(
array_map(
'serialize',
$srl_list
),
array_map(
'serialize',
$srls
)
)
));
}
// OR Search
else
{
// 결과값을 출력용 변수에 모두 병합
$srl_list = array_merge($srl_list, $srls);

// OR 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_unique(
array_map(
'serialize',
$srl_list
)
)
));
}
}
}
}

// 범위 검색 사용시 라이브러리 로드
if ( $addon_info->range_search === 'Y' )
{
if ( $is_range_date === true )
{
Context::loadFile('./addons/ap_extra_search/js/moment.js');
Context::loadFile('./addons/ap_extra_search/js/moment-with-locales.js');
Context::loadFile('./addons/ap_extra_search/js/daterangepicker.js');
Context::loadFile('./addons/ap_extra_search/js/date_range_search.js');
Context::loadFile('./addons/ap_extra_search/js/daterangepicker.css');
}
if ( $is_range_data === true )
{
Context::loadFile('./common/js/plugins/ui/jquery-ui.min.js');
Context::loadFile('./common/js/plugins/ui/jquery-ui.min.css');
Context::loadFile('./addons/ap_extra_search/js/data_range_search.js');
}
}
}

// 애드온 변수를 스킨에 전달
Context::set('extra_search', $addon_info);

// 애드온이 게시판 서명검색까지도 다중검색에 포함하는 경우
if ( $addon_info->signature === 'Y' )
{
if ( Context::get('search_signature') )
{
$search_signature = Context::get('search_signature');
$args = new stdClass();
$args->module_srl = $module_info->module_srl;
$args->category_srl = Context::get('category');
$member_list = executeQueryArray('addons.ap_extra_search.getMemberList', $args)->data;

// AND Search
if ( $addon_info->type === 'and' )
{
$_srl_list = array();
foreach ($member_list as $member_info)
{
$sign_text = strip_tags(getModel('member')->getSignature($member_info->member_srl));
if ( strpos($sign_text, $search_signature) !== false )
{
$args->member_srl = $member_info->member_srl;
$srls = executeQueryArray('addons.ap_extra_search.getDocumentList', $args)->data;

// 회원별로 서명검색 결과 누적
$_srl_list = array_merge($_srl_list, $srls);
$_srl_list = array_values(array_map(
'unserialize',
array_unique(
array_map(
'serialize',
$_srl_list
)
)
));
}
}

// 출력할 문서 목록이 비어 있고 검색 세션에서 현재 변수가 처음일 경우, 별도의 문서 목록 $_srl_list를 출력용 문서 목록 $srl_list에 병합
if ( $srl_list === array() && $search_session === false )
{
$srl_list = array_merge($srl_list, $_srl_list);
$search_session = true;
}

// AND 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_intersect(
array_map(
'serialize',
$srl_list
),
array_map(
'serialize',
$_srl_list
)
)
));
}
// OR Search
else
{
foreach ($member_list as $member_info)
{
$sign_text = strip_tags(getModel('member')->getSignature($member_info->member_srl));
if ( strpos($sign_text, $search_signature) !== false )
{
$args->member_srl = $member_info->member_srl;
$srls = executeQueryArray('addons.ap_extra_search.getDocumentList', $args)->data;

// 결과값을 출력용 변수에 모두 병합
$srl_list = array_merge($srl_list, $srls);

// OR 검색에 맞게 중복 배열을 정리
$srl_list = array_values(array_map(
'unserialize',
array_unique(
array_map(
'serialize',
$srl_list
)
)
));
}
}
}
}
$is_search = true;
Context::set('search_signature', $search_signature);
}

// 주소창 파라미터의 확장변수 개수를 전역 변수로 설정, 그리고 검색 가능한 확장변수의 리스트를 따로 뽑아 전역 변수로 설정
Context::set('is_search', $is_search);
Context::set('extra_keys', $extra_keys);

// 기본검색, 확장변수, 서명검색 등이 시도됐으면 결과값에 따라 문서 목록과 페이지 네비게이션 조정
if ( count($cond) || ( Context::get('search_target') && Context::get('search_keyword') ) || Context::get('search_signature') )
{
// 그리고 취합된 검색결과가 있으면
if ( count($srl_list) )
{
// 페이지 네비게이션 설정
$total_count = count($srl_list);
$total_page = ceil($total_count / $module_info->list_count);
if ( $total_page < 1 )
{
$total_page = 1;
}
$page = Context::get('page') ? abs(Context::get('page')) : 1;
if ( $page > $total_page )
{
$page = $total_page;
}

$page_navigation = new PageHandler($total_page, $total_page, $page, $module_info->page_count);
Context::set('page_navigation', $page_navigation);

// 문서 목록 설정 :: sort_index와 order_type 정리하고 이에 따라 문서 목록 재배열
$order_target = Context::get('sort_index') ? Context::get('sort_index') : $module_info->order_target;
$order_type = Context::get('order_type') ? Context::get('order_type') : $module_info->order_type;

foreach ($srl_list as $key => $val)
{
if ( in_array($order_target, array('list_order', 'regdate', 'last_update', 'update_order', 'readed_count', 'voted_count', 'blamed_count', 'comment_count', 'trackback_count', 'uploaded_count', 'title', 'category_srl', 'nick_name', 'user_name', 'user_id')) )
{
$sort_key[$key] = $val->$order_target;
}
else
{
$extra_vars = $oDocumentModel->getExtraVars($module_info->module_srl, $val->document_srl);
foreach ( $extra_vars as $v )
{
if ( $v->eid === $order_target )
{
$sort_key[$key] = $v->value;
break;
}
}
}
$sort_key2[$key] = $key;
}
array_multisort($sort_key, $sort_key2, $srl_list);
if ( $order_type === 'desc' )
{
$srl_list = array_reverse($srl_list);
}

// 문서 목록 설정 :: 문서번호를 역순으로 넣고, 목록에 담길 문서 개수(list_count)에 따라 전체 문서목록을 나눠줌
$no = count($srl_list);
for ( $i = 0; $i < count($srl_list); $i++ )
{
$document_list[$no] = $oDocumentModel->getDocument($srl_list[$i]->document_srl);
$no--;
}

$document_list = array_slice($document_list, $module_info->list_count * ($page - 1), $module_info->list_count, true);
Context::set('document_list', $document_list);
}
// 취합된 검색결과가 없으면
else
{
// 페이지 네비게이션은 초기화
$page_navigation = new PageHandler(1, 1, 1, $module_info->page_count);
Context::set('page_navigation', $page_navigation);

// 문서목록 비우기
$document_list = array();
Context::set('document_list', $document_list);
}
}
// 검색이 시도되지 않았다면 애드온 실행 중지. 출력화면에는 정상적인 문서목록과 페이지 네비게이션이 나오게 됨
else
{
return;
}
}

if ( $called_position === 'before_display_content' && Context::getResponseMethod() === 'HTML' && Context::get('is_search') )
{
// 검색창 삽입 지점 옵션 설정
$addon_info->spot = $addon_info->spot ? $addon_info->spot : 'above';

// 다국어 지원 언어팩 임포트
Context::loadLang(_XE_PATH_ . 'addons/ap_extra_search/lang');

// 애드온 스킨 파일의 경로 확인
$tpl_file = 'extra.html';
$addon_info->skin = file_exists('./addons/ap_extra_search/skins/' . $addon_info->skin . '/' . $tpl_file) ? $addon_info->skin : 'sketchbook5';
$tpl_path = './addons/ap_extra_search/skins/' . $addon_info->skin;

// 애드온 스킨 파일을 컴파일
$oTemplate = &TemplateHandler::getInstance();
$tpl = $oTemplate->compile($tpl_path, $tpl_file);

// 검색창 삽입 위치를 찾은 후, 삽입 지점에 따라 출력
foreach ( array_map('trim', explode(',', $addon_info->position)) as $position )
{
$pattern = '/<(\w+)[^>]*class=("|\')[^"\']*\b' . $position . '\b[^"\']*\2[^>]*>.*?<\/\1>/is';
if ( preg_match($pattern, $output) )
{
if ( $addon_info->spot === 'above' )
{
$output = preg_replace($pattern, $tpl . '$0', $output);
}
elseif ( $addon_info->spot === 'below' )
{
$output = preg_replace($pattern, '$0' . $tpl, $output);
}
break;
}
}
}

 

글쓴이 제목 최종 글
XE 공지 글 쓰기,삭제 운영방식 변경 공지 [16] 2019.03.05 by 남기남
무지개c34b6 최신글 업데이트 날짜 표시하는 소스 file  
닥터맨 xe현재 버전 php.5.3.에서 사용할 수 있나요? [2] 2018.10.21 by 닥터맨
railman 회원 탈퇴후에 1주일이던지 아니면 한달이던지 기간동안 다시 재가입을 할수 없게 못할까요? [1] 2018.10.21 by sejin7940
rail_man 가입인증 메일 발송 후 회원이 확인할 때 나타나는 메세지 file  
푸푸 관리페이지에서 업데이트를 눌렀떠니 fatal error가 뜹니다. file  
건방진천사 서버 이전하고, xe 설치했는데요, 기존 제로보드 게시판이 안 열려요. [1] 2018.10.20 by sejin7940
데이지 회원가입이 작동하지 않아요  
문화사랑 홈페이지가 갑자기 너무 느려졌어요!외 2건 [1] 2018.10.19 by 문화사랑
rail_man 신규 게시글에 NEW 아이콘(이미지)이 나타나지 않게 [1] file 2018.10.19 by sejin7940
토실이 최신버젼 업데이트 후에 관리자 로그인이 안됩니다.  
박펌 퍼미션 질문 좀 요  
keeeek 작성글보기 모듈에서 제목이 아닌 내용을 불러오는법 [2] 2018.10.19 by keeeek
이음 설치 환경 수집 동의 에러 [2] file 2018.10.18 by 이음
하나보드 로그인 세션 타임 설정은?  
호돌이옆집아저씨 다음과 같은 표에 URL 을 새창열기로 링크 되게 할 수 있나요? [1] 2018.10.18 by 너에게제공
socoolg 게시판의 상단. 하단 내용에 '\' 기호가 삽입됩니다. [1] file 2018.10.18 by 너에게제공
lun**** 누리고 상품등록 file  
sonssi1214 의뢰마당에서 댓글은 레벨제한이 있는건가요? [1] 2018.10.17 by 너에게제공
krise 기본 url를 바꿨더니 문제가 생겼습니다. [2] 2018.10.17 by krise
드카이 플랜너123 달력위젯 크기 위치 변경 방법을 조언 file  
종석 스케치북 게시판 스킨 뷰어 수정문의  
리리즈 구글검색 결과 삭제 방법 부탁드립니다.  
대한국인 관리창에서 메뉴 생성할 때, 바로가기에 입력한 URL이 새로운 창으로 열리게 하는 방법이?? [2] 2018.10.16 by 대한국인
lazar**** 모바일 게시판에서는 확장변수를 출력하게 할 수는 없나요? [2] 2018.10.16 by lazar****
모얼더 xe 언어 질문드립니다 [2] 2018.10.16 by 모얼더
뚜두 로그인시 '존재하지 않는 회원 아이디입니다'라고 뜹니다 [1] 2018.10.16 by sejin7940
얼그레이8ef56 페이지에서 <i class="xi-trending-up"></i> 삽입시 저장하면 em태그로 변경됨 [4] 2018.10.16 by plusnet21
립샤 고수님들 제발 도와주세요. 창크기에 따라서 위젯 위치가 자꾸 변합니다 [1] 2018.10.15 by 르미
솔드 onmouseover,onmouseout 관련 질문 ..  
이온디 제로보드 스킨 자료실은 열어주시면 안되나요? [5] 2018.10.14 by 해피정