묻고답하기

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

예를 들면 이전 게시판에 있던 내용인데요, (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 남기남
brodmea 메인 페이지 HTTP 500 Error [3] 2019.01.04 by brodmea
퓨라 카메론 위젯에서 날짜부분을 올리고 싶어요. [1] file 2019.01.03 by 디자인클립
소시민4 홈페이지 메뉴 클릭시 제대로 안 넘어가는 문제 [1] 2019.01.03 by DoorWeb
문화사랑 500오류  
누들그라탕 상세설정 에서 상단 내용 [6] file 2019.01.02 by 하이하이데스
검은내일 서브메뉴 소스 질문 [6] 2019.01.02 by 검은내일
쟈니 sketchbook5 스케치북 아이콘 수정은 어디서 하나요? [1] file 2019.01.02 by sejin7940
쏘쏘쏘 회원정보보기 관련 [1] 2019.01.02 by sejin7940
enjoyfun 게시판에서 다른 사용자 글을 수정 할 수 있는 방법은? [2] 2019.01.02 by sejin7940
날제비 한글파일 깨지는 이유....문의 [2] 2019.01.02 by 날제비
서울갈매기 드롭다운 메뉴 서브메뉴 크기 변경 방법 질문좀 드릴게요 [1] file 2019.01.02 by DoorWeb
희망 XEDITION 레이아웃 헤더 스크립트 문제 [2] 2019.01.01 by 팔공산
잊혀진호돌이 회원 가입 폼 수정 문의 [1] file 2019.01.01 by 즈베즈다
CHOIe081a 모바일만 사용할수 있나요? [1] 2019.01.01 by DoorWeb
Hexa 로그인, 회원가입 부분만 MS-SQL을 쓸수 있나요?  
날제비 레이아웃 편집관련 문의 [3] file 2018.12.31 by DoorWeb
Koreareview CONTACT US 문구 수정법 알려 주세요~ [1] file 2018.12.31 by DoorWeb
이원태 카테코리 추출  
LAN 전문가님들 도와주세여 ... file  
엘리할배 sketchbook5 웹진형 섬네일 출력이 안됩니다. [1] 2018.12.28 by sejin7940
이봉교 반응형으로 홈페이지 만드려고 하는데요 모바일에 이미지는 왜 그대로죠? [2] 2018.12.28 by 이봉교
엘리할배 sketchbook5 설정 문의드립니다. file  
누들그라탕 홈페이지 접속 시 xe설치 화면 뜨는 문제 [1] file 2018.12.28 by sejin7940
백곰 삭제된 게시물을 볼 수 있는 방법 알려주세요 [1] 2018.12.28 by sejin7940
SJ_KK3 모바일에서 팝업2개가 안띄워집니다..  
787dreamliner 사이트 이전시 첨부파일 손상 [1] 2018.12.28 by 787dreamliner
정민이 특정화면에서 controller 응답값을 못받아 오는 이유  
상해파 xe 버젼 확인 방법은? [2] 2018.12.27 by 상해파
황마마 스케치북5 모바일 보드스킨 검색창이 안나오네요 [2] 2018.12.27 by 티지레몬
레전드 방문자의 접근을 혀용하고 싶습니다. [2] file 2018.12.27 by 레전드