addFilter와 addFieldToFilter


19

Magento 컬렉션에는 두 가지 필터링 방법이 있습니다.

1. Varien_Data_Collection_Db::addFieldToFilter
2. Varien_Data_Collection::addFilter

두 방법 모두 조건을에 추가하는 것 같습니다 Zend_Db_Select. 그리고 어떤 장점이 addFilter있습니까? 대신에 언제 사용해야 addFieldToFilter합니까?

답변:


49

좋아요, 검사 해 봅시다. 첫 번째 차이점은 addFilter()보다 일반적이며 데이터베이스에 따라 다릅니다. Varien_Directory_Collection파일 이름으로 필터링하는 데 사용됩니다 . 그러나이 답변에 초점을 맞추겠습니다 Varien_Data_Collection_Db.

그것들은 다른 서명을 가지고 있는데, addFilter유연성이 떨어지는 것처럼 보이지만 장점도 있습니다.

1. addFieldToFilter ()

/**
 * Add field filter to collection
 *
 * @see self::_getConditionSql for $condition
 *
 * @param   string|array $field
 * @param   null|string|array $condition
 *
 * @return  Mage_Eav_Model_Entity_Collection_Abstract
 */
public function addFieldToFilter($field, $condition = null)

매개 변수

addFieldToFilter ()는 조건 배열이있는 필드 배열 또는 단일 조건이있는 단일 필드를 사용할 수 있습니다.

  • addFieldToFilter('field', 'value')

    결과 : field=value

  • addFieldToFilter(['field1', 'field2'], ['value1', 'value2']);

    결과 : field1=value1 OR field2=value2

조건 은 다음과 같습니다.

  • 단일 스칼라 값 (추천 'value1''value2'위)
  • 형태의 배열 [ operator => value ]
  • Zend_Db_Expr객체
  • "OR"과 결합 된 조건의 배열 (예, 재귀 적)

특히 "operator => value"구문은 다음 코드에 설명되어 Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition()있습니다.

 * If $condition integer or string - exact value will be filtered ('eq' condition)
 *
 * If $condition is array - one of the following structures is expected:
 * - array("from" => $fromValue, "to" => $toValue)
 * - array("eq" => $equalValue)
 * - array("neq" => $notEqualValue)
 * - array("like" => $likeValue)
 * - array("in" => array($inValues))
 * - array("nin" => array($notInValues))
 * - array("notnull" => $valueIsNotNull)
 * - array("null" => $valueIsNull)
 * - array("moreq" => $moreOrEqualValue)
 * - array("gt" => $greaterValue)
 * - array("lt" => $lessValue)
 * - array("gteq" => $greaterOrEqualValue)
 * - array("lteq" => $lessOrEqualValue)
 * - array("finset" => $valueInSet)
 * - array("regexp" => $regularExpression)
 * - array("seq" => $stringValue)
 * - array("sneq" => $stringValue)
 *
 * If non matched - sequential array is expected and OR conditions
 * will be built using above mentioned structure

from/ to연산자 에는 문서화되지 않은 추가 기능이 있습니다 .

  • 와 및 값을 날짜로 구문 분석됩니다. 그들은 어떤 형식 으로든 받아 들일 수 있습니다.['from' => $dateFrom, 'to' => $dateTo, 'date' => true]$dateFrom$dateToVarien_Date::formatDate()
  • 날짜 구문 분석 기능이 필요하지만 <=또는 중 하나만 비교하려는 >=경우 'from'또는 중 하나를 생략 할 수 있습니다 'to'.
  • 'datetime' => true일뿐 만 아니라 시간도 포함해야하지만 Varien_Db_Adapter_Pdo_Mysql :: _ prepareSqlDateCondition () ( $includeTimestamp매개 변수 누락 ) datetime과 동일한 방식으로 작동 하는 버그 가 있습니다.date . 둘 다 시간을 포함합니다. 당신은 단지 날짜를 기준으로 비교해야한다면, 추가 00:00:00받는 from날짜와 23:59:59받는 to날짜입니다.

필드 매핑

이 방법은 필드 매핑을 사용합니다. 별명 필드 이름을 작성하기 위해 구체적 콜렉션 클래스에서 필드 맵핑을 정의 할 수 있습니다. 제품 콜렉션의 예는 다음과 같습니다.

protected $_map = array('fields' => array(
    'price'         => 'price_index.price',
    'final_price'   => 'price_index.final_price',
    'min_price'     => 'price_index.min_price',
    'max_price'     => 'price_index.max_price',
    'tier_price'    => 'price_index.tier_price',
    'special_price' => 'price_index.special_price',
));

2. addFilter ()

/**
 * Add collection filter
 *s
 * @param string $field
 * @param string $value
 * @param string $type and|or|string
 */
public function addFilter($field, $value, $type = 'and')

매개 변수

addFilter()단일 값과 유형 으로 단일 필드 만 필터링 할 수 있습니다 . $type다음 중 하나 일 수 있습니다.

  • "and"(기본값) AND $field=$value-WHERE 절에 추가 합니다 (물론 올바른 인용 부호가 있음)
  • "or" "OR $field=$value-WHERE 절에 추가 (ditto)
  • "string" AND $value-WHERE 절에 추가 합니다 (예 : $ value는 임의의 SQL 표현식 일 수 있음)
  • "public"-필드 매핑을 사용하며 다음 _getConditionSql()과 유사합니다 addFieldToFilter(). 이것은 거의 강력하기 때문에 OR과 결합 된 다른 필드에 대해 여러 필터를 추가하는 기능 만 누락되었습니다.

Varien_Data_Collection_Db::_renderFilters() 당신이 그들이 처리하는 방법을 볼 수 있습니다.

확장 성

한 가지 중요한 차이점이 addFilter()있습니다. 적용 할 필터를 수집 하고 컬렉션을로드하기 직전에 쿼리 개체 $this->_filters()에만 추가합니다 Zend_Db_Select.addFieldToFilter()반면에 쿼리 개체를 즉시 조작합니다.

이를 통해 이미 추가 된 필터를 조작하거나 제거 할 수 있습니다. Varien 컬렉션에는 인터페이스가 없으므로 사용자 지정 컬렉션에서이를 구현해야합니다. _renderFiltersBefore()재정의 할 수 있는 후크 방법 이 있습니다.


나는 우리가 사용할 수있는 하나 개의 질문이 addFilter과를 attributes?
Murtuza Zabuawala

@MurtuzaZabuawala 아니오, EAV 속성에 사용할 수 없습니다
Fabian Schmengler

이 답변에 감사드립니다 Fabian, 나는 이것에 대해 귀하의 웹 사이트 게시물을 즐겼지만 addFilter에서 $ field는 어떤 가치를 가질 수 있습니까? 모듈이 실행되는 범주에있는 제품 만 필터링하기 위해 addFilter 함수를 사용하려고합니다.
John

카테고리는 속성이 아니지만 별도의 테이블에있는 제품과 연관되므로 AFAIK를 사용할 수 없습니다. 내 머리 위에 해결책을 줄 수 없어, 죄송합니다
Fabian Schmengler

응답 해 주셔서 감사합니다. 걱정할 필요가 없습니다. 해결 방법을 찾으면 여기에서 해결책을 업데이트하겠습니다.
John

2

Magento 컬렉션에는 다음과 같은 두 가지 필터링 방법이 있습니다.

  1. Varien_Data_Collection_Db :: addFieldToFilter

addFieldToFilter ($ field, $ condition = null)

의 첫 번째 매개 변수는 addFieldToFilter필터링하려는 속성입니다. 두 번째는 당신이 찾고있는 가치입니다. 다음 sku은 value에 대한 필터를 추가하는 것 n2610입니다.

두 번째 매개 변수를 사용하여 수행 할 필터링 유형을 지정할 수도 있습니다. 이곳은 사물이 조금 복잡해지고 조금 더 깊이 들어갈 가치가 있습니다.

기본적으로 다음과 같은

$collection_of_products->addFieldToFilter('sku','n2610'); 

(본질적으로)

WHERE sku = "n2610"

자신을 살펴보십시오. 다음을 실행

public function testAction()
{
    var_dump(
    (string) 
    Mage::getModel('catalog/product')
    ->getCollection()
    ->addFieldToFilter('sku','n2610')
    ->getSelect());
}

생산할 것이다

SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'

EAV 속성을 사용하는 경우이 작업이 빠르게 복잡해질 수 있습니다. 속성 추가

var_dump(
(string) 
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('meta_title','my title')
->getSelect()
);

쿼리가 심하게 나옵니다.

SELECT `e`.*, IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) AS `meta_title` 
FROM `catalog_product_entity` AS `e` 
INNER JOIN `catalog_product_entity_varchar` AS `_table_meta_title_default` 
    ON (_table_meta_title_default.entity_id = e.entity_id) AND (_table_meta_title_default.attribute_id='103') 
    AND _table_meta_title_default.store_id=0        
LEFT JOIN `catalog_product_entity_varchar` AS `_table_meta_title` 
    ON (_table_meta_title.entity_id = e.entity_id) AND (_table_meta_title.attribute_id='103') 
    AND (_table_meta_title.store_id='1') 
WHERE (IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) = 'my title')

요점을 설명하지 말고 마감일 인 경우 SQL에 대해 너무 많이 생각하지 마십시오.

다른 비교 연산자 "쿼리로 다른 항목을 원한다면 어떻게해야합니까?" 같지 않음, 크거나 작음 등. addFieldToFilter 메서드의 두 번째 매개 변수도 다루었습니다. 문자열을 전달하는 대신 단일 요소 Array를 전달하는 대체 구문을 지원합니다.

이 배열의 핵심은 비교하려는 유형입니다. 해당 키와 연관된 값은 필터링하려는 값입니다. 위의 필터를 다시 실행하되이 명시 적 구문을 사용하십시오

public function testAction()
{
    var_dump(
    (string) 
    Mage::getModel('catalog/product')
    ->getCollection()
    ->addFieldToFilter('sku',array('eq'=>'n2610'))
    ->getSelect()
    );          
}

필터 불러 오기

addFieldToFilter('sku',array('eq'=>'n2610'))

보시다시피, 두 번째 매개 변수는 PHP 배열입니다. 키는 eq이며 이는 같습니다. 이 키의 값은 필터링 할 값인 n2610입니다.

마 젠토에는 필터와 같은 많은 영어 언어가있어 청중의 모든 오래된 펄 개발자에게 기억의 눈물을 흘릴 수 있습니다.

아래는 모든 필터와 해당 SQL의 예입니다.

array("eq"=>'n2610')
WHERE (e.sku = 'n2610')

array("neq"=>'n2610')
WHERE (e.sku != 'n2610')

array("like"=>'n2610')
WHERE (e.sku like 'n2610')

array("nlike"=>'n2610')
WHERE (e.sku not like 'n2610')

array("is"=>'n2610')
WHERE (e.sku is 'n2610')

array("in"=>array('n2610'))
WHERE (e.sku in ('n2610'))

array("nin"=>array('n2610'))
WHERE (e.sku not in ('n2610'))

array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)

array("null"=>'n2610')
WHERE (e.sku is NULL)

array("gt"=>'n2610')
WHERE (e.sku > 'n2610')

array("lt"=>'n2610')
WHERE (e.sku < 'n2610')

array("gteq"=>'n2610')
WHERE (e.sku >= 'n2610')

array("moreq"=>'n2610') //a weird, second way to do greater than equal
WHERE (e.sku >= 'n2610')

array("lteq"=>'n2610')
WHERE (e.sku <= 'n2610')

array("finset"=>array('n2610'))
WHERE (find_in_set('n2610',e.sku))

array('from'=>'10','to'=>'20')
WHERE e.sku >= '10' and e.sku <= '20'

이것들 대부분은 설명이 필요하지만 일부는 특별한 설명이 필요합니다.

in, nin, find_in_set in 및 nin 조건을 사용하면 값 배열을 전달할 수 있습니다. 즉, 필터 배열의 값 부분 자체가 배열이 될 수 있습니다.

array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))

notnull, null 키워드 NULL은 대부분의 SQL 버전에서 특별합니다. 일반적으로 표준 평등 (=) 연산자로는 잘 작동하지 않습니다. 필터 유형으로 notnull 또는 null을 지정하면 전달한 값을 무시하고 NULL 비교에 대한 올바른 구문을 얻을 수 있습니다.

array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)

from-to filter 표준 규칙을 위반하는 또 다른 특수 형식입니다. 단일 요소 배열 대신 두 요소 배열을 지정합니다. 한 요소에는 키가 있고 다른 요소에는 키가 있습니다. 표시된 키와 같이이 필터를 사용하면 기호보다 크거나 작게 걱정할 필요없이 시작 / 종료 범위를 구성 할 수 있습니다

public function testAction
{
        var_dump(
        (string) 
        Mage::getModel('catalog/product')
        ->getCollection()
        ->addFieldToFilter('price',array('from'=>'10','to'=>'20'))
        ->getSelect()
        );                      
}

위의 수율

WHERE (_table_price.value >= '10' and _table_price.value <= '20')'

AND 또는 OR, 아니면 OR 및 AND입니까? 마지막으로, 부울 연산자에옵니다. 하나의 속성으로 만 필터링하는 드문 순간입니다. 다행히 마젠 토의 컬렉션은 우리를 다루었습니다. addFieldToFilter에 대한 여러 호출을 연결하여 여러 "AND"쿼리를 얻을 수 있습니다.

function testAction()
{
        echo(
        (string) 
        Mage::getModel('catalog/product')
        ->getCollection()
        ->addFieldToFilter('sku',array('like'=>'a%'))
        ->addFieldToFilter('sku',array('like'=>'b%'))
        ->getSelect()
        );                                  
}

위와 같이 여러 호출을 연결하여 다음과 같은 where 절을 생성합니다.

WHERE (e.sku like 'a%') AND (e.sku like 'b%')

손을 든 사람에게는 위의 예가 항상 0 레코드를 반환합니다. sku는 a와 b 모두로 시작할 수 없습니다. 여기서 원하는 것은 OR 쿼리입니다. 이것은 addFieldToFilter의 두 번째 매개 변수의 또 다른 혼란스러운 측면을 보여줍니다.

OR 쿼리를 작성하려면 두 번째 매개 변수로 필터 배열 배열을 전달해야합니다. 개별 필터 배열을 변수에 할당하는 것이 가장 좋습니다.

public function testAction()
{
        $filter_a = array('like'=>'a%');
        $filter_b = array('like'=>'b%');
}

그런 다음 모든 필터 변수의 배열을 할당하십시오.

public function testAction()
{
        $filter_a = array('like'=>'a%');
        $filter_b = array('like'=>'b%');
        echo(
        (string) 
        Mage::getModel('catalog/product')
        ->getCollection()
        ->addFieldToFilter('sku',array($filter_a,$filter_b))
        ->getSelect()
        );
}

명시 적으로하기 위해 위에서 언급 한 필터 배열 배열이 있습니다.

array($filter_a,$filter_b)

이것은 다음과 같은 WHERE 절을 제공합니다.

WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
  1. Varien_Data_Collection :: addFilter
 addFilter($field, $value, $type = 'and')

addFilter()단일 값과 유형으로 단일 필드 만 필터링 할 수 있습니다. $type다음 중 하나 일 수 있습니다.

  1. "and"(기본값)-WHERE 절에 AND $ field = $ value를 추가합니다.
  2. "or"- "OR $ field = $ value를 WHERE 절에 추가합니다

자세한 내용보기


1
이것은 아무것도 설명하지 않습니다.
Fabian Schmengler

이것은 말이되지 않습니다. 그것은 이러한 방법의 차이를 설명하지 않습니다
Lindar


2
업데이트 된 답변은 주로 alanstorm.com/magento_collections 에서 복사됩니다 . 적어도 출처를 인용하십시오!
Fabian Schmengler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.