Posts

커스텀 콜렉션에 페이지네이션(pagination) 적용하기

마젠토의 콜렉션(Collection)은 객체의 데이터가 엔트리 형식으로 저장되어있을때 여러 데이터를 한번에 불러오는데 유용하게 사용됩니다.
제품이나 카테고리, 주문정보 및 손님 데이터 처럼 객체의 많은 수의 엔트리가 데이터 베이스에 저장되어 있을경우, 콜렉션을 이용하면 한번에 모든 엔트리 또는 필터를 사용해서 필요한 엔트리만 불러오는데 상당히 유용하게 사용됩니다.
기본적인 콜렉션 사용법은 마젠토 콜렉션(Collection) 사용하기를 참조해 주세요.

마젠토에 이미 존재하는 객체(product, category, order, customer 등등)이외에 다른 종류의 엔트리 형식의 커스텀 데이터가 존재하고 이 데이터들을 불러오려면 콜렉션을 사용해야 합니다.
프로그래밍 상으로는

1
$collection = Mage::getModel('{네임스페이스}/{모듈}')->getCollection();

이런 형식으로 불러오면 되는데 데이터의 양이 많을경우 이렇게 불러온 데이터를 웹페이지에 모두 표시하기에는 무리가 있습니다.
물론

1
2
$collection = Mage::getModel('{네임스페이스}/{모듈}')->getCollection();
$collection->getSelect()->limit(5);

위와같은 방법으로 $collection->getSelect()->limit(5);을 사용해서 원하는 수 만큼만 불러올수 있지만 제품리스트 페이지처럼 페이지당 10, 15, 20개의 엔트리만 나오게 하려고 인위적으로 코드를 짜기 시작하면 조금 복잡해 집니다.

하지만 마젠토의 기본으로 존재하는 제품리스트 페이지에서도 볼수 있듯이 이미 페이지네이션 기능은 이미 만들어져 있으므로 그 기능만 살짝 가져와서 커스텀 모듈에 적용하면 됩니다.
아래의 코딩을 적용하려면 일단 커스텀 모듈이 이미 만들어져 있어야 하구요, 거기에 데이터도 모두 데이터베이스에 존재해서 $collection = Mage::getModel(‘{네임스페이스}/{모듈}’);의 실행이 가능한 상황을 전제로 합니다.

첫번째로 모듈의 블록객체를 생성하거나(이미 없을경우) 수정해야 합니다.

1. 블록 객체 설정
app/code/local/{네임스페이스}/{모듈}/Block/{블록객체}.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class {네임스페이스}_{모듈}_Block_{블록객체} extends Mage_Core_Block_Template
{
    public function __construct()
    {
        parent::__construct();

        // 콜렉션 로딩후 저장하기
        $collection = Mage::getModel('{네임스페이스}/{모듈}')->getCollection();
        $this->setCollection($collection);
    }

    protected function _prepareLayout()
    {
        parent::_prepareLayout();

        // 페이저 블록을 생성하고 거기에 __construct에서 저장했던 콜렉션을 설정
        $pager = $this->getLayout()
            ->createBlock('page/html_pager', '{프로젝트관련이름 - 어떤것이던 상관없음}')
            ->setCollection($this->getCollection());
        // 위에서 생성한 페이지 블록을 현재 블록에 차일드로 설정
        $this->setChild('pager', $pager);
        // 현재 블록에 콜렉션 적용
        $this->getCollection()->load();

        return $this;
    }

    // 차일드로 설정해 놓은 페이저 블록 불러오기
    public function getPagerHtml()
    {
        return $this->getChildHtml('pager');
    }
}

블록객체를 위와 같이 설정을 했으면 frontend의 디자인 템플릿을 생성 또는 수정해 주면 됩니다.

2. 디자인 템플릿 파일 생성/수정
app/design/frontend/{패키지}/{테마}/template/{모듈}/{템플릿}.phtml

1
2
3
4
5
6
7
8
// 콜렉션의 상단에 페이지네이션 표시하기
echo $this->getPagerHtml();
foreach($this->getCollection AS $entry) {
    // 데이터 출력
    // echo $entry->getName();
}
// 콜렉션의 하단에 페이지네이션 표시하기
echo $this->getPagerHtml();

위와같이 설정해 놓는다면 커스텀 모듈에도 제품리스트 같은 페이지네이션을 간단하게 적용시킬수 있습니다.
이것은 콜렉션에 대한 페이지네이션이 이미 만들어져 있기 때문이고, 이렇게 이미 만들어져 있는 페이지네이션에 커스텀 콜렉션만 적용시키면 언제 어디서든 복잡한 코드 없이 반복적으로 페이지 네이션을 사용할수 있습니다.

마젠토 콜렉션(Collection) 사용하기

마젠토 콜렉션(Collection)은 한번에 여러개의 객체(product, customer, category 등등)를 불러오는데 사용됩니다.
예를들어 카테고리 페이지에있는 모든 제품을 불러온다던지, 모든 커스토머(customer) 정보를 불러올때 유용하게 쓰입니다.

아래와 같은 php코드를 루트에 올려놓고 시험해 보세요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require_once "app/Mage.php";
Mage::app();

// 모든 제품 불러오기
$collection = Mage::getResourceModel('catalog/product_collection'); // 첫번째 방법
$collection = Mage::getModel('catalog/product')->getCollection(); // 두번째 방법

// 모든 제품이 필요하지는 않으므로 5개만 로드합니다.
$collection->getSelect()->limit(5);
$collection->load(); // 콜렉션을 불러옵니다.
foreach($collection AS $product) {
    // 제품의 모든 데이터 출력
    print_r($product->getData());
}

위의 코드를 실행해 보시면 제품의 모든 데이터가 출력이 됩니다.
콜렉션 객체를 불러올때 두가지 방법을 보여드렸는데 첫번째 방법과 두번째 방법의 결과가 약간은 틀린걸 확인할수 있습니다.

첫번째 방법은 최소한의 데이터만 로드함으로써 메모리의 사용을 최대한 줄이는 방법이고,
$collection = Mage::getResourceModel(‘catalog/product_collection’);

두번째 방법은 제품의 모든 데이터를 불러옴으로써 메모리 사용에 상관없이 콜렉션을 사용하는 방법입니다.
$collection = Mage::getModel(‘catalog/product’)->getCollection();

개인적으로 메모리 사용이 적은 첫번째 방법을 선호합니다.
그렇다고 필요한 제품의 데이터를 불러오지 못하는것은 아닙니다.
아래와 같이 addAttributeToSelect()을 사용해서 필요한 Attribute을 불러올수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require_once "app/Mage.php";
Mage::app();

$collection = Mage::getResourceModel('catalog/product_collection');

// 아래처럼 원하는 attribute을 콜렉션에 포함시킬수 있습니다.
$collection->addAttributeToSelect('price');
$collection->addAttributeToSelect('weight');

// 모든 제품이 필요하지는 않으므로 5개만 로드합니다.
$collection->getSelect()->limit(5);
$collection->load(); // 콜렉션을 불러옵니다.
foreach($collection AS $product) {
    // 제품의 모든 데이터 출력
    print_r($product->getData());
}

Attribute으로 불러올 데이터를 addAttributeToFilter()를 사용해서 걸러낼수도 있습니다.
예를들어 id가 10보다 커야 한다던지 sku가 ‘abcd’를 포함해야 하는경우 아래와 같이 콜렉션을 설정할수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require_once "app/Mage.php";
Mage::app();

$collection = Mage::getResourceModel('catalog/product_collection');

// 아래처럼 원하는 attribute을 콜렉션에 포함시킬수 있습니다.
// product entity_id가 10보다 커야하는경우
$collection->addAttributeToFilter('entity_id', array('gt' => 10));

// price가 $100 이하여야 하는 경우
$collection->addAttributeToFilter('price', array('lt' => 100));

// sku가 'abcd'를 포함해야 하는 경우
$collection->addAttributeToFilter('sku', array('like' => '%abcd%'));

// sku가 'zzz1'이 아니어야 하는 경우
$collection->addAttributeToFilter('sku', array('neq' => 'zzz1'));

// description이 아무것도 없는 제품을 포함하는 경우
$collection->addAttributeToFilter('description', 'null');

$collection->load(); // 콜렉션을 불러옵니다.
foreach($collection AS $product) {
    // 제품의 모든 데이터 출력
    print_r($product->getData());
}

이런식으로 addAttributeToSelect()나 addAttributeToFilter()를 사용해서 원하는 attribute을 콜렉션에 포함시키거나 필터를 적용해서 걸러낼수 있습니다.
콜렉션의 사용은 한번에 많은 객체를 불러와야 할때, 또 한번에 여러 객체의 정보를 수정해야할때 유용하게 쓰입니다.