Extra Form
PHP PHP 7.4
CMS Rhymix 2.1

게시판 목록을 가나다/ABC별로 볼 수 있도록 쿼리를 짜서 목록을 가로채려고 하고 있는데요.

 

쿼리별로

<condition operation="like_prefix" column="title" var="title_prefix" /> 또는

<condition operation="like_prefix" column="documents.title" var="title_prefix" pipe="and" />

이런 식으로 해서 다행히 영어로는 목록이 만들어지고 있습니다.

 

근데 문제는 한글이네요.

애석하게도 ㅋ 같은 값으로는 카로 시작하는 제목의 데이터를 뽑아주질 못합니다.

검색해보니 select * from documents where title >= '카' and title <= '킿'

같은 식으로 데이터를 뽑아주면 될 것 같은데요.

이것도 초성 검색으로는 말이 되는지 잘 모르겠고요.

 

암튼 이런 아이디어를 쿼리 xml 파일에 넣어줄 방법이 있을까요?

아니면 그냥 커스텀 쿼리를 짜야 하나요... (문서목록 커스텀 쿼리 겁나 빡센데ㅜ)

  • Lv36

    <condition operation="gte" column="title" var="title1" />
    <condition operation="lte" column="title" var="title2" />

    이렇게 조건을 걸고 (gte = greater than or equal to, lte = less than or equal to의 줄임말입니다. XE 시절부터 사용하던 more, less 연산자는 equal을 포함하는지 안 하는지 의미가 명확히 와닿지 않기 때문에 비추입니다. 만약 equal을 포함하지 않는 부등호가 필요하다면 gt, lt를 쓰면 됩니다.)

    $args->title1 = '카';
    $args->title2 = '킿';

    이렇게 각각 따로 넘기면 될 것 같은데요?

    <condition operation="between" column="title" var="title_prefixes" />
    $args->title_prefixes = ['카', '킿'];

    이렇게 할 수도 있는데, 한글 초성 검색이 between에서도 통하는지는 잘 모르겠습니다.

    이런 종류의 쿼리가 DB를 터뜨리지 않고 빨리 실행될지도 의문이고요.

  • Lv36 Lv19

    늦은 시간에 답변 감사합니다. 다행히 between으로 잘 됩니다.

    https://dev.aporia.blog/board_fKje48/?title_prefix=ㅋ

    덕분에 코드도 일사분란해졌어요ㅎㅎ


    애드온에서 Context::get('title_prefix')로 파라미터값을 받아서 한글 초성이랑 영어 알파벳이 아니면 작동을 중지하고, 유효성 테스트를 통과하면 아래처럼 전달하게 했습니다.
    영어는 between이 필요 없으니 그냥 $args->title_prefix로 가서 like_prefix으로 처리했고요.
    감사합니다!

    (근데 정규식이 ㅋ 같은 게 ㄱ-ㅎ으로는 이상하게 안 먹히고 있어서 전부 나열해버렸는데 나름 보기 좋습니다ㅋㅋㅋ 그리고 알파벳과 달리 글자 끝에 +를 붙여야 되는 초성도 있더라구요. 신기한 한글 세상인지 php 세상인지 @@)

    // 한글 초성이 들어왔을 경우 범위 검색으로 대체
    if ( preg_match('/^[ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ]+$/', $title_prefix) )
    {
        $args->title_prefix = null;
        $args->title_prefixes = [];
        switch ( $title_prefix )
        {
            case 'ㄱ' : $args->title_prefixes = ['가', '깋']; break;
            case 'ㄲ' : $args->title_prefixes = ['까', '낗']; break;
            case 'ㄴ' : $args->title_prefixes = ['나', '닣']; break;
            case 'ㄷ' : $args->title_prefixes = ['다', '딯']; break;
            case 'ㄸ' : $args->title_prefixes = ['따', '띻']; break;
            case 'ㄹ' : $args->title_prefixes = ['라', '맇']; break;
            case 'ㅁ' : $args->title_prefixes = ['마', '밓']; break;
            case 'ㅂ' : $args->title_prefixes = ['바', '빟']; break;
            case 'ㅃ' : $args->title_prefixes = ['빠', '삫']; break;
            case 'ㅅ' : $args->title_prefixes = ['사', '싷']; break;
            case 'ㅆ' : $args->title_prefixes = ['싸', '앃']; break;
            case 'ㅇ' : $args->title_prefixes = ['아', '잏']; break;
            case 'ㅈ' : $args->title_prefixes = ['자', '짛']; break;
            case 'ㅉ' : $args->title_prefixes = ['짜', '찧']; break;
            case 'ㅊ' : $args->title_prefixes = ['차', '칳']; break;
            case 'ㅋ' : $args->title_prefixes = ['카', '킿']; break;
            case 'ㅌ' : $args->title_prefixes = ['타', '팋']; break;
            case 'ㅍ' : $args->title_prefixes = ['파', '핗']; break;
            case 'ㅎ' : $args->title_prefixes = ['하', '힣']; break;
            default : $args->title_prefixes = null; break;
        }
    }
    else
    {
        $args->title_prefix = $title_prefix ?? null;
        $args->title_prefixes = null;
    }

     

  • Lv19 Lv36

    한글을 정규식에 사용하려면 반드시 맨 뒤에 /u를 붙여야 합니다. 그렇지 않으면 UTF-8 한글을 구성하는 3바이트 중 첫 번째 바이트만을 기준으로 매칭하게 되어서 +가 필요한 것이고, +를 붙이더라도 중간에 낀 바이트들 때문에 예상치 못한 동작이 일어날 수 있습니다.

  • Lv36 Lv19
    그랬군요. 정규식을 써도 js에서나 가끔 사용하다보니...
    '/^[ㄱ-ㅎ]$/u' 이렇게 바꾸고 더 깔끔해졌습니다 :)