Controllers¶
Custom rendering logic¶
In some cases, displaying a Content item/Location via the built-in ViewController
is not sufficient to show everything you want. In such cases you may want to use your own custom logic to display the current Content item/Location instead.
Typical use cases include access to:
- Settings (coming from
ConfigResolver
orServiceContainer
) - Current Content item's
ContentType
object - Current Location's parent
- Current Location's children count
- Main Location and alternative Locations for the current Content item
- etc.
There are three ways in which you can apply a custom logic:
- Configure a custom view controller alongside regular matcher rules (recommended).
- Add a Symfony Response listener to add custom logic to all responses.
- Override the built-in
ViewController
with the custom controller in a specific situation.
Permissions for custom controllers
See permission documentation for information about access control for custom controllers.
Enriching ViewController with a custom controller¶
This is the recommended way of using a custom controller
To use your custom controller on top of the built-in ViewController
you need to point to both the controller and the template in the configuration, for example:
1 2 3 4 5 6 7 8 9 10 11 |
|
With this configuration, the following controller will forward the request to the built-in ViewController
with some additional parameters:
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 |
|
These parameters can then be used in templates, for example:
1 2 3 4 5 6 7 8 |
|
Adding a listener¶
One way to add custom logic to all responses is to use your own listener. Please refer to the Symfony documentation for the details on how to achieve this.
Using only your custom controller¶
If you want to apply only your custom controller in a given match situation and not use the ViewController
at all, in the configuration you need to indicate the controller, but no template, for example:
1 2 3 4 5 6 7 8 9 10 11 |
|
In this example, as the ViewController
is not applied, the custom controller takes care of the whole process of displaying content, including pointing to the template to be used (in this case, AcmeTestBundle::custom_controller_folder.html.twig
):
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 |
|
Here again custom parameters can be used in the template, e.g.:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Query controller¶
The Query controller is a predefined custom content view controller that runs a repository Query.
You can use it as a custom controller in a view configuration, alongside match rules. It can use properties of the viewed Content item or Location as parameters to the Query.
The Query controller makes it easy to retrieve content without writing custom PHP code and to display the results in a template. Example use cases include:
- List of Blog posts in a Blog
- List of Images in a Gallery
Usage example¶
This example assumes a "Blog" container that contains a set of "Blog post" items. The goal is, when viewing a Blog, to list the Blog posts it contains.
Three items are required:
- a
LocationChildren
QueryType - It will generate a Query retrieving the children of a given Location id - a View template - It will render the Blog, and list the Blog posts it contains
- a
content_view
configuration - It will instruct Platform, when viewing a Content item of type Blog, to use the Query Controller, the view template, and theLocationChildren
QueryType. It will also map the id of the viewed Blog to the QueryType parameters, and set which Twig variable the results will be assigned to.
The LocationChildren QueryType¶
QueryTypes are described in more detail in the next section. In short, a QueryType can build a Query object, optionally based on a set of parameters. The following example will build a Query that retrieves the sub-items of a Location:
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 |
|
Any class will be registered as a QueryType when it:
- implements the QueryType interface,
- is located in the QueryType subfolder of a bundle, and in a file named
<Something>QueryType.php
.
If the QueryType has dependencies, it can be manually tagged as a service using the ezpublish.query_type
service tag, but it is not required in that case.
The content_view
configuration¶
We now need a view configuration that matches Content items of type "Blog", and uses the QueryController to fetch the blog posts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
The view's controller action is set to the QueryController's locationQuery
action (ez_query:locationQueryAction
). Other actions are available that run a different type of search (contentInfo or content).
The QueryController is configured in the query
array, inside the params
of the content_view
block:
query_type
specifies the QueryType to use, based on its name.parameters
is a hash where parameters from the QueryType are set. Arbitrary values can be used, as well as properties from the currently viewed Location and ContentInfo. In that case, the id of the currently viewed Location is mapped to the QueryType'sparentLocationId
parameter:parentLocationId: "@=location.id"
assign_results_to
sets which Twig variable the search results will be assigned to.
The view template¶
Results from the search are assigned to the blog_posts
variable as a SearchResult
object. In addition, since the standard ViewController is used, the currently viewed location
and content
are also available.
1 2 3 4 5 6 |
|
Configuration details¶
controller
¶
Three Controller Actions are available, each for a different type of search:
locationQueryAction
runs a Location SearchcontentQueryAction
runs a Content SearchcontentInfoQueryAction
runs a Content Info search
See the Search documentation page for more details about different types of search.
params
¶
The Query is configured in a query
hash in params
, you could specify the QueryType name, additional parameters and the Twig variable that you will assign the results to for use in the template.
query_type
- Name of the Query Type that will be used to run the query, defined by the class name.parameters
- Query Type parameters that can be provided in two ways: 1. As scalar values, for example an identifier, an id, etc. 1. Using the Expression language. This simple script language, similar to Twig syntax, lets you write expressions that get value from the current Content and/or Location: - For example,@=location.id
will be evaluated to the currently viewed location's ID.content
,location
andview
are available as variables in expressions.assign_results_to
- This is the name of the Twig variable that will be assigned the results.
- Note that the results are the SearchResult object returned by the SearchService.
QueryType objects¶
QueryType is an object that build a Query. It is different from public PHP API queries.
To make a new QueryType available to the Query Controller, you need to create a PHP class that implements the QueryType interface, then register it as such in the Service Container.
For more information about the Service Container on its documentation page.
The QueryType interface¶
The PHP QueryType interface describes three methods:
getQuery()
getSupportedParameters()
getName()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Parameters¶
A QueryType may accept parameters, including string, array and other types, depending on the implementation. They can be used in any way, such as:
- customizing an element's value (limit, ContentType identifier, etc.)
- conditionally adding/removing criteria from the query
- setting the limit/offset
The implementations should use Symfony's OptionsResolver
for parameter handling and resolution.
QueryType example: latest content¶
This QueryType returns a Query that searches for the 10 last published Content items, ordered by reverse publishing date.
It accepts an optional type
parameter that can be set to a ContentType identifier:
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 |
|
Naming of QueryTypes¶
Each QueryType is named after what is returned by getName()
. Names must be unique. A warning will be thrown during compilation if there is a conflict, and the resulting behavior will be unpredictable.
QueryType names should use a unique namespace, in order to avoid conflicts with other bundles. We recommend that the name is prefixed with the bundle's name, e.g.: AcmeBundle:LatestContent
. A vendor/company's name could also work for QueryTypes that are reusable throughout projects, e.g.: Acme:LatestContent
.
Registering the QueryType into the service container¶
In addition to creating a class for a QueryType
, you must also register the QueryType with the Service Container. This can be done in two ways: by convention, and with a service tag.
By convention¶
Any class named <Bundle>\QueryType\*QueryType
that implements the QueryType interface will be registered as a custom QueryType.
Example: AppBundle\QueryType\LatestContentQueryType
.
Using a service tag¶
If the proposed convention doesn't work for you, QueryTypes can be manually tagged in the service declaration:
1 2 3 4 |
|
The effect is exactly the same as when registering by convention.
More information
Follow the FieldType creation Tutorial and learn how to Register the Field Type as a service.
The OptionsResolverBasedQueryType abstract class¶
An abstract class based on Symfony's OptionsResolver
makes the implementation of QueryTypes with parameters easier.
It provides final implementations of getQuery()
and getDefinedParameters()
.
A doGetQuery()
method must be implemented instead of getQuery()
. It is called with the parameters processed by the OptionsResolver, meaning that the values have been validated, and default values have been set.
In addition, the configureOptions(OptionsResolver $resolver)
method must configure the OptionsResolver.
The LatestContentQueryType from the example above can benefit from the abstract implementation:
- validate that
type
is a string, but make it optional - validate that
limit
is an int, with a default value of 10
Note
For further information see the Symfony's Options Resolver documentation page
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 42 |
|
Using QueryTypes from PHP code¶
All QueryTypes are registered in the QueryType registry.
It is available from the container as ezpublish.query_type.registry
.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|