Symfony 4 - KnpPaginator Bundle:“服务未找到,尽管存在于应用程序容器中”

9

我一直在跟随教程,所有的指令都显示是按照同样的方式完成的,但在Symfony 4中似乎无法正常工作。我是否忽略了某些东西或者这个bundle根本不兼容?

我运行了:composer require knplabs/knp-paginator-bundle

由于Flex的自动加载,它被自动加载到bundles.php中。

将以下内容插入到config/services.yaml中:

knp_paginator:
    page_range:                 5          # default page range used in pagination control
    default_options:
        page_name:              page       # page query parameter name
        sort_field_name:        sort       # sort field query parameter name
        sort_direction_name:    direction  # sort direction query parameter name
        distinct:               true       # ensure distinct results, useful when ORM queries are using GROUP BY statements
    template:
        pagination: KnpPaginatorBundle:Pagination:twitter_bootstrap_v3_pagination.html.twig     # sliding pagination controls template
        sortable: KnpPaginatorBundle:Pagination:sortable_link.html.twig                         # sort link template

尝试在控制器中使用以下内容:

$paginator  = $this->get('knp_paginator');

您遇到了以下错误:

找不到服务"knp_paginator":尽管它存在于应用程序的容器中,但在"App\Controller\PhotoController"内部的容器是一个较小的服务定位器,只知道关于"doctrine"、"form.factory"、"http_kernel"、"request_stack"、"router"、"security.authorization_checker"、"security.token_storage"、"serializer"、"session"和"twig"服务。除非您需要额外的惰性加载,否则请尝试使用依赖注入。否则,您需要使用"PhotoController::getSubscribedServices()"声明它。


根据错误提示,我觉得可能是我把 knp_paginator 的 yaml 设置放错了位置。但是我找不到一个合适的位置放置它,否则就会崩溃并显示它不属于“那里”。当我将其缩进“services”时,它会显示“配置键“page_range”不支持定义“knp_paginator””,这很糟糕。 - Darius
尝试在config/packages目录中创建一个名为“knppaginator.yaml”的新文件,并将您的配置放入新文件中,而不是services.yaml文件中。 - Frank B
尝试了knp_paginator.yaml和knppaginator.yaml,但没有成功,出现了相同的错误。有趣的是,我故意将其配置弄错为knpS_paginator,它会抛出错误,说“没有扩展能够加载...”,所以它知道knp_paginator是正确的。 - Darius
我自己试过了。创建了一个文件config/packages/knp_paginator.yaml,并将配置放入其中,例如在GitHub上的示例。需要清除缓存,然后它就可以正常工作了。请确保使用扩展名yaml而不是yml。 - Frank B
@FrankB 这个问题是因为使用了 "extends AbstractController",Symfony 建议使用抽象控制器而不是常规控制器。Malcolm 展示了如何在使用 AbstractController 时解决这个问题。缓存已被清除,所以不是缓存的问题。 - Darius
很高兴听到您的问题已经解决。感谢您的回答。 - Frank B
4个回答

29

你需要扩展 Controller 类而不是 AbstractController 类:

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MyController extends Controller
{

    public function myAction()
    {
        $paginator  = $this->get('knp_paginator');

或者更好的是保留AbstractController ,并将 knp_paginator 服务注入到您的操作中:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Knp\Component\Pager\PaginatorInterface;

class MyController extends AbstractController
{

    public function myAction(PaginatorInterface $paginator)
    {
        $paginator->paginate()...
    }

1
太神奇了,我甚至不知道你是怎么想到 AbstractController 是问题所在的。非常感谢你。我将尝试使用你刚刚编写的允许我仍然使用 AbstractController 的编辑版本。但是,值得一提的是,将 AbstractController 更改为 controller 也可以解决问题。 - Darius
1
刚刚测试了一下AbstractController方法,也非常好用。 - Darius
您好,我在我的应用程序(Symfony 4)中实现分页时遇到了问题。 - Angel
@Darius 你是如何让它与AbstractController一起工作的? - mehmetsen80
@mehmetsen80 看看 Malcolm 的回答,他展示了把它注入到动作变量中的方法。myAction(PaginatorInterface $paginator){ } - Darius
4
请注意,Controller在Symfony 4.2中已被弃用,并将在Symfony 5中被删除,因此您需要改用注入方法。 - Sam

8

在我的情况下,我使用AbstractController,正如malcolm所说,最好直接在您的操作中注入服务,即使如此,我多次调用一个方法,我认为覆盖getSubscribedServices对我的目的更加清晰。

public static function getSubscribedServices(): array
{
    $services = parent::getSubscribedServices();
    $services['fos_elastica.manager'] = RepositoryManagerInterface::class;
    $services['knp_paginator'] = PaginatorInterface::class;

    return $services;
}

private function listHandler(Search $search, Request $request, int $page): Response
{
    //...
    $repository = $this->container->get('fos_elastica.manager')->getRepository(Foo::class);
    //...

}

这似乎是正确的方法。适用于各种服务。另一种解决方案对于 sonata.admin.pool 无效,但这种方法有效。 - Indivision Dev
这是在Symfony 4.2中期望的方式。 - winkbrace

1

0
在我的情况下,我使用的是Symfony 4.3,我只需要将该类作为参数注入到方法中,然后就完成了。
public function list(ProductManager $productManager)
{ 
   $products = $productManager->prepareProducts(); 
   return $products;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接