hero background ibexa-dark
hero background ibexa-dark

Quick tip: Composite Criterion

Quick tip: Composite Criterion
Quick tip: Composite 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.