不完全确定(控制器)转发在Symfony中是如何工作的


Not entirely sure how (controller) forwarding works in Symfony

我试图将一些代码移动到as函数以将分页添加到我的页面,到现在看起来像这样的某个控制器:

<?php
namespace AppBundle'Controller;
use Sensio'Bundle'FrameworkExtraBundle'Configuration'Route;
use Symfony'Bundle'FrameworkBundle'Controller'Controller;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'HttpFoundation'Response;
use Symfony'Component'HttpFoundation'JsonResponse;
use AppBundle'Entity'Movie;
class PaginationController extends Controller
{
    public function paginationAction(Request $request, $pageNumber)
    {
        $recordsPerPage = 5;
        $page = $pageNumber;
        // Positioning
        $start = ($page > 1) ? ($page * $recordsPerPage) - $recordsPerPage : 0;
        // Query
        //Records:
        //$movies = $this->getDoctrine()->getEntityManager()->getRepository('AppBundle:Movie')->FindAll();
        $repository = $this->getDoctrine()->getRepository('AppBundle:Movie');
        //Data to count:
        $qb = $repository->createQueryBuilder('m');
        $query = $qb
        ->getQuery();
        $totalAmountRows = count($query->getResult());
        //For display:
        $query = $qb
        ->setFirstResult($start)
        ->setMaxResults($recordsPerPage)
        ->getQuery();
        $movies = $query->getResult();
        //Pagination: 
        $filterVariables = "";
        //Always round up number (whole pages):
        $totalPages = ceil($totalAmountRows / $recordsPerPage);
        return array(
            'movies' => $movies,
            'filtervariables' => $filterVariables,
            'totalPages' => $totalPages,
            'totalAmountRows' => $totalAmountRows,
            'pageNumber' => $pageNumber
        );
    }
}

应该接收值的控制器如下所示:

<?php
namespace AppBundle'Controller;
use Sensio'Bundle'FrameworkExtraBundle'Configuration'Route;
use Symfony'Bundle'FrameworkBundle'Controller'Controller;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'HttpFoundation'Response;
use Symfony'Component'HttpFoundation'JsonResponse;
use AppBundle'Entity'Movie;
class MovieDisplayController extends Controller
{
    public function showAction(Request $request, $pageNumber)
    {
        $this->forward('AppBundle:Pagination:pagination', array(
            'pageNumber' => $pageNumber
        ));
        return $this->render('movies/index.html.twig', array(
            'movies' => $movies,
            'filtervariables' => $filterVariables,
            'page' => $page,
            'totalPages' => $totalPages,
            'totalAmountRows' => $totalAmountRows,
            'pageNumber' => $pageNumber
        ));
    }
}

但是当我看页面时,我看到:Notice: Undefined variable: movies.我应该如何更改我的代码,以便它知道我正在尝试将$movies变量从一个控制器提供给另一个控制器?

编辑:为了让我完全理解下面的答案,我想在我的问题中添加以下内容(感谢@Rvanlaak):

当我想处理MovieRepository中的分页时,它应该是什么样子?

转发请求也会导致获得完全独立的响应。换句话说,你的showAction可以直接返回 $this->forward 的返回响应对象。

您要做的不是转发,您可以处理MovieRepository中的分页,甚至更好地使用像KnpPaginatorBundle这样的捆绑包,只需要您传递QueryBuilder,每页结果和活动页面。

编辑附加问题:为了让存储库进行分页,您应该创建一个自定义存储库类并添加一个函数,该函数根据$resultsPerPage$activePage输入参数返回预期结果:

// Oversimplified repo
class MovieRepository extends EntityRepository 
{
    public function findAllWithPagionation($resultsPerPage, $activePage) 
    {
        $builder = $this->createQueryBuilder('m');
        $totalRows = $builder->getQuery()->getSingleScalarResult();
        return array(
            'total' => $totalRows,
            'results' => $builder 
                ->setFirstResult($resultsPerPage * $activePage)
                ->setMaxResults($resultsPerPage)
                ->getQuery()
                ->getResult()
        );
    }
}

编辑

做这种事情(在这种情况下是资源获取、分页)的最佳位置是在自定义EntityRepository中。

转发其他操作不会让您访问转发操作的变量。

换句话说,前向paginationAction不会给你访问$movies,因为你没有在原始方法showAction中定义它。

您应该通过在仅返回查询结果的Repository方法中移动所有QueryBuilder逻辑来保持事物的位置。

但是要解决此问题,您需要避免转发。更改名称(可以getPaginatedResults(),在存储库中移动时进行调整),删除请求参数(仅保留$pageNumber)。

然后,使showAction看起来像:

public function showAction(Request $request, $pageNumber)
{
    $data = $this->getPaginatedResults($pageNumber); // Actually $this->paginateAction($request, $pageNumber);    
    return $this->render('movies/index.html.twig', array(
        'movies' => $data['movies'], // Get it from $data
        'filtervariables' => $data['filterVariables'],
        'page' => $data['page'],
        'totalPages' => $data['totalPages'],
        'totalAmountRows' => $data['totalAmountRows'],
        'pageNumber' => $data['pageNumber'],
    ));
}