How to solve KnpPaginator exception in Symfony 4: Service "knp_paginator" not found even though it exists in the app's container

How to solve KnpPaginator exception in Symfony 4: Service "knp_paginator" not found even though it exists in the app's container

This exception appears on Symfony 4 projects that are using code from previous versions (Symfony 3), where the service is requested via the service container, for example, the following controller should throw the exception:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use ReCaptcha\ReCaptcha;
use Doctrine\ORM\Query\Expr\Join;
use App\Entity\FosUser;

// Note as well that extends the 'Symfony\Bundle\FrameworkBundle\Controller\Controller' class 
// which is deprecated in Symfony 4
class AuthorsController extends Controller
{
    // Controller that shows all the news from x repository
    public function show(Request $request, FosUser $user){
        $em = $this->getDoctrine()->getManager();
        
        $repoArticles = $em->getRepository('App:News');
        
        $pagination = $repoArticles->createQueryBuilder('a')
            ->where('a.published = 1')
            ->andWhere('a.author = :user')
            ->orderBy('a.datepublished', 'DESC')
            ->setParameter('user', $user->getId())
            ->getQuery()
            ->getResult();
        
        // Important: and paginates the query with knp paginator, however accesing the service container
        $paginator = $this->get('knp_paginator');
        $entities = $paginator->paginate($pagination, $request->query->getInt('page', 1), 14);
    
        return $this->render('news/show.html.twig',array(
            'user' => $user,
            'entities' => $entities
        ));
    }
}

The issue as described in the code, is caused by the way you try to access the paginator service of KNP. In this article, we'll explain you briefly how to solve this exception in your Symfony 4 project.

Solution

Basically what you need to do to resolve this problem is analyze your existing code and identify from where you are requesting the paginator service. If it is required from the service container, you will need to remove that variable and injecting the PaginatorInterface to the controller directly. This will expose the same variable that works in the same way it did from the service container, note as well that the controller needs to extend the AbstractController class, not the Controller class as this will prevent future deprecation warnings:

<?php

namespace App\Controller;

// 1. Include the AbstractController class
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

// 2. The controller extends now the AbstractController
class ExampleController extends AbstractController
{
    // 3. The paginator is injected in the action $paginator
    public function exampleaction(PaginatorInterface $paginator){
        
        $em    = $this->get('doctrine.orm.entity_manager');
        $dql   = "SELECT a FROM AcmeMainBundle:Article a";
        $query = $em->createQuery($dql);

        // 3. Use paginator to do something with the paginator
        $pagination = $paginator->paginate(
            $query, /* query NOT result */
            $request->query->getInt('page', 1), /*page number*/
            10 /*limit per page*/
        );
    }
}

Solution of our example

The following snippet shows how to fix the initial example properly with the implementation of the AbstractController and injecting the paginator directly in the action:

<?php

namespace App\Controller;

// Use the abstract controller instead
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use ReCaptcha\ReCaptcha;
use Doctrine\ORM\Query\Expr\Join;
use App\Entity\FosUser;

// The controller extends now the AbstractController
class AuthorsController extends AbstractController
{
    // Controller that shows all the news from x repository
    // The paginator is injected in the action $paginator
    public function show(Request $request, FosUser $user, PaginatorInterface $paginator){
        $em = $this->getDoctrine()->getManager();
        
        $repoArticles = $em->getRepository('App:News');
        
        $pagination = $repoArticles->createQueryBuilder('a')
            ->where('a.published = 1')
            ->andWhere('a.author = :user')
            ->orderBy('a.datepublished', 'DESC')
            ->setParameter('user', $user->getId())
            ->getQuery()
            ->getResult();
        
        $entities = $paginator->paginate($pagination, $request->query->getInt('page', 1), 14);
    
        return $this->render('news/show.html.twig',array(
            'user' => $user,
            'entities' => $entities
        ));
    }
}

Happy coding !

This could interest you

Become a more social person