Quick tip: Composite Criterion

Quick tip: Composite Criterion

Composite Criterion has been introduced in eZ Platform 3.0. It’s a base class for custom criterions which are built from existing ones. Because of that we can skip implementing search engine specific criterion visitor (criterion visitor is a class responsible for translating criterion into language understandable by specific search engine) and it makes it the easiest way to implement your own criterion. 

How to use it in your own project? In short words:

  1. Create class extending   eZ\Publish\API\Repository\Values\Content\Query\Criterion\CompositeCriterion. Give it a meaningful name e.g. IsRelatedBlogPost
  2. Override class constructor. Create your criteria and pass it into the parent constructor call

Example is worth more than thousand words so let’s take a look on the following code snippet: 

    <?php 

namespace App\Query\Search\Query\Criterion;use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\CompositeCriterion;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\ContentTypeIdentifier;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\FieldRelation;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalAnd;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator;

final class IsRelatedBlogPost extends CompositeCriterion
{
   public function __construct(Content $content)
   {
       $criteria = new LogicalAnd([
           new ContentTypeIdentifier('blog_post'),
           new FieldRelation('relations', Operator::CONTAINS, [$content->id]),
       ]);
       parent::__construct($criteria);
   }
}
 

Now whenever you need to select blog posts related to some content you can use IsRelatedBlogPost criterion:

    $query = new Query();
$query->filter = new IsRelatedBlogPost($product);

If you need to narrow down the results to specific subsets e.g. related blog posts published in the last 2 weeks combine IsRelatedBlogPost criterion with DateMetadata criterion using logical “and” operator. You don’t have to repeat yourself.

Also Composite Criterion could help you improve a code readability. Could you tell at first sight what the following code snippet does?

    $query = new Query();
$query->filter = new LogicalAnd([
   new ParentLocationId($location->parentLocationId),
   new LogicalNot(
       new LocationId($location->id)
   ),
]);
$result = $searchService->findLocations($query);

Even if you know the answer, let’s refactor this code by moving filter creation logic to custom criterion based on Composite Criterion. 

    $query = new Query();
$query->filter = Sibling::fromLocation($location);
$result = $searchService->findLocations($query);

Right now it’s a way more readable and self explanatory.

eZ Platform is now Ibexa DXP

Ibexa DXP was announced in October 2020. It replaces the eZ Platform brand name, but behind the scenes it is an evolution of the technology. Read the Ibexa DXP v3.2 announcement blog post to learn all about our new product family: Ibexa Content, Ibexa Experience and Ibexa Commerce

Introducing Ibexa DXP 3.2

Insights and News