Skip to content

Create a custom Query type

If you need to perform a more complex query than the built-in Query types allow, you can create a custom Query type.

The following example shows how to create a custom Query type that renders the latest content items of selected Types.

First, add the following LatestContentQueryType.php file to src/QueryType:

 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
34
35
36
<?php declare(strict_types=1);

namespace App\QueryType;

use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery;
use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Core\QueryType\QueryType;

class LatestContentQueryType implements QueryType
{
    public static function getName()
    {
        return 'LatestContent';
    }

    public function getQuery(array $parameters = [])
    {
        $criteria[] = new Query\Criterion\Visibility(Query\Criterion\Visibility::VISIBLE);
        if (isset($parameters['contentType'])) {
            $criteria[] = new Query\Criterion\ContentTypeIdentifier($parameters['contentType']);
        }

        return new LocationQuery([
            'filter' => new Query\Criterion\LogicalAnd($criteria),
            'sortClauses' => [
                new Query\SortClause\DatePublished(Query::SORT_DESC),
            ],
            'limit' => isset($parameters['limit']) ? $parameters['limit'] : 10,
        ]);
    }

    public function getSupportedParameters()
    {
        return ['contentType', 'limit'];
    }
}

Tip

When the custom Query type is in the App namespace, like in the example above, it is registered automatically as a service. Otherwise, register it with the ibexa.query_type service tag.

The name defined in getName() is the one you use to identify the Query type in content view configuration.

1
2
3
4
    public static function getName()
    {
        return 'LatestContent';
    }

Caution

Query type name must be unique.

The getQuery() method constructs the query based on Search Criteria and Sort Clauses. See Content search for more information about queries and Search reference for a reference of available Criteria and Sort Clauses.

The getSupportedParameters() method provides the parameters you can set in content view configuration.

1
2
3
4
    public function getSupportedParameters()
    {
        return ['contentType', 'limit'];
    }

Note

To have more control over the details of parameters, use the Options resolver-based Query type.

Then, in the content view configuration, indicate that the content view should use the custom Query type:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
            content_view:
                full:
                    latest:
                        controller: ibexa_query::locationQueryAction
                        template: '@ibexadesign/full/latest.html.twig'
                        match:
                            Identifier\ContentType: "latest"
                        params:
                            query:
                                query_type: LatestContent
                                parameters:
                                    contentType: [article, blog_post]
                                assign_results_to: latest

Options resolver-based Query type

Additionally, your custom Query type can extend the OptionsResolverBasedQueryType abstract class. This gives you more flexibility when defining parameters.

In the configureOptions() method you can define the allowed parameters, their types and default values.

 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
34
35
36
37
38
39
40
41
<?php declare(strict_types=1);

namespace App\QueryType;

use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery;
use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Core\QueryType\OptionsResolverBasedQueryType;
use Ibexa\Core\QueryType\QueryType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class OptionsBasedLatestContentQueryType extends OptionsResolverBasedQueryType implements QueryType
{
    public static function getName()
    {
        return 'OptionsLatestContent';
    }

    protected function doGetQuery(array $parameters)
    {
        $criteria[] = new Query\Criterion\Visibility(Query\Criterion\Visibility::VISIBLE);
        if (isset($parameters['contentType'])) {
            $criteria[] = new Query\Criterion\ContentTypeIdentifier($parameters['contentType']);
        }

        return new LocationQuery([
            'filter' => new Query\Criterion\LogicalAnd($criteria),
            'sortClauses' => [
                new Query\SortClause\DatePublished(Query::SORT_DESC),
            ],
            'limit' => isset($parameters['limit']) ? $parameters['limit'] : 10,
        ]);
    }

    protected function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefined(['contentType', 'limit']);
        $resolver->setAllowedTypes('contentType', 'array');
        $resolver->setAllowedTypes('limit', 'int');
        $resolver->setDefault('limit', 10);
    }
}

Note

In contrast with the previous example, a Query type that extends OptionsResolverBasedQueryType must implement the doGetQuery() method instead of getQuery().