Bejegyzés URL-átírása Symfonyban

Antal Áron • 2015. október 25.

Ha egy olyan linket látunk, ami így néz ki: /2015/10/bejegyzes-url-atirasa-symfonyban.html, már rögtön elmondja nekünk azt, hogy ezt a bejegyzést, 2015 októberében írták, és körülbelül mi a címe.

Az automatikus ParamConverterrel könnyen be tudjuk kötni a Post entityt a controllerbe, de kiegészülhet esetleg a bejegyzés dátumával?

Induljunk ki egy Post entityből.

<?php

namespace AntalAron\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="PostRepository")
 */
class Post
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     */
    private $title;

    /**
     * @ORM\Column(type="string")
     */
    private $slug;

    /**
     * @ORM\Column(type="datetime")
     */
    private $created;

    /**
     * @ORM\Column(type="text")
     */
    private $text;

    // ...
}

A controllerben összekötjük a Post entityt a repositoryjában levő eljárással a ParamConverteren keresztül:

<?php

namespace AntalAron\BlogBundle\Controller;

use AntalAron\BlogBundle\Entity\Post;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class PostController extends Controller
{
    /**
     * @Route("/{year}/{month}/{slug}.html", requirements={
     *     "year": "\d+",
     *     "month": "\d+"
     * })
     * @ParamConverter("post", class="AntalAronBlogBundle:Post", options={
     *     "repository_method" = "loadPostByYearMonthSlug",
     *     "mapping": {
     *         "year": "year",
     *         "month": "month",
     *         "slug": "slug"
     *     },
     *     "map_method_signature" = true
     * })
     */
    public function postAction(Post $post)
    {
        return $this->render('post.html.twig', ['post' => $post]);
    }
}

És a repository:

<?php

namespace AntalAron\BlogBundle\Entity;

use Doctrine\ORM\EntityRepository;

class PostRepository extends EntityRepository
{
    public function loadPostByYearMonthSlug($year, $month, $slug)
    {
        $startTime = new \DateTime(sprintf('%s-%s-01', $year, $month));
        $endTime = clone $startTime;
        $endTime->add(new \DateInterval('P1M'));

        $post = $this->createQueryBuilder('p')
            ->where('p.slug = :slug')
            ->andWhere('p.created BETWEEN :start_date AND :end_date')
            ->andWhere('p.created < CURRENT_TIMESTAMP()')
            ->orderBy('p.created', 'ASC')
            ->setParameter('slug', $slug)
            ->setParameter('start_date', $startTime->format('Y-m-d'))
            ->setParameter('end_date', $endTime->format('Y-m-d'))
            ->getQuery()
            ->getOneOrNullResult();

        return $post;
    }
}

És kész is! Ha találna is a kért sluggal bejegyzést, de az máskor keletkezett, mint ami az URL-ben van, nem adja vissza, és 404-et dob.