Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UrGuardian4ngel/a2d3bf9341492cce1b08 to your computer and use it in GitHub Desktop.
Save UrGuardian4ngel/a2d3bf9341492cce1b08 to your computer and use it in GitHub Desktop.
Little demonstration of Symfony2 ParamConverter on additional question on StackOverflow http://stackoverflow.com/questions/17634972/passing-objects-through-controllers-in-symfony2/17635505
<?php
namespace MusicM\SongBundle\Controller;
use MusicM\SongBundle\Entity\Track;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class SongController extends Controller
{
/**
* Load the track, based on the 'slug' field.
* The mapping from slug to entity is automatically done by Symfony2.
*
* The column to use ('slug'), is defined in the parameters as cmusic_m.song.slug_field
* in services.yml
*
* @see \MusicM\SongBundle\ParamConverter\EntitySlugParamConverter
*
* @param Track $track
* @return \Symfony\Component\HttpFoundation\Response
*/
public function addTrackToSongAction(Track $track)
{
return $this->render('MusicMSongBundle:Song:index.html.twig', array(
'track' => $track,
));
}
/**
* Load the track manually by slug.
*
* @param string $track The slug of the track
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* @return \Symfony\Component\HttpFoundation\Response
*/
public function addTrackToSongManualAction($track)
{
$entity = $this->getDoctrine()
->getRepository('MusicMSongBundle:Track')
->findOneBySlug($track);
if (!$entity) {
throw new NotFoundHttpException('Track not found.');
}
return $this->render(
'MusicMSongBundle:Song:index.html.twig',
array(
'track' => $entity,
)
);
}
public function trackListAction()
{
$tracks = $this->getDoctrine()
->getRepository('MusicMSongBundle:Track')
->findAll();
return $this->render('MusicMSongBundle:Song:track_list.html.twig', array(
'tracks' => $tracks,
));
}
}
<?php
namespace MusicM\SongBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('music_m_song');
// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.
return $treeBuilder;
}
}
<?php
namespace MusicM\SongBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class MusicMSongExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
<?php
namespace MusicM\SongBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\Table(name="track")
*/
class Track
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="slug", type="string")
*/
private $slug;
/**
* @var string
*
* @ORM\Column(name="title", type="string")
*/
private $title;
/**
* @param int $id
*/
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @param string $slug
*/
public function setSlug($slug)
{
$this->slug = $slug;
}
/**
* @return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
}
<?php
namespace MusicM\SongBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class MusicMSongBundle extends Bundle
{
}
<?php
namespace MusicM\SongBundle\ParamConverter;
use Doctrine\Common\Persistence\ObjectManager;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class EntitySlugParamConverter implements ParamConverterInterface
{
protected $manager;
protected $column;
function __construct(ObjectManager $manager, $column = 'machine_name')
{
$this->manager = $manager;
$this->column = $column;
}
public function apply(Request $request, ParamConverter $configuration)
{
$name = $configuration->getName();
$class = $configuration->getClass();
if (null === $request->attributes->get($name, false)) {
$configuration->setIsOptional(true);
}
$entity = $this->findByIdentifierColumn($class, $request, $configuration);
if (null === $entity && false === $configuration->isOptional()) {
throw new NotFoundHttpException(sprintf('%s object not found.', $class));
}
$request->attributes->set($name, $entity);
return $entity;
}
public function supports(ParamConverter $configuration)
{
$metadata = $this->manager->getClassMetadata($configuration->getClass());
$hasIdentifierColumn = $metadata->hasField($this->column);
return $hasIdentifierColumn;
}
protected function findByIdentifierColumn($class, Request $request, ParamConverter $configuration)
{
$name = $configuration->getName();
$value = $request->attributes->get($name, false);
if (false === $value) {
return null;
}
$repository = $this->manager->getRepository($class);
$object = $repository->findOneBy(array(
$this->column => $value,
));
return $object;
}
}
MusicMBundle_Song_addTrackToSong:
pattern: /tracks/add-to-song/{track}
defaults: { _controller: MusicMSongBundle:Song:addTrackToSong }
MusicMBundle_Song_addTrackToSongManual:
pattern: /tracks/add-to-song/manual/{track}
defaults: { _controller: MusicMSongBundle:Song:addTrackToSongManual }
MusicMBundle_Song_trackList:
pattern: /tracks/list
defaults: { _controller: MusicMSongBundle:Song:trackList }
parameters:
music_m_song.param_converter.entity_slug_param_converter.class: MusicM\SongBundle\ParamConverter\EntitySlugParamConverter
music_m.song.slug_field: slug
services:
music_m_song.param_converter.entity_slug_param_converter:
class: %music_m_song.param_converter.entity_slug_param_converter.class%
arguments: [@doctrine.orm.entity_manager, %music_m.song.slug_field%]
tags:
- { name: request.param_converter, priority: 1, converter: entity_slug }
<h1>Track details</h1>
<dl>
<dt>Id</dt>
<dd>{{ track.id }}</dd>
<dt>Title</dt>
<dd>{{ track.title }}</dd>
</dl>
<a href="{{ path('MusicMBundle_Song_trackList') }}">&larr; Back to track list</a>
<h1>Track list</h1>
<table>
<tr>
<th>Id</th>
<th>Slug</th>
<th>Title</th>
<th>Details action</th>
</tr>
{% for track in tracks %}
<tr>
<td>{{ track.id }}</td>
<td>{{ track.slug }}</td>
<td>{{ track.title }}</td>
<td>
<a href="{{ path('MusicMBundle_Song_addTrackToSong', { 'track': track.slug }) }}">auto</a>
<a href="{{ path('MusicMBundle_Song_addTrackToSongManual', { 'track': track.slug } ) }}">manual</a>
</td>
</tr>
{% endfor %}
</table>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment