The full error I am getting is this one.
An exception has been thrown during the rendering of a template ("Some mandatory parameters are missing ("id") to generate a URL for route "FooBlogBundle_articles".") in "FooBlogBundle:Article:articles.html.twig".
This is the controller, that handles the action:
public function articlesAction($id)
{
$em = $this->getDoctrine()->getManager();
$blog = $em->getRepository('FooBlogBundle:Blog')->find($id);
if(!$em){
throw $this->createNotFoundException('Unable to find blog posti');
}
return $this->render('FooBlogBundle:Article:articles.html.twig', ['blog'=>$blog]);
}
}
and the routing
FlickBlogBundle_articles:
pattern: /foo/{id}
defaults: { _controller: FooBlogBundle:Article:articles }
requirements:
_method: GET
id: \d+
Twig and database, are completely normal, no type or problems. But this error is kind of hard to spot, where I have gone wrong.
EDIT: Including template:
{% extends 'FooBlogBundle::layout.html.twig' %}
{% block body %}
{{ blog.title }}<br/>
{{ blog.author }}<br/>
{{ blog.blog }}<br/>
{{ blog.tags }}<br/>
{{ blog.comments }}
{% endblock %}
The above template is located in views/article/ it extends another templates found at views/
whic is just
{% extends 'FooBlogBundle::layout.html.twig' %}
In FooBlogBundle:Article:articles.html.twig template you have something like {{ path(FlickBlogBundle_articles) }} (can not tell exactly because I do not see a template). This route requires additional parameter id. So change it to {{ path(FlickBlogBundle_articles, {'id':article.id}) }}
I got the same error and in my case I forgot to set public Getters & Setters for my private foreign Key:
/**
* #var Provider
*
* #ORM\ManyToOne(targetEntity="Provider")
* #ORM\JoinColumn(name="fk_provider", referencedColumnName="id", nullable=true)
*/
private $fkProvider;
And
/**
* #return Provider
*/
public function getFkProvider()
{
return $this->fkProvider;
}
/**
* #param Provider $fkProvider
*/
public function setFkProvider($fkProvider)
{
$this->fkProvider = $fkProvider;
}
Related
I am displaying some entity relations in a Sonata Admin list view. The problem: When no relation exists (what is legal in my case) the table cell stays empty:
What I want is basically this:
I tried to overwrite the default template (base_list_field.html.twig):
$listMapper
->add(
'example',
null,
array(
'template' => 'AppBundle:Admin:listItemWithFallback.html.twig'
)
)
;
But even when I only extend the default template, all links for existing references stop working. Also I cannot figure out where to add my fallback. My AppBundle:Admin:listItemWithFallback.html.twig looks like this:
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
With this result:
Even when I copy the whole code from base_list_field.html.twig into my own template, the links stop to work.
So: How can I add a fallback label without overwriting the whole default templates? I want to modify as less of the base templates as possible.
Edit:
This is a workaround using a kernel.event_listener, hope there is a nicer way to achieve this:
services.yml:
services:
empty_cells.listener:
class: AppBundle\Listener\EmptyAdminTableCellListener
arguments:
- '#translator'
tags:
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
EmptyAdminTableCellListener.php:
namespace AppBundle\Listener;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class EmptyAdminTableCellListener
{
/**
* #var TranslatorInterface
*/
protected $translator;
/**
* #param TranslatorInterface $translator
*/
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
/**
* #param FilterResponseEvent $event
*/
public function onKernelResponse(FilterResponseEvent $event)
{
$request = $event->getRequest();
$path = $request->getPathInfo();
if (strpos($path, '/admin/') !== false) {
$emptyText = $this->translator->trans('Not set', [], 'admin');
$response = $event->getResponse();
$content = $response->getContent();
$content = preg_replace(
';(<td[^>]*?>)[\s]+?(</td>);is',
sprintf('$1%s$2', $emptyText),
$content
);
$response->setContent($content);
}
}
}
Here is how to recreate the working links in your custom template:
{{ value }}
with the fallback and all:
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
{% if object.species %}
{{ value }}
{% else %}
{{ 'Your fallback text'|trans() }}
{% endif %}
{% endblock %}
Hope that helps
I'd like to get prefix route in Controller or in Twig.
/**
* #Route("/blog",name="root_post")
*/
class PostController extends Controller
{
/**
* #Route("/{id}",name="post")
*/
public function showAction($id)
{
}
}
I don't know if i can do
name="root_post"
Then I'd like to get this root like (in controller)
$this->get(request')->attributes->get('_route')
or (in Twig)
app.request.attributes.get('_route')
I don't know if I can
To check if your currently routed to the route you want, you can do the following in twig:
{% if app.request.get('_route') == 'root_post' %}
<p>Routed to root_post!</p>
{% endif %}
I have a problem to get a object from a controller called by the render controller method.
This is my Entity with the self OneToOne relation :
class Family
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Family")
* #ORM\JoinColumn(name="brother_id", referencedColumnName="id")
**/
private $brother;
/**
* #ORM\Column(type="string", length=100)
*/
private $label;
}
This is my action:
/**
* #Template()
*/
public function testAction()
{
$em = $this->getDoctrine()->getManager();
$brothers = $em->getRepository('FifaAdminBundle:Family')->findAll();
return array(
'brothers' => $brothers,
);
}
My view
{% for brother in brothers %}
{{ brother.id }} - {{ brother.label }}
<hr />
{% render controller('AdminBundle:Test:show', {'brother': brother}) %}
<hr />
{{ render(controller('AdminBundle:Test:show', { 'brother': brother })) }}
<hr />
{% endfor %}
My other controller
public function showAction($brother)
{
if (is_object($brother))
{
return new \Symfony\Component\HttpFoundation\Response('OK');
}
else
{
var_dump($brother);
return new \Symfony\Component\HttpFoundation\Response('KO');
}
}
The first element isgood.
But if it has a brother_id, this brother in not load by the showAction.
It gives me this:
array(1) { ["__isInitialized__"]=> string(1) "1" }
Please help me.
You probably want to use the #ParamConverter annotation in your case.
Your controller would go as follow:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Admin\Bundle\Entity\Family;
/**
* #Route("/show/{id}")
* #ParamConverter("family", class="AdminBundle:Family")
*/
public function showAction(Family $brother)
{
//Do your stuff
}
And the view:
{% for brother in brothers %}
{{ brother.id }} - {{ brother.label }}
<hr />
{{ render(controller('AdminBundle:Test:show', { 'brother': brother.id })) }}
<hr />
{% endfor %}
Note that if no Family object is found, a 404 Response is generated. So you don't need to check if $brother is an object or not in your controller.
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
Thank you cheesemacfly
Indeed, it's work with the #ParamConverter
But it is wird because if I remove the OneToOne relation, it works without #ParamConverter
In the Symfony 2 template documentation it recommends embedding a controller within a template via the render url method and provides the following example:
<div id="sidebar">
{% render url('latest_articles', { 'max': 3 }) %}
</div>
This is fine, however is it possible to make this route only accessible to templates to prevent a user from accessing the url directly, and if so - what is the recommended way of doing it?
You can define all you rendered controller routes pattern as "/_render/unique_name" or prefix them with "_render" and use access_control to secure the routes from outside world:
# app/config/security.yml
security:
access_control:
- { path: ^/_render, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
- { path: ^/_render, roles: ROLE_NO_ACCESS }
You can do this by not defining a route for this method.
class TestController extends Controller
{
/**
* #Route("/", name="index")
* #Template
*/
public function indexAction()
{
return array();
}
/**
* #Template
*/
public function testAction()
{
return array(
'text' => 'This text is being included'
);
}
}
And then in the template
{% extends "::base.html.twig" %}
{% block body %}
<h1>{{ hello }}</h1>
{% render "TestBundle:Test:test" %}
{% endblock %}
In my Symfony2 bundle, I need to check if a function (an extension) is defined. More specifically, if the KnpMenuBundle is installed I use that one in my bundle, otherwise I will render the plugin myself.
I tried this, but this of course doesn't work:
{% if knp_menu_render() is defined %}
{# do something #}
{% else %}
{# do something else #}
{% endif %}
Is there a test/function/filter to check if a function is defined? If not, is there another way to check if the KnpMenuBundle is installed in the application?
Write a function in a Twig Extension which would check if bundle is enabled.
List of registered bundles is stored in the kernel.bundles parameter.
Twig extensions are registered as services. This means you can pass any other service or a parameter to your extension:
<services>
<service id="acme.twig.acme_extension" class="Acme\DemoBundle\Twig\AcmeExtension">
<argument>%kernel.bundles%</argument>
<tag name="twig.extension" />
</service>
</services>
In your Twig function or filter you can later use a service or a parameter which you've passed to an extension.
I had the same need, so I created my own extension:
class IsLoadedExtension extends \Twig_Extension
{
/**
* #var \Twig_Environment
*/
protected $environment;
public function initRuntime(\Twig_Environment $environment)
{
$this->environment = $environment;
}
/**
* Returns a list of functions to add to the existing list.
*
* #return array An array of functions
*/
public function getTests()
{
return array(
new \Twig_SimpleTest('loaded', [$this, 'hasExtension']),
);
}
/**
* #param string $name
* #return boolean
*/
function hasExtension($name)
{
return $this->environment->hasExtension($name);
}
/**
* Returns the name of the extension.
*
* #return string The extension name
*/
public function getName()
{
return 'amce_extension_exists';
}
}
Then registered it in Twig:
services:
acme_somebundle.twig.is_loaded_extension:
class: Acme\SomeBundle\Twig\IsLoadedExtension
tags: [{ name: twig.extension }]
And used it in twig template like this:
{% if 'knp_menu' is loaded %}
{# use knp menu #}
{% endif %}