How to generate right route in twig with dynamic sub-domain? - symfony

I have a multi-tenant APP based on sub-domain that's working properly but I have an issue with generated link in Twig templates.
All the generated link are on the default sub-domain and not the current one
routes.yaml
app_customer:
resource: '../src/Controller/Customer/'
host: "{subdomain}.domain.com"
defaults:
subdomain: tenant1
requirements:
subdomain: tenant1|tenant2
SecurityController.php
class SecurityController extends AbstractController
{
/**
* #Route("/login", name="app_login", methods={"GET","POST"})
*/
public function login(AuthenticationUtils $authenticationUtils)
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
]);
}
}
login.html.twig
<form action="{{ path('app_login') }}" method="post">...</form>
will always generate https://tenant1.domain.com/login however the current url is tenant2.domain.com

I believe it is always generating https://tenant1.domain.com/login because you have "tenant1" set as the default value for subdomain and you do not pass a different value when you call path()
Try this :
{% set currsubdomain = app.request.getHttpHost()|split('.')|first %}
<form action="{{ path('app_login', {subdomain: currsubdomain }) }}" method="post">...</form>
Or maybe just pass the whole host:
<form action="{{ path('app_login', {host: app.request.getHttpHost}) }}" method="post">...</form>

Related

symfony form handling subcontroller

I have a working contactform, which allows the user to send a e-mail to me and additionally gets a confirmation mail.
I would like to add a confirmation message to the page, so the user is sure the message was sent.
default.html.twig
<div>
{% include 'includes/overview.html.twig' %}
{% include 'includes/service.html.twig' %}
{% include 'includes/offer.html.twig' %}
{% include 'includes/aboutus.html.twig' %}
{% include 'Advanced/contactForm.html.twig' %}
</div>
contactForm.html.twig
<div class="col-lg-6 col-md-6 contactfrom nopadding">
{# request has to go further to the contactCormController -> {'request' : app.request} #}
{{ render(controller('AppBundle\\Controller\\ContactFormController::contactForm', {'request' : app.request})) }}
</div>
ContactController.php
public function contactForm(Request $request, \Swift_Mailer $mailer)
{
$contactForm = new ContactForm();
$form = $this->createForm(ContactFormType::class, $contactForm);
$form->handleRequest($request);
if ($form->isSubmitted()){ //&& $form->isValid()
$message = (new \Swift_Message)
->setFrom($contactForm->getEmail())
->setTo('mail')
->setSubject("Kontaktformular - ". $contactForm->getFirstname() ." ". $contactForm->getLastname())
->setBody($contactForm->getMessage())
;
if ($contactForm->getHonigtopfRoboter() == "") {
try {
// Sending message to the Host
// Sending confirmation message to the user
$mailer->send($message);
$this->confirmationMail($mailer, $contactForm->getEmail());
// empty ContactForm
unset($contactForm);
unset($form);
$contactForm = new ContactForm();
$form = $this->createForm(ContactFormType::class, $contactForm);
// add succes flashmessage
// $this->addFlash('success', 'message');
}
catch (\Swift_TransportException $Ste){
//TODO: Exception Handling
//echo $Ste->getMessage();
// add error flashmessage
// $this->addFlash('danger', 'message');
}
}
else{
}
}
$contactFormEntity = $form->getData();
return $this->render('form/contactForm.html.twig',
['contactform' => $form->createView()
]);
}
The most common solution I found was to use "flash message", sadly flash messages only work, if you redirect to a new page. Due to the fact, that my contact form stays on the same page it does not work.
My form is embedded and rendered in a sub-html.twig page, so I have the problem to get the information to my ContentController.php and further to the page.
I am really stuck and don't really know the best workflow for this scenario. How do i handle the submit and:
Success -> empty contact form -> success message on page
Error -> leave contact form -> error message on page
Thanks for your help.
If your form is valid, you should redirect the user after the form submission
public function contactForm(Request $request, \Swift_Mailer $mailer)
{
$form = ...
if ($form->isSubmitted() && $form->isValid()) {
$message = ...
$mailer->send($message);
$this->addFlash('success', 'Wohoo, we got it!');
return $this->redirectToRoute('app_contact_form');
}
return $this->render('form/contactForm.html.twig', ['contactform' => $form->createView()]);
}
Doing this, you don't need to empty the form like you do and then re-create it. And as the user is redirected, he will see the flash message.
Also, always check if the form is valid !

Symfony Twig: send a set parameter with a form submit request

I have a form in my twig, i want that by clicking on its submit button, another parameter (that i've set in the twig) get sent to the same action that handles the form :
this is the variable i've set
{% set idprof = profil.id %}
I want to send it with the submit request : ( i know this code is false)
{{ form_widget(form.id),{'idprof': idprof} }}
and the action will look like this :
public function gestProfAction(Request $request, $idprof)
{
}
I'm sorry i know this is a stupid question, but I'm still new in symfony, I couldn't find a solution by myself.
Just pass it in the form start line
{{ form_start(form, {'action': path('idprof', { 'idprof': idprof })}) }}
Remember to add the annotation or yaml for the routing
/**
* #Route("/idprof/{idprof}", name="idprof")
*/
public function gestProfAction(Request $request, $idprof)
{
}
For reference:
http://symfony.com/doc/current/forms.html#rendering-the-form
http://symfony.com/doc/current/form/action_method.html
http://symfony.com/doc/current/templating.html#linking-to-pages

send in link id of username symfony2

want to send an email from my Symfony2 application, this email must contain a link of confirmation and when the user clicks on this link the state of a field in DB to change.
i have this in my controller:
$message = \Swift_Message::newInstance()
->setSubject('demande de conge ')
->setFrom($col->getEmailCollaborateur())
->setTo($form->get("emailcdp")->getData())
->setBody($this->render('AcmeBundle:Conge:demandeCongeNormal.html.twig', array('conge' => $conge, 'id'=> $this->getUser()->getId())))
;
$this->get('mailer')->send($message);
in the twig :
id de collab: {{ id }}
pour confirmer la demande :
{{ url('confirmer_conge' ,{'username': ' id '}) }}
but in the Email i have this :
http://local.symfony2.com/app_dev.php/confirm/?username=+id+
i want to get the id of user that send the message in another controller for update my DB
in my routing.yml:
confirmer_conge:
pattern: /confirm/{username}
defaults: { _controller: acmeBundle:Conge:confirme }
and in the controller i have this function:
public function confirmeAction()
{return $this->render('acmeBundle:Conge:confirmer.html.twig');
}
Remove the quotes from around id, it is a variable.
{{ url('confirmer_conge', {'username': id}) }}
As for accessing the ID in your controller it should work like this:
public function confirmeAction($username)
//...
}

symfony2 form is not displaying

I am learning symfony2 and i have created one form in controller which is as bellow.
the controller file as DefaultController.php
namespace Banner\TestBundle\Controller;
use Banner\TestBundle\Entity\Contact;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Banner\TestBundle\Entity\Task;
use Symfony\Components\HttpFoundation\Request;
class DefaultController extends Controller
{
public function newAction(Request $request)
{
echo "The controller is called ";
$task = new Task();
$task->setTask("Write a blog Post ");
$task->setDueDate(new DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task','text ')
->add('duedate','date')
->getForm();
return $this->render('BannerTestBundle:default:zoo.html.twig',array('form'=>$form->createView()));
}
}
my routing file is as below.
routing.yml
task_new:
pattern: /task/{request}
defaults: { _controller: BannerTestBundle:Default:new}
and the zoo.html.twig file is as bellow.
{% extends '::page.html.twig' %}
{% block title %}The Zoo{% endblock %}
{% block content %}
<form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit">
</form>
{% endblock %}
as i am passing the "task/GET" in my url it will shows the 'Request does not exist. error 500'.
what i basically want to do is when i pass the url the zoo.html.twig will be called. i want to display the form in zoo.html.twig.
You don't need to pass $request to your action and you don't need to put it in your route. The request object is available in global context. So
task_new:
pattern: /task-new
defaults: { _controller: BannerTestBundle:Default:new}
You can either leave it this way
public function newAction(Request $request)
or have
public function newAction()
and access request object like this
$request = $this->getRequest();
Your routing file is not properly indented so the yaml will not parse properly. Try:
task_new:
pattern: /task/{request}
defaults: { _controller: BannerTestBundle:Default:new}
Also:
It is probably a bad idea to override request that way
You don't appear to be doing anything with request in your controller

How to load a controller function and render it in a twig tag using Symfony2?

I am using Symfony2 and Twig. I have a function (below) in my controller that returns a specific text. Is it possible to call that function directly from my template and change the {{text}} in my template to whatever the function returns, possibly via Ajax?
Here's my function:
public function generateCode($url) {
$url = $_SERVER['SERVER_NAME'] . '/embed/' . $url;
$return = '<iframe>'.$url.'</iframe>';
return $return;
}
Another controller function calls the function above and renders my template:
public function getCodeAction($url) {
$text = $this->generateCode($url);
return $this->render('MyMyBundle:User:code.html.twig', array('text' => $text));
}
In my template I am using:
{{ text }}
to display the value.
In Symfony 2.2, this was changed.
The render tag signature and arguments changed.
Before:
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, { 'alt': BlogBundle:Post:error' } %}
After:
{% render controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
or
{{ render(controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error'}) }}
Note: The function is the preferred way.
See https://github.com/symfony/symfony/blob/2.2/UPGRADE-2.2.md
You can use ajax if you have dynamic data, but as far as I can see from your brief info, you can always execute that controller function directly from your view:
{% render "MyMyBundle:User:generateCode" with { 'url': 'your url here' } %}
More Information on this available at:
http://symfony.com/doc/2.0/quick_tour/the_view.html, under Embedding other Controllers
For the record, in new versions you need to use the absolute URL:
{{ render url('my_route_id', {'param': value}) }}
{{ render(controller("AcmeDemoBundle:Demo:topArticles", {'num': 10})) }}
In Silex I solved it like this:
{{ render(url('route_name', {'param': value})) }}
If you do not have the route name, URL can be used:
{{ render(app.request.baseUrl ~ '/some-path/' ~ value) }}
If using URL we should always concat the baseUrl.
Symfony 2.6+
in twig:
{{ render(controller('AppBundle:PropertySearch:featuredProperties', {'limit': 15})) }}
controller:
/**
* featuredPropertiesAction
*
* #param Request $request
* #param int $limit
*
* #return Response
*/
public function featuredPropertiesAction(Request $request, $limit)
{
$search = $this->resultsHelper->featuredSearch($limit);
return $this->render('HASearchBundle::featured_properties.html.twig', [
'search' => $search,
]);
}

Resources