eZ Platform Discussions

Query controller or Custom Controller > Paginate search query

version2

#1

Good afternoon.

In the full view of my objects of type rubric I must put a search form to search among the articles children (or grandson and more) .

The search will use a text search with solr plus some filters (free / paid articles)

The thing is easy to do with a custom controller
https://doc.ezplatform.com/en/2.1/guide/controllers/#custom-rendering-logic

template_rules.yml

#ezpublish:
system:
    all_group:
        location_view:
            full:
                rubric:
                    controller: MyBundle:Rubric:full
                    template: "MyBundle:full:rubric.html.twig"
                    match:
                        Identifier\ContentType: ["rubric"]

But maybe this is your chance to use a Query controller
https://doc.ezplatform.com/en/2.1/guide/controllers/#query-controller

It would allow me to make a reusable article search tool.

Am I in an appropriate use case?
How would you do that?
Thank you for your feedback and suggestions.


#2

Good,

I decided to use a custom controller.
It allows me to manage a Synfony form.


    public function fullAction(Request $request, ContentView $view)
    {
        $query = new LocationQuery();

        $location = $view->getLocation();

        $query->limit = 3;
        $query->filter = new Criterion\LogicalAnd([
            new Criterion\ContentTypeIdentifier(['article', 'breve', 'publi_redactionnel']),
            new Criterion\Subtree($location->pathString),
        ]);
        
        $form = $this->createFormBuilder( array('q' => '') )
            ->add('q', TextType::class, ['required' => false])
            ->add('submit', SubmitType::class)
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            $q = trim($data['q']); // TODO Est ce que l'on doit protéger la valeur ?
            $query->query = new Criterion\FullText($q);
        }

        $articles = $this->getRepository()->getSearchService()->findLocations($query);

        $view->addParameters(['articles' => $articles]);
        $view->addParameters(['form' => $form->createView()]);

        // Set custom header for the Response
        $response = new Response();
        $response->headers->add(['X-Hello' => 'World']); // TODO Cache
        $view->setResponse($response);

        return $view;
    }

But I still have one small question… (very important.) How to manage pagination?


#3

Okay.

I turn to the “PagerFanta” solution.

But I can’t make the connection between search and pagination.


    public function fullAction(Request $request, ContentView $view)
    {
        $page = $request->get('page', 1);
        $query = new LocationQuery();
        $location = $view->getLocation();

        $query->filter = new Criterion\LogicalAnd([
            new Criterion\ContentTypeIdentifier(['article', 'breve', 'publi_redactionnel']),
            new Criterion\Subtree($location->pathString),
        ]);

        $form = $this->createFormBuilder( array('q' => '') )
            ->add('q', TextType::class, ['required' => false])
            ->add('submit', SubmitType::class)
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            $q = trim($data['q']); // TODO Est ce que l'on doit protéger la valeur ?
            $query->query = new Criterion\FullText($q);
            $page = 1; // Force page 1
        }

        $pagerArticle = new Pagerfanta(
            new LocationSearchHitAdapter($query, $this->getRepository()->getSearchService())
        );

        $pagerArticle->setMaxPerPage(2);
        $pagerArticle->setCurrentPage($page);

        $view->addParameters([
            'totalArticleCount' => $pagerArticle->getNbResults(),
            'pagerArticle' => $pagerArticle,
            'form' => $form->createView(),
        ]);

        // Set custom header for the Response
        $response = new Response();
        $response->headers->add(['X-Hello' => 'World']); // TODO Cache
        $view->setResponse($response);

        return $view;
    }

In my twig :

{% extends noLayout == true ? viewbaseLayout : pagelayout %}
{% block content %}
    <h1>{{ ez_content_name(content) }}</h1>

    {{ form(form) }}

    <section>
        <h2>Listing all articles: {{ totalArticleCount }} articles found.</h2>

        {% for article in pagerArticle %}{#{{ dump(article.valueObject) }}#} {# Location #}
            <article>
                <h2>{{ ez_content_name(article.valueObject.contentInfo) }}</h2>
                <a href="{{ path( article.valueObject ) }}">Lire la suite</a>
            </article>
        {% endfor %}

        {# Only display Pagerfanta navigator if needed. #}
        {% if pagerArticle.haveToPaginate() %}
            <div class="pagerfanta">
                {{ pagerfanta( pagerArticle, 'twitter_bootstrap_translated', {'routeName': location} ) }}
            </div>
        {% endif %}
    </section>

{% endblock %}

If I do a search it is well taken into account. But if I change pages, she’s lost.


#4

It would be really cool to be able to do that!

new LocationSearchHitAdapter($query, $this->getRepository()->getSearchService(), $form)

#5

Follow this https://github.com/netgen/ezplatform-site-api/pull/70
It will be merged soon and new version of Site API will be released


#6

Hy @gof,

Version 2.1.1 is released. Is this feature available?

I have another very simple case: Displaying the list of Content children of a folder. (without search therefore)

Of course my file contains more than 500 Content…
So I need a pagination.


#7

Site API is a bundle that we at Netgen build and maintain, so you need to install it on your ez installation:

AFAIK it should work with the newest eZ Platform version


#8

Bonjour,

To make work together a Symfony form and pagination I found this solution :

$form = $this->createFormBuilder( array('q' => ''), ['csrf_protection' => false] )
            ->setMethod('GET')
            ->add('q', TextType::class, ['required' => false])
            ->add('submit', SubmitType::class)
            ->getForm();

$form->handleRequest($request);

if ($form->isValid()) {
    // ...
}

$view->addParameters([
            'pager' => $pager,
            'form' => $form->createView(),
            'q' => $q,
]);

{{ pagerfanta( pager, 'twitter_bootstrap_translated', {'routeName': location, 'routeParams':{'form[q]':q} } ) }}

Portez-vous bien et bon code à tous :slight_smile:


#9

just for your information, you have the same functionality here: https://github.com/ezsystems/ezplatform-admin-ui/blob/master/src/bundle/Controller/SearchController.php .
This is used for the Backend search