【问题标题】:Symfony Doctrine PaginationSymfony 学说分页
【发布时间】:2016-03-31 13:14:49
【问题描述】:

我有实体用户,例如计数 90355,我需要得到 100 个用户并与该用户做一些逻辑。然后下 100 次使用,这是我有的,但是当我找到所有我的服务器下拉列表时如何解决这个问题?

public function find()
{
    $developers = $this->em->getRepository('ArtelProfileBundle:Users')->findBy(array(), array('id' => 'desc'));
    foreach ($developers as $developer) {
       $this->getApiFullContact($developer);
    }
    return true;
}

我想像这个函数但是 setFirstResult 和 setMaxResults 动态变量?

    public function getPaginationUser()
{
    $qb = $this->getEntityManager()->createQueryBuilder('d');
    $qb
        ->select('d')
        ->from('ArtelProfileBundle:Users', 'd')
        ->setFirstResult(0)
        ->setMaxResults(100)
        ->orderBy('d.id', 'DESC')
        ->getQuery()
        ->getResult()
    ;
    $query = $qb->getQuery();
    $results = $query->getResult();

    return $results;
}

如何迭代?

【问题讨论】:

  • 只需执行 ($page-1) * 100; 其中 $page 是请求的页码,并在 setFirstResult 中使用它而不是 0。也没有理由做两次 getQuery / getResult 。只需删除您在那里的前两个电话。
  • 我如何知道如何调用函数以及可能的第一个结果和最大结果动态变量?我更新了我的问题
  • 不需要渲染到模板我用 cron 运行命令并与用户做一些逻辑,KnpPaginatorBundle 对此有帮助吗?

标签: php symfony doctrine-orm


【解决方案1】:

我把这个例子从我发现的几件事中综合起来,它似乎有效。这是非常基本的,但它只是一个开始。

所以回答:Doctrine2 Paginator getting total results

Symfony 文档:Querying for Objects Using Doctrine's Query Builder

/**
 * @Route("/users/{page}", name="user_list", requirements={"page"="\d+"})
 */
public function getUsersByPage($page = 1)
{
    // get entity manager
    $em = $this->getDoctrine()->getManager();

    // get the user repository
    $developers = $em->getRepository(Users::class);

    // build the query for the doctrine paginator
    $query = $developers->createQueryBuilder('u')
                        ->orderBy('d.id', 'DESC')
                        ->getQuery();

    //set page size
    $pageSize = '100';

    // load doctrine Paginator
    $paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);

    // you can get total items
    $totalItems = count($paginator);

    // get total pages
    $pagesCount = ceil($totalItems / $pageSize);

    // now get one page's items:
    $paginator
        ->getQuery()
        ->setFirstResult($pageSize * ($page-1)) // set the offset
        ->setMaxResults($pageSize); // set the limit

    foreach ($paginator as $pageItem) {
        // do stuff with results...
        dump($pageItem);
    }

    // return stuff..
    return [$userList, $totalItems, $pageCount];
}

【讨论】:

  • 在查询中,orderBy 键应该是 u.id 而不是 d.id $query = $developers->createQueryBuilder('u') ->orderBy('u.id', 'DESC ') ->getQuery();
【解决方案2】:

完全工作示例在这里 -> Using limit and offset in doctrine query builder for manual pagination。我只是给你一些你需要先理解的代码。

这就是它的工作原理,对我来说这是最好的做法!也许不适合其他人!

  1. 请求转到控制器
  2. 控制器调用服务
  3. 具有特征的服务规范化请求参数
  4. 服务从存储库中提取数据
  5. 存储库将结果返回给服务
  6. 服务将结果传递给工厂
  7. 工厂创建结果模型
  8. 工厂将结果模型返回给服务
  9. 服务将结果模型返回给控制器

回购

namespace Application\BackendBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;

class StudentRepository extends EntityRepository
{
    /**
     * @param string|null $name
     * @param int         $limit
     * @param int         $offset
     *
     * @returns array
     */
    public function findPaginatedByName($name, $limit, $offset)
    {
        $qb = $this->createQueryBuilder('s');

        if ($name) {
            $qb->where('s.name = :name')->setParameter('name', $name);
        }

        $qb->setMaxResults($limit)->setFirstResult($offset);

        return $qb->getQuery()->getResult(Query::HYDRATE_SIMPLEOBJECT);
    }

    /**
     * @param string|null $name
     *
     * @return int
     */
    public function findPaginatedByNameCount($name)
    {
        $qb = $this->createQueryBuilder('s')->select('COUNT(s)');

        if ($name) {
            $qb->where('s.name = :name')->setParameter('name', $name);
        }

        return $qb->getQuery()->getResult(Query::HYDRATE_SINGLE_SCALAR);
    }
}

寻呼机特征

namespace Application\BackendBundle\Util;

trait PagerTrait
{
    public function getPage($page = 1)
    {
        if ($page < 1) {
            $page = 1;
        }

        return floor($page);
    }

    public function getLimit($limit = 20)
    {
        if ($limit < 1 || $limit > 20) {
            $limit = 20;
        }

        return floor($limit);
    }

    public function getOffset($page, $limit)
    {
        $offset = 0;
        if ($page != 0 && $page != 1) {
            $offset = ($page - 1) * $limit;
        }

        return $offset;
    }
}

服务

namespace Application\BackendBundle\Service;

use Application\BackendBundle\Factory\StudentFactoryInterface;
use Application\BackendBundle\Model\Student\Result;
use Application\BackendBundle\Repository\StudentRepository;
use Application\BackendBundle\Util\PagerTrait;

class StudentService implements StudentServiceInterface
{
    use PagerTrait;

    private $studentRepository;
    private $studentFactory;

    public function __construct(
        StudentRepository $studentRepository,
        StudentFactoryInterface $studentFactory
    ) {
        $this->studentRepository = $studentRepository;
        $this->studentFactory = $studentFactory;
    }

    /**
     * @param string $name
     * @param int    $page
     * @param int    $limit
     *
     * @return Result
     */
    public function get($name, $page, $limit)
    {
        $page = $this->getPage($page);
        $limit = $this->getLimit($limit);
        $offset = $this->getOffset($page, $limit);
        $total = 0;

        $result = $this->studentRepository->findPaginatedByName($name, $limit, $offset);
        if ($result) {
            $total = $this->studentRepository->findPaginatedByNameCount($name);
        }

        return $this->studentFactory->createStudentResult($result, $name, $page, $limit, $total);
    }
}

【讨论】:

    【解决方案3】:

    这是未经测试的,但我认为这应该可行:

    public function find($offset = 0)
    {
        $developers = $this->em->getRepository('ArtelProfileBundle:Users')->findBy(array(), array('id' => 'desc'), 100, $offset);
    
        foreach ($developers as $developer) {
           $this->getApiFullContact($developer);
        }
    
        if (count($developers) < 100){
            $offset = $offset + 100;
            $this->find($offset)
        }      
    
        return new Response("finished!");  
    
    }
    

    【讨论】:

      【解决方案4】:

      我如何在 symfony 上进行分页

      /**
       * @Route("", name="admin_number_pool", methods={"GET"})
       */
      public function index(NumberPoolRepository $repo, NumberPoolCategoryRepository $categories, Request $request): Response
      {
          $page = $request->query->get('page', 1);
          $limit = 10;
          $pagesCount = ceil(count($repo->findAll()) / $limit);
          $pages = range(1, $pagesCount);
          $pools = $repo->findBy([], [], $limit, ($limit * ($page - 1)));
      
      
          return $this->render('admin/number-pool/index.html.twig', [
              'numberPools' => $pools,
              'categories' => $categories->findAll(),
              'pages' => $pages,
              'page' => $page,
          ]);
      }
      

      【讨论】:

      • 请分享更多细节。通过$repo-&gt;findAll() 读取所有实体看起来有点矫枉过正,因为这加载所有实体只是为了计算它们
      • @NicoHaase 是的,你是对的。我在这里有点匆忙。确实,如果数据库中有很多数据,那将是不切实际的。感谢您的评论。
      猜你喜欢
      • 2012-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多