bestit / commercetools-filter-bundle
Commerce tools filter and search implementation
Installs: 6 419
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 4
Forks: 3
Open Issues: 0
Type:lib
Requires
- php: ^7.0
- amstaffix/pagination: ^1.1@dev
- commercetools/php-sdk: ^1.2.1 || ^2.0
- symfony/symfony: ^3.1
Requires (Dev)
- phpunit/phpunit: ^5.5
- squizlabs/php_codesniffer: ^2.6
This package is auto-updated.
Last update: 2024-10-29 04:53:18 UTC
README
Add filter and search implementation for commerce tools. It still uses the commmercetools/php-sdk under the hood.
Installation
Step 1: Download the Bundle
Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:
$ composer require bestit/commercetools-filter-bundle
This command requires you to have Composer installed globally, as explained in the installation chapter of the Composer documentation.
Step 2: Enable the Bundle
Then, enable the bundle by adding it to the list of registered bundles
in the app/AppKernel.php
file of your project:
<?php // app/AppKernel.php // ... class AppKernel extends Kernel { public function registerBundles() { $bundles = array( // ... new BestIt\Commercetools\FilterBundle\BestItCommercetoolsFilterBundle(), ); // ... } // ... }
Step 3: Configure the Bundle
Minimum configuration (only all required fields)
# Minimum configuration for "BestItCommercetoolsFilterBundle"
best_it_commercetools_filter:
# Client service id of commerce tools sdk client
client_id: app.commercetools.client
# Sorting. At least one sorting options must exist
sorting:
# Default sorting to use if no sorting is selected
default: name_asc
# This is an array with all available sortings.
choices:
name_asc:
# Translation key
translation: sorting_name_asc
# Api query for sdk
query: 'name.de asc'
Maximum configuration (all required and optional fields)
# Maximum configuration for "BestItCommercetoolsFilterBundle"
best_it_commercetools_filter:
# Used translation domain (default "messages")
translation_domain: messages
# Product normalizer (service id / implement interface)
product_normalizer_id: best_it_commercetools_filter.normalizer.empty_product_normalizer
# Client service id of commerce tools sdk client
client_id: ~ # Required
# Optional facets factory config provider (service id / implement interface)
config_provider_id: best_it_commercetools_filter.provider.empty_facet_config_provider
# Generator for filter urls
url_generator_id: best_it_commercetools_filter.generator.default_filter_url_generator
# Cache life time. Enum Attribute labels are cached to minimize CommerceTools requests.
# DEPRECATED: Do not use. Switch to enum_normalizer
cache_life_time: 86400
# Optional query for defining a base category. If used, only products under the base category will be selected. (default: null)
base_category_query: 'custom(fields(alias="_SHOP_ROOT"))'
# Sorting. At least one sorting options must exist
sorting: # Required
# The default sort
default: ~ # Required
# Default Sorting for the listing pages
default_listing: ~ # optional, if not set fallback to default sorting
# Default Sorting for the search page
default_search: ~ # optional, if not set fallback to default sorting
# Define the sorting id, the translation key and sort query. This is an array with all available sortings.
choices: # Required
# Prototype
key:
# Api query for sdk (default: null for relevance sorting)
query: ~
# Translation key
translation: ~ # Required
# Pagination settings
pagination:
# Products per page
products_per_page: 20
# Neighbours at pagination 1 => "1 2 3" | 2 => "1 2 3 4 5"
neighbours: 1
# View settings
view:
# Default view type (eg. grid, list)
default: list
# Facet config
facet:
# Translation key for reset button or false for disable reset button
reset: reset
# Translation key for reset button or false for disable submit button
submit: submit
# Suggest config
suggest:
# Use fuzzy suggest (default: true)
enable_fuzzy: false
# The fuzziness level is quantified in terms of the Damerau-Levenshtein distance.
# If null, the platform selects level based on the length of the searched text
# Default: null
fuzzy_level: 2
# Mark matching variants with "isMatchingVariant". (default: false)
match_variants: true
# Search config
search:
# Use fuzzy search (default: true)
enable_fuzzy: false
# The fuzziness level is quantified in terms of the Damerau-Levenshtein distance.
# If null, the platform selects level based on the length of the searched text
# Default: null
fuzzy_level: 2
# Mark matching variants with "isMatchingVariant". (default: false)
match_variants: true
# Enum Normalizer
# CommerceTools only returns enum keys. We have to normalize it.
# This bundle ships one standard way - but you can define your own normalizer as well
enum_normalizer:
# Switch this normalizer on / off (default: true)
enable: false
# You can define your own cache pool (default: see id below)
cache_id: cache.app
# Time in seconds (default: 86400)
cache_life_time: 60
# Category Normalizer
# CommerceTools only returns category id's. We have to normalize it.
# This bundle ships one standard way - but you can define your own normalizer as well
category_normalizer:
# Switch this normalizer on / off (default: true)
enable: false
# You can define your own cache pool (default: see id below)
cache_id: cache.app
# Time in seconds (default: 86400)
cache_life_time: 60
# Optional facet filter mode for listing (default: 'none')
# Possible values:
# - none: No filter will be applied
# - parent: Only direct childrens categories will be shown
# - ancestors: All childrens and subchildrens will be shown
facet_filter_type: 'parent'
Usage
Listing
Just execute the listing method of the filter manager in your listing controller. It need the Symfony Request object and the current listing category (Commercetools Object) for creating the listing request.
Example:
// ListingController.php public function indexAction(Request $request, Category $category): array { $result = $this->get('best_it_commercetools_filter.manager.filter_manager')->listing($request, $category); return [ 'products' => $result->getProducts(), 'totalProducts' => $result->getTotalProducts(), 'context' => $result->getContext(), 'pagination' => $result->getPagination(), 'sorting' => $result->getSorting(), 'facetForm' => $result->getForm() ]; }
Search
Just execute the search method of the filter manager in your listing controller. It need the Symfony Request object and the search string for creating the search request.
Example:
// SearchController.php public function indexAction(Request $request, Category $category): array { $result = $this->get('best_it_commercetools_filter.manager.filter_manager')->search($request, $request->query->get('search')); return [ 'products' => $result->getProducts(), 'totalProducts' => $result->getTotalProducts(), 'context' => $result->getContext(), 'pagination' => $result->getPagination(), 'sorting' => $result->getSorting(), 'facetForm' => $result->getForm() ]; }
Product Normalizer
In most cases, products need to be normalized for the frontend. You can choose one of the base normalizer from filter bundle or use your own if you implement the ProductNormalizerInterface and add the service id to the app config. The filter bundle contains two base normalizer:
- ArrayProductNormalizer: Converts the ProductProjection object to array.
- EmptyProductNormalizer: Just return the ProductProjection without normalization
EmptyProductNormalizer will be use if you don't fill the product_normalizer_id Parameter (@ config.yml).
Term Normalizer
There are cases where you have to normalize facet terms. Commercetools only ships enum keys and categories id for example, which aren't enough for your frontend. This bundle contains two default normalizers:
- CategoryNormalizer: Converts category id's to their real name
- EnumAttributeNormalizer: Converts enum keys to their label
But you can define your own TermNormalizer as well. Just implement the TermNormalizerInterface and add the tag best_it_commercetools_filter.term_normalizer
to your service. Remember to disable the default normalizer in your config.
If you want to skip a term, just throw a SkipTermException
. No further normalizer will be applied and the term will not be shown at frontend.
Config Provider id
You can add you own filter config provider. Just implement the FacetConfigProviderInterface and add your service id to config_provider_id (@ config.yml). The filter bundle default provider will be use if you don't fill the config_provider_id Parameter (@ config.yml), which returns no filters.
Url generator
The filter bundle need to create urls, but the route names can vary between projects. So you can add your own url generator for creating the correct urls with the url_generator_id parameter. The generator need to implement the FilterUrlGeneratorInterface. The bundle will use his own default generator if you do not fill the field.
Events
Request events
You can modify the commercetools client request with the filter and suggest post events. Check all events @ SuggestEvent and FilterEvent class.
Example usage: Extend request
// FilterRequestSubscriber.php
class FilterRequestSubscriber implements EventSubscriberInterface
{
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
SuggestEvent::PRODUCTS_REQUEST_POST => 'onProductsFilterRequest',
FilterEvent::PRODUCTS_REQUEST_POST => 'onProductsSuggestRequest'
];
}
/**
* On products request for filter
* @param ProductProjectionSearchRequestEvent $event
*/
public function onProductsFilterRequest(ProductProjectionSearchRequestEvent $event)
{
$request = $event->getRequest();
$request
->expand('masterVariant.attributes[*].value')
->expand('productType');
$event->setRequest($request);
}
/**
* On products request for suggest
* @param ProductProjectionSearchRequestEvent $event
*/
public function onProductsSuggestRequest(ProductProjectionSearchRequestEvent $event)
{
$request = $event->getRequest();
$request
->expand('categories[*]')
->expand('masterVariant.attributes[*].value[*].value')
->expand('productType');
$event->setRequest($request);
}
}