Esta excepción:
Service "knp_paginator" not found even though it exists in the app's container
aparece en proyectos de Symfony 4 que utilizan código de versiones anteriores (Symfony 3), donde el servicio se solicita a través del contenedor de servicios , por ejemplo, el siguiente controlador debería lanzar la excepción:
<?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;
// Tenga en cuenta también que extiende la clase 'Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller'
// que está obsoleto en 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();
// Importante: y pagina la consulta con knp paginator, sin embargo accediendo al contenedor de servicios
$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
));
}
}
El problema, como se describe en el código, se debe a la forma en que intenta acceder al servicio de paginador de KNP. En este artículo, le explicaremos brevemente cómo resolver esta excepción en su proyecto Symfony 4.
Solución
Básicamente, lo que debe hacer para resolver este problema es analizar su código existente e identificar desde dónde está solicitando el servicio de paginador. Si se requiere del contenedor de servicios, deberá eliminar esa variable e inyectarla PaginatorInterface
directamente en el controlador. Esto expondrá la misma variable que funciona de la misma manera que lo hizo desde el contenedor de servicios, tenga en cuenta también que el controlador necesita extender la AbstractController
clase, no la Controller
clase, ya que esto evitará futuras advertencias de depreciación:
<?php
namespace App\Controller;
// 1. Incluir la clase AbstractController
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
// 2. El controlador extiende ahora el AbstractController
class ExampleController extends AbstractController
{
// 3. El paginador $paginator se inyecta en la acción
public function exampleaction(PaginatorInterface $paginator){
$em = $this->get('doctrine.orm.entity_manager');
$dql = "SELECT a FROM AcmeMainBundle:Article a";
$query = $em->createQuery($dql);
// 3. Usa la paginación para hacer algo con el paginador
$pagination = $paginator->paginate(
$query, /* consulta, no resultado */
$request->query->getInt('page', 1), /*número de página*/
10 /* límite por página */
);
}
}
Solución de nuestro ejemplo
El siguiente fragmento muestra cómo corregir el ejemplo inicial correctamente con la implementación de AbstractController
e inyectando el paginador directamente en la acción:
<?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;
// El controlador extiende ahora el AbstractController
class AuthorsController extends AbstractController
{
// Controlador que muestra todas las novedades del repositorio x
// El paginador se inyecta en la acción
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
));
}
}
Que te diviertas ❤️!
Conviertete en un programador más sociable