개인적인 목적으로 번역한 글이기 때문에 오역과 의역이 많습니다.

 

원문 - http://teknoid.wordpress.com/2008/05/07/jquery-autocomplete-in-cakephp/


이것은 CakePHP와 jQuery를 이용한 "필드 자동완성"을 설정하는 방법에 대한 빠른 예제이다.

Product 라는 모델과 products 콘트롤러가 있다고 가정해 보자. 여기서 목표는 사용자가 단어 몇개를 치면 autocomplete 기능을 이용해서 DB에서 매칭되는 제품 리스트를 보여주는 것이다. 먼저 해줘야 할 것은 jQuery 라이브러리를 인클루딩하는 것이다. 만약 $script_for_layout 을 사용한다면 뷰 파일은 아마도 아래와 같을 것이다.


  1. $javascript->link(’jquery/jquery.min’, false);


다음으로 autocomplete 플러그인을 인클루드해야 한다. 그런 플러인들은 몇 종류가 있다.


이 플러그인이 조금 쓸만하다: http://www.pengoworks.com/workshop/jquery/autocomplete.htm

(jQuery 자동완성이 어떻게 작동하는지에 대한 자세한 내용은 문서를 참고하라. 또한 적절한 CSS 파일과 로딩 이미지도 얻을 수 있다.)


JS 디렉토리 어딘가에 저장을 하고 난 후에(아마도 js/jquery/plugins 폴더가 될것이다.) 뷰에서 아래와 같이 반드시 인클루딩을 해줘야 한다.

 

  1. $javascript->link(’jquery/plugins/autocomplete’, false);

 

이제 자동완성 필드로 사용될 폼 필드가 필요하다. 기본적으로 플러그인에서 id="autoComplete"인 필드명을 기대할 것이다. 그래서 폼의 일부분에 이런 부분을 명시해 줘야 한다.

 

  1. <?php echo $form->text('Product.name', array('size'=>'30', 'id'=>'autoComplete')); ?>

(여기서 Product 라는 모델명을 사용하기로 한것을 기억하자.)

아직까진 나쁘지 않다. 자 그럼 이제부터 자바스크립트 코드를 작성해서 폼 엘리먼트에 실제 자동완성 기능을 붙이도록 해보자. 새로운 JS 파일을 만들고 파일명을 autocompleteAction.js 라고 하자.(뷰에서 인클루딩하는 것. 잊지 말자.) 코드는 아래와 같은 형태가 될 것이다.

 

  1. $(document).ready(function(){
        $("#autoComplete").autocomplete("/products/autoComplete", {
               minChars: 2,
               lineSeparator: "^",
               cacheLength: 10,
               onItemSelect: selectItem,
               onFindValue: findValue,
               formatItem: formatItem,
               autoFill: false
            });

    });

    function selectItem(li) {
        findValue(li);
    }

    function findValue(li) {
        if( li == null ) return alert("No match!"); // if coming from an AJAX call, let's use the product id as the value
        if( !!li.extra ) var sValue = li.extra[0]; // otherwise, let's just display the value in the text box
        else var sValue = li.selectValue;
        alert("The value you selected was: " + sValue);
    }

    function formatItem(row) {
        if(row[1] == undefined) {
            return row[0];
        } else {
            return row[0] + " (id: " + row[1] + ")";
        }
    }

 

기본에서 다뤘던것처럼 위 액션은 폼 필드에 두글자 이상을 입력하게 되면 자동완성 기능을 통해서 알려주게 될 것이다.(최소 두글자 이상은 입력해야 한다.) lineSeparator:"^" 는 자동완성 플러그인에 글자를 세는 라인이 어디든지 간에 ^ 문자를 만나면 다음 줄로 건너 뛰라는 의미이다. 이 부분에 대해서는 조금 뒤에 설명하도록 하겠다. 이 기능은 새줄 입력하는 문자가 "\n"일 경우엔 의미가 없다. 하지만 CakePHP에서 이 개행문자열을 인식시킬 수 없었다. 그래서 제품명에 나타나지 않는 이런 애매한 문자 대신에 ^ 를 사용하기로 했다. 이것은 아주 좋은 해결책은 아니지만 나중에 다시 살펴보기로 했다.

 

그래서 무슨일이 벌어졌는가? 자, 이제 자동완성은 어딘가에 있는 아이템(예제에서는 제품) 리스트를 가져올 필요가 있다. 그리고 이 코드는 바로 부분을 보여준다:

 

autocomplete(”/products/autoComplete”…

 

아마도 CakePHP의 규약에 따라 폴더명을 보고 products 콘트롤러와 autoComplete 액션이 필요할 것이라는 것을 알 수 있을 것이다. 이제 그 파일을 만들 때가 되었다. 코드는 아래와 같다.


  1. function autoComplete() {
    Configure::write('debug', 0);
    $this->layout = 'ajax';
    $products = $this->Product->find('all', array(
    'conditions'=>array( 'Product.name'=> 'LIKE '.$this->params['url']['q'].'%'),
    'fields'=>array( 'name', 'id')
    ));
    }

    $this->set('products', $products);

    }

자이 기본적으로 폼 필드에 입력한 최초의 두 글자와 매칭되는 제품명을 찾아볼 수 있게 되었다. DB에서 제품 아이디와 제품명을 리턴받아왔다. $this->params['url']['q'] 라고 되어 부분을 주목하자. 자동완성 플러그인은 GET 메서드를 사용해서 폼 데이터를 콘트롤러에 넘겨주게 된다. 여기서 q=<문자열> 에는 쿼리문이 오게 된다. 이 부분이 CakePHP가 쿼리문을 읽어오는 방법이다. 이제 어떤 제품을 찾고 뷰를 위한 결과를 배열로 저장해 보자. 뷰는 텍스트 필드에 타이핑을 시작할때 필드 아래쪽에 리스트 형태로 나오게 된다. 파일을 하나 만들어 보자(auto_complete.ctp)

  1. if(!empty($products)) {
    foreach($products as $product) {
    echo $product['Product']['name'].'|'.$product['Product']['id'].'^';
    }
    } else {
    echo 'No results';
    }

위 코드는 제품 배열을 풀어서 제품명과 제품 아이디 형태로 분류해서 보여주는 코드이다. 물론 배열이 비어 있다면 아무런 결과 값이 없기 때문에 "No results"라는 메시지를 뿌리게 된다. 위에 설명했던 ^ 문자를 기억하는가? 여기 코드에 보면 각 제품명과 제품 아이디를 출력하고 다음 제품으로 넘어갈 때 ^문자를 기준으로 구분을 한다.

 

자. 여기까지가 전부다. 복사해서 붙여넣기 기능을 이용하면 빠르게 결과를 볼 수 있고 수정도 가능하다. 아마 20분 이내에 가능할 것이다.물론 자바스크립트의 경고창보다는 더 나은 방식으로 나오길 원할것이다.

글은 스프링노트에서 작성되었습니다.