I would separate logic in my controllers.
In newWebsiteAction() I display my form. Next, I send data from form to postWebsiteAction() method.
If validation fails, I would like to redirect to senWebsiteAction() and display errors. What I should add to my code to do it? Because now I dont see errors
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Website;
use AppBundle\Form\Type\WebsiteType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class WebsitesController extends Controller
{
/**
* #Route("/websites", name="websites")
*/
public function getWebsiteAction()
{
return $this->render('websites/index.html.twig');
}
/**
* #Route("/websites/new", name="websites.new")
*/
public function newWebsiteAction()
{
$website = new Website();
$form = $this->createForm(new WebsiteType(), $website);
return $this->render('websites/create.html.twig', array(
'form' => $form->createView()
));
}
/**
* #Route("/websites/post", name="websites.post", methods={"POST"})
*/
public function postWebsiteAction(Request $request)
{
$form = $this->createFormBuilder()->getForm();
$form->handleRequest($request);
if($form->isValid())
{
$website = $form->getData();
$website->setUser($this->getUser());
$em =$this->getDoctrine()->getManager();
$em->persist($website);
$em->flush();
return $this->redirectToRoute('websites');
}
return $this->redirectToRoute('websites.new');
}
}
Hmm. IMHO you doing it wrong.
First: Why you wan't to do it in single action? If you want some separation better move some logic to services. Because store logic in services is Symfony2 way. E.g. Persist and flush logic to some EntityManager service (abstract example).
Second (hint): How you will get $form errors in newWebsiteAction()?
Edit:
Here is how I usually doing that:
public function createAction(Request $request)
{
$post = new Post();
$form = $this->createForm('post', $post);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($post);
$em->flush();
return $this->redirect($this->generateUrl('show_post', ['slug_title' => $post->getSlugTitle()]));
}
return $this->render('GeekhubMainBundle:Post:create.html.twig', ['form' => $form->createView()]);
}
yes it looks like some logic will duplicated in different methods, but:
1) If method less than 20 lines all fine;
2) In your way you methods for handle form or create entity are not reusable;
Hope that will help :)
public function postWebsiteAction(Request $request)
{
$form = $this->createFormBuilder()->getForm();
$form->handleRequest($request);
if($form->isValid())
{
$website = $form->getData();
$website->setUser($this->getUser());
$em =$this->getDoctrine()->getManager();
$em->persist($website);
$em->flush();
return $this->redirectToRoute('websites');
} else {
$this->generateUrl('\your_defined_route');
return $this->redirect($url);
}
return $this->redirectToRoute('websites.new');
}
check out the else after $form is valid.
Related
I get the error Controller not found: service "AppBundle / Controller / TestController.php" does not exist
but i don't know how to debug it. Can someone please help me !?
Is it possible that the error comes from the routing or it is something else !?
I just want to clarify that I use Symfony 3.4.
Here is the extract from the TestController.php code
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Task;
use AppBundle\Form\TaskType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("test/form-test")
*/
class TestController extends Controller
{
/**
* #Route("/", name="test")
*/
public function newAction(Request $request)
{
// creates a task and gives it some dummy data for this example
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->get('form.factory')->createNamed('addTask', TaskType::class, $task);
$form->handleRequest($request);
$validator = $this->get('validator');
$errors = $validator->validate($form);
if (count($editErrors) > 0) {
$errorsString = (string)$editErrors;
return new Response($errorsString);
}
echo('------------------------------------------------------------------------' . $form->isSubmitted() . ' && ' . $form->isValid());
if ($form->isSubmitted() && $form->isValid()) {
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$task = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Task is a Doctrine entity, save it!
// $entityManager = $this->getDoctrine()->getManager();
// $entityManager->persist($task);
// $entityManager->flush();
return new Response('<h1>-----------------------------------------------------------------------------------OK</h1>');
}
return $this->render('default/index.html.twig', [
'form' => $form->createView(),
'errors' => $errors,
]);
}
}
thank you in advance
I have problem when trying to dump some values, but issue is that when I use dump, it don't show any error message and don't dump any value. I have installed symfony/var-dumper.
Source code
<?php
namespace App\Controller;
use App\Form\UserType;
use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\VarDumper\VarDumper;
class RegistrationController extends Controller
{
/**
* #Route("/register", name="user_registration")
*/
public function registerAction(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
dump($user);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('number', array('slug' => 1500, 'dump' => $user));
} else {
return $this->render(
'registration/register.html.twig',
array('form' => $form->createView())
);
}
}
}
Add exit; after dump() or check the debug tab in profiler.
It is not visible because you have a redirect response.
If you are using the rest of the framework (as appears to be from the use of Controller), you'll find it linked from the debug-toolbar. However, as you are doing a redirect, the page that you end up on isn't the same request as the dump was made.
If you go into the debug profiler, and click the 'Last 10' button (near the top-left), you will see the previous pages. It's very likely that the 2nd one down will have the 'dump' section linked from the left hand column, and you'll be able to check the output from there.
Hello i saw a lot of tutorials and still dont know how can i make custom functions in my already done repository.
this is content of my CommentController:
public function newAction(Request $request, $productId)
{
$comment = new Comment();
$form = $this->formFactory->create(CommentForm::class, $comment);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->get('doctrine')->getManager();
/** #var Product $product */
$product = $em->getRepository(Product::class)->find($productId);
$comment->setAuthor($this->tokenStorsge->getToken()->getUser());
$comment->setProduct($product);
$comment->setContent($form->get('content')->getData());
$this->em->persist($comment);
$this->em->flush();
}
return $this->render(':form:comment.html.twig', array(
'form' => $form->createView(),
));
}
and i just want to make some function to make controller more beautiful any ideas? if you give me and example how can i insert my data into database via custom repository function. I know how to make custom query thats all. Every help/idea is very helpfull!
From here
Doctrine 2 ORM does not support INSERT via DQL or the DQL query builder. For a complete syntax, check the EBNF of DQL.
You can add more abstractions if you want your controller to look slightly more beautiful, off the top of my head (effective in Symfony 2.8):
BaseController.php:
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
abstract class BaseController extends Controller
{
/**
* #return ProductRepository
*/
protected function getProductRepo()
{
return $this->get('doctrine.orm.entity_manager')->getRepository(Product::class);
}
}
CommentController.php:
Use native controller functions to create a form and get the currently logged in user. And if you are not intend to add more complex logic between $form->isSubmitted() and $form->isValid() use just $form->isValid()
class CommentController extends BaseController
{
public function newAction(Request $request, $productId)
{
$comment = new Comment();
$form = $this->createForm(CommentForm::class, $comment);
$form->handleRequest($request);
if ($form->isValid()) {
/** #var Product $product */
$product = $this->getProductRepo()->find($productId);
$comment->setAuthor($this->getUser());
$comment->setProduct($product);
$comment->setContent($form->get('content')->getData());
$this->em->persist($comment);
$this->em->flush();
}
return $this->render(':form:comment.html.twig', array(
'form' => $form->createView(),
));
}
}
[SETTINGS]
Symfony 3
BoxEntity: [id, name]
CandyEntity: [id, name]
[PROBLEM]
Currently, when creating a new candy, I must choose a box as parent entity.
The thing is, I would like this choice to be automated.
The box is already registered in the database, and the session is holding the current box parameters to find it back easily.
But I can't figure out how to apply it to the candy entity once the data have been posted.
[FILES]
AppBundle/Controller/CandyController.php
public function newAction(Request $request) {
$$candy= new Candy();
$form = $this->createForm('AppBundle\Form\CandyType', $conference);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($candy);
$em->flush();
return $this->redirectToRoute('candy_show', array('id' => $candy->getId()));
}
return $this->render('candy/new.html.twig', array(
'candy' => $candy,
'form' => $form->createView(),
));
}
AppBundle/Form/CandyType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nom')
->add('box'); //Remove from form, and set manually
}
I did read this page, but can't figure out how to do it properly.
If someone would be so kind as to give me a full example to solve my problem, it would be much appreciated.
You have multiple options to perform what you want. You could set the value after your form submits:
public function newAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$candy = new Candy();
$box = $em->find('AppBundle\Entity\Box', $this->get('session')->get('boxId'));
$form = $this->createForm('AppBundle\Form\CandyType', $candy);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// add the box entity to the candy
$candy->setBox($box);
$em->persist($candy);
$em->flush();
return $this->redirectToRoute('candy_show', array('id' => $candy->getId()));
}
return $this->render('candy/new.html.twig', array(
'candy' => $candy,
'form' => $form->createView(),
));
}
You could set it on the Candy entity before passing it to the createForm() call, although it may not stay on the entity after doing the form handleRequest() call:
$em = $this->getDoctrine()->getManager();
$candy = new Candy();
$box = $em->find('AppBundle\Entity\Box', $this->get('session')->get('boxId'));
$candy->setBox($box);
$form = $this->createForm('AppBundle\Form\CandyType', $candy);
$form->handleRequest($request);
You could do it in the way that you are attempting, in a form event. What you would want to do is inject the entity manager and session into your form and treat your form as a service:
public function CandyType extends AbstractType
{
private $em;
private $session;
public function __construct(EntityManager $em, SessionInterface $session)
{
$this->session = $session;
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ... build the form
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) {
$form = $event->getForm();
$candy = $event->getData();
$box = $this->em->find('AppBundle\Entity\Box', $this->session->get('boxId');
$candy->setBox($box);
}
);
}
}
You might need to do that on the POST_SET_DATA or POST_SUBMIT event instead, but I'm not sure. Also I used $this->get('session') in the Controller, but depending on your Symfony version (> 3.3) you could inject that into your controller as a service as well.
Either way the main concept is to use Doctrine to grab your Box entity from the session itself using the stored box id in the session, then set that on your Candy entity. You could even use a hidden field to achieve the same results. As I said before there are lots of ways to solve your issue.
I made this Controller to play around with Symfony 2.3
namespace AskThem\MainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use AskThem\MainBundle\Entity\Task;
class DefaultController extends Controller {
private $context = array();
public function indexAction(Request $request) {
$task = new Task();
$form =
$this->createFormBuilder($task)
->add("task", "text")
->add("dueDate", "date")
->add("save", "submit")
->add("saveAndAdd", "submit")
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
// ... perform some action, such as saving the task to the database
$nextAction = $form->get('saveAndAdd')->isClicked()
? 'homepage'
: 'task_success';
return $this->redirect($this->generateUrl($nextAction));
}
$this->context["form"] = $form->createView();
return $this->render('AskThemMainBundle:Default:index.html.twig', $this->context);
}
public function successAction(Request $request) {
return new Response("Victory");
}
}
The form was working fine, so then I added a validation-yml file with some NotBlank rules to test if it would work, and indeed it did.
But when I deleted those rules (I even deleted the whole file) the form still kept presenting itself with the required attribute. How do I turn off the validation?