Reputation: 524
I'm new to Symfony2 and would a step by step guidance how to pass in my pagination code as a service so I don't have to repeat the code and practice good coding habits.
Here is the original pagination code in the controller that I'd like to pass into a service.
I understand I need to setup my services: (beyond this I need help on how to call the variables in my pagination.php service class into the controller to pass into twig)
config.yml
services:
pagination:
class: Demo\ProjectBundle\Services\Pagination
arguments: ["$request_stack", @doctrine]
scope: request
Pagination class (service)
class Pagination
{
protected $request;
public function __construct(RequestStack $requestStack, Registry $doctrine)
{
$this->request = $requestStack->getCurrentRequest();
$this->doctrine = $doctrine;
}
public function pagination()
{
//$page = $request->get('page');
$page = $this->request->query->get('q');
$count_per_page = 5;
$total_count = $this->getTotalBlogs();
$total_pages = ceil($total_count/$count_per_page);
if (!is_numeric($page)) {
$page = 1;
} else {
$page = floor($page);
}
if ($total_count <= $count_per_page) {
$page = 1;
}
if (($page * $count_per_page) > $total_count) {
$page = $total_pages;
}
$offset = 0;
if ($page > 1) {
$offset = $count_per_page * ($page - 1);
}
$em = $this->getDoctrine()->getManager();
$blogQuery = $em->createQueryBuilder()
->select('b')
->from('DemoProjectBundle:Blog', 'b')
->addOrderBy('b.created', 'DESC')
->setFirstResult($offset)
->setMaxResults($count_per_page);
$blogFinalQuery = $blogQuery->getQuery();
$blogPage = $blogFinalQuery->getArrayResult();
foreach ($blogPage as $blog) {
$blog_id = $blog['id'];
$commentRepository = $this->getDoctrine()
->getRepository('DemoProjectBundle:Comment');
$comments[] = $commentRepository->findByBlog($blog_id);
}
return array(
'blogPage' => $blogPage,
'total_pages' => $total_pages,
'current_page' => $page,
'comments' => $comments,
);
}
}
PageController (with pagination code I want to put into a service)
class PageController extends Controller
{
public function indexAction(Request $request)
{
// Pagination code
$page = $request->get('page');
$count_per_page = 5;
$total_count = $this->getTotalBlogs();
$total_pages = ceil($total_count/$count_per_page);
if (!is_numeric($page)) {
$page = 1;
} else {
$page = floor($page);
}
if ($total_count <= $count_per_page) {
$page = 1;
}
if (($page * $count_per_page) > $total_count) {
$page = $total_pages;
}
$offset = 0;
if ($page > 1) {
$offset = $count_per_page * ($page - 1);
}
$em = $this->getDoctrine()->getManager();
$blogQuery = $em->createQueryBuilder()
->select('b')
->from('DemoProjectBundle:Blog', 'b')
->addOrderBy('b.created', 'DESC')
->setFirstResult($offset)
->setMaxResults($count_per_page);
$blogFinalQuery = $blogQuery->getQuery();
$blogPage = $blogFinalQuery->getArrayResult();
foreach ($blogPage as $blog) {
$blog_id = $blog['id'];
$commentRepository = $this->getDoctrine()
->getRepository('DemoProjectBundle:Comment');
$comments[] = $commentRepository->findByBlog($blog_id);
}
return $this->render('DemoProjectBundle:Default:index.html.twig', array(
'blogPage' => $blogPage,
'total_pages' => $total_pages,
'current_page' => $page,
'comments' => $comments,
));
}
index.html.twig
{% block body %}
{% for blog in blogPage %}
<div class="container">
<div class="row">
<div class="col-sm-8 blog-main">
<div class="blog-post">
<h2 class="blog-post-title">{{ blog.title }}</h2>
<p class="blog-post-meta"><time datetime="{{ blog.created|date('c') }}">{{ blog.created|date('l, F j, Y') }}</time> by <a href="#">{{ blog.author }}</a></p>
<div class="comment">
<p><small>Comments: {{ comments[loop.index0]|length }}</small> </p>
</div>
<p>{{ blog.blog|truncate(350, true) }}</p><br>
<div class="tags">
<p><strong><small>Tags: </small></strong><span class="highlight">{{ blog.tags }}</span></p>
</div>
<p class="continue"><a href="{{ path('demo_project_show', { 'id': blog.id, 'slug': blog.slug }) }}">More reading» </a></p>
<hr>
</div><!-- /.blog-post -->
</div>
</div>
</div>
{% endfor %}
{% endblock %}
{% block pagination %}
<ul class="pager">
{% if total_pages > 0 %}
<div class="pagination">
<ul>
{% for i in 1..total_pages %}
{% if loop.first %}
<li class="{% if current_page == 1 %} {% endif %}"><a href="{{ path('demo_project_homepage', { 'page':current_page - 1 }) }}">Previous</a></li>
{%endif%}
{% if loop.last %}
<li class="{% if current_page == total_pages %} {% endif %}"><a href="{{ path('demo_project_homepage', { 'page':current_page + 1 }) }}">Next</a></li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
</ul>
{% endblock %}
Upvotes: 1
Views: 1019
Reputation: 1608
When you define the service, it's available in the service container, which you can access from the controller.
Service definition:
services:
pagination:
class: Demo\ProjectBundle\Services\Pagination
arguments: [@request_stack] # use @ to refer another services
scope: request
In your controller:
class PageController extends Controller
{
public function indexAction(Request $request)
{
$pagination = $this->container->get("pagination");
...
}
}
Then it's just a matter of putting your pagination code in the Pagination
class. This class structure depends on your design, but normally you have one or more public methods to pass data from the controller for the service to do it's logic and then returning the expected response.
EDIT
To get data from your service to the controller, return them in a way you can use them later in your templates or wherever you need it. One way of doing this is using arrays:
Returning an array
class Pagination
{
public function getPaginationData()
{
return array('blogPage' => $blogPage, total_pages' => $total_pages, 'current_page' => $page, 'comments' => $comments);
}
}
In your controller
$pagination = $paginationService->getPaginationData();
// return to the Twig template
return ['pagination_data' => $pagination];
In your twig template you can access the array as normal:
{{ pagination_data.blogPage }}
{{ pagination_data.total_pages }}
And so on so forth. You can replace the array for a class if you need more internal logic, even passing the full Pagination service to the Twig template. At the end it all depends on your application design.
Upvotes: 3