Symfony2.7 : Twig render controller() ignore my parameters - symfony

I have a trouble with a symfony exeption and some parameter i try to get. I have absolutely no idea why i get this exception after thousands checks of my code and on the internet.
The exception is :
An exception has been thrown during the rendering of a template ("Some mandatory parameters are missing ("slug") to generate a URL for route "blogcomment_create".") in #Blog\Default\Blog\singlePost.html.twig at line 29.
The route configuration :
blogcomment_create:
path: /{slug}/comment/create/
defaults: { _controller: "BlogBundle:Comment:create" }
requirements: { methods: post }
My code in my twig template to import my controller:
<footer>
{{ render(controller('BlogBundle:Comment:create', {
'slug': Post.slugname
})) }}
</footer>
My Action declaration :
public function createAction(Request $request, $slug = null)
{
//...
}
I starting to get mad with this exception, i have no clues why i get her and i realy need a good pair of eyes.
i try tons of exemples :
How to insert a Controller in Twig with "render" in Symfony 2.2?
symfony2 - twig - how to render a twig template from inside a twig template
Change template via parameter when render a controller action?
...
Here a dump of the fonction :
object(Symfony\Component\HttpKernel\Controller\ControllerReference)[992]
public 'controller' =>
string 'BlogBundle:Comment:create' (length=31)
public 'attributes' =>
array (size=1)
'slug' => string 'article-de-test-yolowowo' (length=24)
public 'query' =>
array (size=0)
empty

Ok i finaly get it !
The problem was not at all in my twig template but in my controller. I have a fonction to generate my form in this controller. I call her in my action :
private function createCreateForm(Comment $entity, $slug)
{
$form = $this->createForm(new CommentType(), $entity, array(
'action' => $this->generateUrl('blogcomment_create', array('slug' => $slug)),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
In this function i forgot to pass parameters in this fonction :
$this->generateUrl()
I really need to sleep sooner when i get that kind of problems >.>
I hope my problem will help other peoples in the future.

Related

Object of type Doctrine\Bundle\DoctrineBundle\Registry is not callable

I've got an error when trying to use doctrine.
Here is my error:
Object of type Doctrine\Bundle\DoctrineBundle\Registry is not callable
And my controller:
public function index(ManagerRegistry $doctrine): Response
{
$articles = $doctrine()->getRepository(Article::class)->findAll();
return $this->render('blog/index.html.twig', [
'controller_name' => 'BlogController',
'articles' => $articles,
]);
}
Can someone help me ? thanks :)
This works on Symfony 5.4:
use Doctrine\Persistence\ManagerRegistry;
//...
public function index(ManagerRegistry $doctrine): Response
{
$articles = $doctrine->getRepository(Article::class)->findAll();
return $this->render('blog/index.html.twig', [
'controller_name' => 'BlogController',
'articles' => $articles
]);
}
You can learn more in Symfony docs and Doctrine ORM docs.

Symfony 4.3 Multiple ChoiceType can only add values and not remove when using PATCH

Given form:
...
$builder
->add('testArray', ChoiceType::class, [
'choices' => ['ROLE_ADMIN' => 'ROLE_ADMIN', 'ROLE_USER' => 'ROLE_USER'],
'expanded' => true,
'multiple' => true
])
;
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => TestEntity::class,
'csrf_protection' => false,
'method' => 'PATCH'
]);
}
...
And entity:
...
/**
* #ORM\Column(type="simple_array", nullable=true)
*/
private $testArray = [];
public function getTestArray(): ?array
{
return $this->testArray;
}
public function setTestArray(?array $testArray): self
{
$this->testArray = $testArray;
return $this;
}
...
When submitting the form by adding values... everything works fine.
But when removing values... the values are not removed, and the setter is never called.
Strangely, switching the form method to GET fixes this.
What's going on?
--- edit ---
Here's a controller that reproduces this issue:
/**
* #Route("/{id}/edit", name="test_entity_edit", methods={"GET","POST","PATCH"})
*/
public function edit(Request $request, TestEntity $testEntity): Response
{
$form = $this->createForm(TestEntityType::class, $testEntity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('test_entity_index', [
'id' => $testEntity->getId(),
]);
}
return $this->render('test_entity/edit.html.twig', [
'test_entity' => $testEntity,
'form' => $form->createView(),
]);
}
---- edit ----
Testing using POST this works perfectly. But using PATCH it fails. All other fields update. And adding to the array works. But removing from the array doesn't. I've added the relevant PATCH code above and updated the title to clarify the question.
I'm not sure this it the entirety of your problem, but when you handle your form submit, you are not persisting the entity.
$this-getDoctrine()->getManager()->flush();
is normally written
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($testEntity);
$entityManager->flush();
See https://symfony.com/doc/current/best_practices/forms.html#handling-form-submits
It appears that PATCH is ambiguous when it comes to arrays and there are various ways of handling the sent data.
Symfony will detect a PATCH and not $clearMissing when calling submit() (not empty the fields in the entity that are missing from the data). When it comes to an array, this is ambigious.
To deal with this I've moved away from using PATCH to update a user entity and moved to this solution Symfony2: Edit user without having password
Which essentially uses two different FormType's one to create the user, and another to edit it. Each form type uses a different validation group. Allowing to edit a user without submitting or clearing the users password.

twig how to render a twig template as a variable

I'm trying to render twig template as variable, using symfony. I have a 'sendAction' Controller, which uses the mailgun API to send emails to one or more mailing lists. Here is my code for the Controller:
public function sendAction(Request $request, Newsletter $newsletter, MailgunManager $mailgunManager) {
$form = $this->createForm(SendForm::class);
$form->handleRequest($request);
$formData = array();
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$mailingLists = $formData['mailingLists'];
foreach ($mailingLists as $list) {
$mailgunManager->sendMail($list->getAddress(), $newsletter->getSubject(), 'test', $newsletter->getHtmlContent());
return $this->render('webapp/newsletter/sent.html.twig');
}
}
return $this->render('webapp/newsletter/send.html.twig', array(
'newsletter' => $newsletter,
'form' => $form->createView()
));
}
}
And here's my sendMail (mailgun) function:
public function sendMail($mailingList, $subject, $textBody, $htmlBody) {
$mgClient = new Mailgun($this::APIKEY);
# Make the call to the client.
$mgClient->sendMessage($this::DOMAIN, array(
'from' => $this::SENDER,
'to' => $mailingList,
'subject' => $subject,
'text' => $textBody,
'html' => $htmlBody
));
}
I want my ' $newsletter->getHtmlContent()' to render template called 'newsletter.twig.html'. can anyone help me or point me in the right direction as to what I can do or Where I can find Tutorials or notes on what I am trying to do. the symfony documentation is quite vague.
You can use getContent() chained to your render function.
return $this->render('webapp/newsletter/send.html.twig', array(
'newsletter' => $newsletter,
'form' => $form->createView()
))->getContent();
Simply inject an instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface into your action, and you’ll be able to use Twig directly:
public function sendAction(Request $request, EngineInterface $tplEngine, Newsletter $newsletter, MailgunManager $mailgunManager)
{
// ... other code
$html = $tplEngine->render('webapp/newsletter/send.html.twig', [
'newsletter' => $newsletter,
'form' => $form->createView()
]);
}
Note that $this->render() (in the controller action) will return an instance of Symfony\Component\HttpFoundation\Response, while $tplEngine->render() returns a HTML string.

JMS Serializer event is not working

I am sure it is a small error but I cannot find it.
I am trying to follow the official doc and implement an event listener on the pre_serialize event.
My service declaration:
<service id="app.question_serializer_subscriber" class="AppBundle\Serializer\QuestionSerializerSubscriber">
<tag name="jms_serializer.event_subscriber"/>
</service>
My subscriber:
<?php
namespace AppBundle\Serializer;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
class QuestionSerializerSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.pre_serialize',
'method' => 'onPreSerialize',
)
);
}
public function onPreSerialize(ObjectEvent $event)
{
die('in event');
}
}
And my controller:
$question = $repo->findLastVersionByQuestionId((int) $questionId);
$serializer = SerializerBuilder::create()->build();
$context = new SerializationContext();
return new JsonResponse(json_decode(
$serializer->serialize(
$question,
'json',
$context
),
true
));
When I access the route my entity Question is serialized and displayed, but why does the die('in event'); is not displayed ?
Maybe it has a relation with the fact that my object is a Doctrine entity (issue 666 or PR 677 )
I finally find the issue. The problem is
$serializer = SerializerBuilder::create()->build();
This does not work but this does:
$serializer = $this->get('jms_serializer');
Try adding the class attribute, as example:
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.pre_serialize',
'class' => 'FQCN_class_name',
'method' => 'onPreSerialize',
)
);
}
Another difference regarding the doc is in the argument of the class method: you should use PreSerializeEvent instead of ObjectEvent:
So like this:
public function onPreSerialize(PreSerializeEvent $event)
{
// ...
}
Check your service is correctly load from the container as example with the console command:
php app/console debug:container --tag=jms_serializer.event_subscriber
Hope this help

Getting Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException

I'm sending a PUT request that handles input data and updates a record, but I get the above response. The problem doesn't seem to be the route, however, because if I do dd($user) after the $user = User::whereId($id)->firstOrFail(); line, I get the object returned correctly.
Yet, when it comes time to validate it, it throws this error.
# routes
Route::resource('users', 'UsersController', ['only' => ['index', 'show', 'update']]);
# api call
PUT /users/2
# controller
public function update($id)
{
$user = User::whereId($id)->firstOrFail();
$input = Input::all();
$this->userForm->validate($input);
$user->fill($input)->save();
return $user->toJson();
}
# userForm class
<?php namespace Olp\Forms;
use Laracasts\Validation\FormValidator;
class UserForm extends FormValidator {
protected $rules = [
'email' => 'required|email|unique:users',
'password' => 'required',
'password_confirmation' => 'required|same:password',
'firstname' => 'required',
'lastname' => 'required',
'schoolname' => 'required',
'address1' => 'required',
'address2' => 'required',
'postcode' => 'required',
'city' => 'required'
];
}
and in my UserController:
use Olp\Forms\UserForm;
class UsersController extends \BaseController {
function __construct(UserForm $userForm)
{
$this->userForm = $userForm;
}
I'm not a Laravel guy, but a quick check on their documentation indicates that Resource Controllers support PUT in addition to other HTTP verbs.
I was not able to figure out how to add HTTP verb support to an arbitrary action, but this indicates that you can name a controller action prefixed with the verb it responds to
public function putUpdate($id)

Resources