Artikel ini dirunut berdasarkan Jobeet Tutorial, yang dibuat oleh Fabien Potencier, untuk Symfony 1.4.
Routing kategorinya
Hal pertama yang akan kita lakukan adalah membuat url untuk halaman kategori agar lebih mudah dibaca. Untuk itu kita harus mengubah konfigurasi routingnya. Edit file konfigurasi routing, dengan menambahkan kode berikut:src/Ibw/JobeetBundle/Resources/config/routing.yml
# ...
IbwJobeetBundle_category:
pattern: /category/{slug}
Untuk dapat menggunakan method getSlug() kita harus menambahkannya di model Category
src/Ibw/JobeetBundle/Entity/Category.php
use Ibw\JobeetBundle\Utils\Jobeet as Jobeet;
class Category
{
// ...
public function getSlug()
{
return Jobeet::slugify($this->getName());
}
}
Link kategorinya
Sekarang kita harus mengedit index.html.twig, untuk menambahkan link ke halaman kategori.src/Ibw/JobeetBundle/Resources/views/Job/index.html.twig
<!-- some HTML code -->
<h1><a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug }) }}">{{ category.name }}</a></h1>
<!-- some HTML code -->
</table>
{% if category.morejobs %}
<div class="more_jobs">
and <a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug }) }}">{{ category.morejobs }}</a>
more...
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endblock %}
di template tersebut kita menggunakan category.morejobs, untuk itu mari kita definisikan di model Category:src/Ibw/JobeetBunlde/Entity/Category.php
class Category
{
// ...
private $more_jobs;
// ...
public function setMoreJobs($jobs)
{
$this->more_jobs = $jobs >= 0 ? $jobs : 0;
}
public function getMoreJobs()
{
return $this->more_jobs;
}
}
Attribut more_job akan menampilkan jumlah lowongan dari halaman kategori selain lowongan yang sudah ditampilkan sebelumnya. Sekarang di JobController kita harus menambahkan value dari more_jobs untuk masing-masing kategori.
src/Ibw/JobeetBundle/Controller/JobController.php
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$categories = $em->getRepository('IbwJobeetBundle:Category')->getWithJobs();
foreach($categories as $category)
{
$category->setActiveJobs($em->getRepository('IbwJobeetBundle:Job')->getActiveJobs($category->getId(), $this->container->getParameter('max_jobs_on_homepage')));
$category->setMoreJobs($em->getRepository('IbwJobeetBundle:Job')->countActiveJobs($category->getId()) - $this->container->getParameter('max_jobs_on_homepage'));
}
return $this->render('IbwJobeetBundle:Job:index.html.twig', array(
'categories' => $categories
));
}
src/Ibw/JobeetBundle/Repository/JobRepository.php
// ...
public function countActiveJobs($category_id = null)
{
$qb = $this->createQueryBuilder('j')
->select('count(j.id)')
->where('j.expires_at > :date')
->setParameter('date', date('Y-m-d H:i:s', time()));
if($category_id)
{
$qb->andWhere('j.category = :category_id')
->setParameter('category_id', $category_id);
}
$query = $qb->getQuery();
return $query->getSingleScalarResult();
}
// ...
Modifikasi Category Controller
Sekarang saatnya membuat CategoryController, buat file baru bernama CategoryController.php di dalam folder Controller.src/Ibw/JobeetBundle/Controller/CategoryController.php
namespace Ibw\JobeetBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Ibw\JobeetBundle\Entity\Category;
/**
* Category controller
*
*/
class CategoryController extends Controller
{
}
Update databasenya
Kita perlu menambahkan field slug di tabel kategori, untuk itu tambahkan filed baru di file Category.orm.yml
src/Ibw/JobeetBundle/Resources/config/doctrine/Category.orm.yml
Ibw\JobeetBundle\Entity\Category:
type: entity
repositoryClass: Ibw\JobeetBundle\Repository\CategoryRepository
table: category
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 255
unique: true
slug:
type: string
length: 255
unique: true
oneToMany:
jobs:
targetEntity: Job
mappedBy: category
manyToMany:
affiliates:
targetEntity: Affiliate
mappedBy: categories
lifecycleCallbacks:
prePersist: [ setSlugValue ]
preUpdate: [ setSlugValue ]
Hapus method getSlug() dari model Category (src/Ibw/JobeetBundle/Entity/Category.php). Kemudian update databasenya dengan menjalankan perintah berikut:
php app/console doctrine:generate:entities
Jika kamu buka file model Category maka kamu akan melihat kode berikut:
src/Ibw/JobeetBundle/Entity/Category.php
// ...
/**
* @var string
*/
private $slug;
/**
* Set slug
*
* @param string $slug
* @return Category
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* @return string
*/
public function getSlug()
{
return $this->slug;
}
Sesuaikan method SetSlugValue()
src/Ibw/JobeetBundle/Entity/Category.php
// ...
class Category
{
// ...
public function setSlugValue()
{
$this->slug = Jobeet::slugify($this->getName());
}
}
Sekarang kita drop databasenya dan kita buat ulang serta kita reload fixturenya dengan menggunakan perintah berikut:
php app/console doctrine:database:drop --force
php app/console doctrine:database:create
php app/console doctrine:schema:update --force
php app/console doctrine:fixtures:load
Halaman kategorinya
Sekarang kita perlu mengedit Category Controllernya, pada method showAction() tambahkan kode berikut:src/Ibw/JobeetBundle/Controller/CategoryController.php
// ...
public function showAction($slug)
{
$em = $this->getDoctrine()->getManager();
$category = $em->getRepository('IbwJobeetBundle:Category')->findOneBySlug($slug);
if (!$category) {
throw $this->createNotFoundException('Unable to find Category entity.');
}
$category->setActiveJobs($em->getRepository('IbwJobeetBundle:Job')->getActiveJobs($category->getId()));
return $this->render('IbwJobeetBundle:Category:show.html.twig', array(
'category' => $category,
));
}
// ...
Langkah terakhir adalah membuat file show.html.twig untuk menampilkan halaman kategori.
src/Ibw/JobeetBundle/Resources/views/Category/show.html.twig
{% extends 'IbwJobeetBundle::layout.html.twig' %}
{% block title %}
Jobs in the {{ category.name }} category
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('bundles/ibwjobeet/css/jobs.css') }}" type="text/css" media="all" />
{% endblock %}
{% block content %}
<div class="category">
<div class="feed">
<a href="">Feed</a>
</div>
<h1>{{ category.name }}</h1>
</div>
<table class="jobs">
{% for entity in category.activejobs %}
<tr class="{{ cycle(['even', 'odd'], loop.index) }}">
<td class="location">{{ entity.location }}</td>
<td class="position">
<a href="{{
path('ibw_job_show', { 'id': entity.id, 'company': entity.companyslug,
'location': entity.locationslug, 'position': entity.positionslug }) }}">
{{ entity.position }}
</a>
</td>
<td class="company">{{ entity.company }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Mengikludkan template twig lainnya
Buat file list.html.twig untuk menampilkan list dari job di halaman kategori.src/Ibw/JobeetBundle/Resources/views/Job/list.html.twig
<table class="jobs">
{% for entity in jobs %}
<tr class="{{ cycle(['even', 'odd'], loop.index) }}">
<td class="location">{{ entity.location }}</td>
<td class="position">
<a href="{{
path('ibw_job_show', { 'id': entity.id, 'company': entity.companyslug,
'location': entity.locationslug, 'position': entity.positionslug }) }}">
{{ entity.position }}
</a>
</td>
<td class="company">{{ entity.company }}</td>
</tr>
{% endfor %}
</table>
Kamu bisa mengincludekan file template denga menggunakan fungsi include. Replace tag <table> .... </table> pada file berikut:
src/Ibw/JobeetBundle/Resources/view/Job/index.html.twig
{{ include ('IbwJobeetBundle:Job:list.html.twig', {'jobs': category.activejobs}) }}
src/Ibw/JobeetBundle/Resources/view/Category/show.html.twig
{{ include ('IbwJobeetBundle:Job:list.html.twig', {'jobs': category.activejobs}) }}
Membuat pagination
Langkah awal untuk membuat pagination adalah dengan membuat routingnya terlebih dahulu.src/Ibw/JobeetBundle/Resources/config/routing.yml
IbwJobeetBundle_category:
pattern: /category/{slug}/{page}
defaults: { _controller: IbwJobeetBundle:Category:show, page: 1 }
# ...
Kemudian bersihkan chace setelah memodifikasi file routing:
php app/console cache:clear --env=dev
php app/console cache:clear --env=prod
Set parameter value untuk membatasi data Job pada halaman Category.
app/config/config.yml
// ...
public function getActiveJobs($category_id = null, $max = null, $offset = null)
{
$qb = $this->createQueryBuilder('j')
->where('j.expires_at > :date')
->setParameter('date', date('Y-m-d H:i:s', time()))
->orderBy('j.expires_at', 'DESC');
if($max)
{
$qb->setMaxResults($max);
}
if($offset)
{
$qb->setFirstResult($offset);
}
if($category_id)
{
$qb->andWhere('j.category = :category_id')
->setParameter('category_id', $category_id);
}
$query = $qb->getQuery();
return $query->getResult();
}
Ubah lagi method showAction() pada CategoryController, seperti berikut ini:
src/Ibw/JobeetBundle/Controller/CategoryController.php
public function showAction($slug, $page)
{
$em = $this->getDoctrine()->getManager();
$category = $em->getRepository('IbwJobeetBundle:Category')->findOneBySlug($slug);
if (!$category) {
throw $this->createNotFoundException('Unable to find Category entity.');
}
$total_jobs = $em->getRepository('IbwJobeetBundle:Job')->countActiveJobs($category->getId());
$jobs_per_page = $this->container->getParameter('max_jobs_on_category');
$last_page = ceil($total_jobs / $jobs_per_page);
$previous_page = $page > 1 ? $page - 1 : 1;
$next_page = $page < $last_page ? $page + 1 : $last_page;
$category->setActiveJobs($em->getRepository('IbwJobeetBundle:Job')->getActiveJobs($category->getId(), $jobs_per_page, ($page - 1) * $jobs_per_page));
return $this->render('IbwJobeetBundle:Category:show.html.twig', array(
'category' => $category,
'last_page' => $last_page,
'previous_page' => $previous_page,
'current_page' => $page,
'next_page' => $next_page,
'total_jobs' => $total_jobs
));
}
Terakhir update templatenya
src/Ibw/JobeetBundle/Resources/views/Category/show.html.twig
{% extends 'IbwJobeetBundle::layout.html.twig' %}
{% block title %}
Jobs in the {{ category.name }} category
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('bundles/ibwjobeet/css/jobs.css') }}" type="text/css" media="all" />
{% endblock %}
{% block content %}
<div class="category">
<div class="feed">
<a href="">Feed
</a>
</div>
<h1>{{ category.name }}</h1>
</div>
{{ include ('IbwJobeetBundle:Job:list.html.twig', {'jobs': category.activejobs}) }}
{% if last_page > 1 %}
<div class="pagination">
<a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug, 'page': 1 }) }}">
<img src="{{ asset('bundles/ibwjobeet/images/first.png') }}" alt="First page" title="First page" />
</a>
<a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug, 'page': previous_page }) }}">
<img src="{{ asset('bundles/ibwjobeet/images/previous.png') }}" alt="Previous page" title="Previous page" />
</a>
{% for page in 1..last_page %}
{% if page == current_page %}
{{ page }}
{% else %}
<a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug, 'page': page }) }}">{{ page }}</a>
{% endif %}
{% endfor %}
<a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug, 'page': next_page }) }}">
<img src="{{ asset('bundles/ibwjobeet/images/next.png') }}" alt="Next page" title="Next page" />
</a>
<a href="{{ path('IbwJobeetBundle_category', { 'slug': category.slug, 'page': last_page }) }}">
<img src="{{ asset('bundles/ibwjobeet/images/last.png') }}" alt="Last page" title="Last page" />
</a>
</div>
{% endif %}
<div class="pagination_desc">
<strong>{{ total_jobs }}</strong> jobs in this category
{% if last_page > 1 %}
- page <strong>{{ current_page }}/{{ last_page }}</strong>
{% endif %}
</div>
{% endblock %}
Mmmm... ada masalah? yap semoga tidak kita lanjut lagi besok bye!
Mantap mas. tutorial nya mudah di pahami untuk pemula symfony sebagi best pratice.
ReplyDeletelanjutkan :D