Search code examples
symfonydoctrine-ormdql

The controller must return a response (1 given). 500 Internal Server Error - LogicException


I started out with the following controller code

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\events;
//use AppBundle\Entity\eventtype;
use AppBundle\Entity\users;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class DefaultController extends Controller {

    /**
     * @Route("/home", name="homepage")
     */
    public function indexAction(Request $request) {
        $events = new events();

        $form = $this->createFormBuilder($events)
                ->add('eT1', ChoiceType::class, array(
                    'choices' => array(
                        'Poker' => 1,
                        'Chess' => 2,
                        'Cricket' => 3,
                        'Marbles' => 4,
                        'Football' => 5,
                    ),
                    'choices_as_values' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Choose After Breakfast Event',
                ))
                ->add('eT2', ChoiceType::class, array(
                    'choices' => array(
                        'Poker' => 1,
                        'Chess' => 2,
                        'Cricket' => 3,
                        'Marbles' => 4,
                        'Football' => 5,
                    ),
                    'choices_as_values' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Choose After Snacks Event',
                ))
                ->add('save', SubmitType::class, array('label' => 'Submit'))
                ->getForm();

        if ($request->isMethod('POST')) {
            $form->submit($request);

            $formData = $form->getData();

            //check to see if the after breakfast event (eT1) is full (ie.has reached the maxlimit)
            //for now the maxLimit is set to 4
            $ET1 = $formData->getET1();

            $repository = $this->getDoctrine()->getRepository('AppBundle:events');
            $query1 = $repository->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.eT1 = :eT1')
                    ->setParameter('eT1', $ET1)
                    ->getQuery();
            $a = $query1->getSingleScalarResult();

            if ($a >= $maxLimit=4) {
                echo 'choose another event, this one is full';
            }
            else{
               return $ET1; 
            }

            //check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
            //for now the maxLimit is set to 4
            $ET2 = $formData->getET2();

            $query2 = $repository->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.eT2 = :eT2')
                    ->setParameter('eT2', $ET2)
                    ->getQuery();
            $b = $query2->getSingleScalarResult();

            if ($b >= $maxLimit=4) {
                echo 'choose another event, this one is full';
            }
            else{
               return $ET2; 
            }

            //get the user_id of the logged in user
            $user = $this->container->get('security.context')->getToken()->getUser();
            $events->setUser($user);
            $x = $events->getUser()->getID();

            if ($form->isValid()) {

                //check if the user has already registered or not
                $y = $repository->findOneBy(array('user' => $x));

                // If the user is registering for the first time (execute the insert query)
                if (!$y) {                    
                    $em = $this->getDoctrine()->getManager();
                    $em->persist($events);
                    $em->flush();
                    return $this->redirectToRoute('homepage');
                } 

                //If the user has registered already and want change his registered events (execute the update query)
                else {                    
                    $formData = $form->getData();
                    $ET1 = $formData->getET1();
                    $ET2 = $formData->getET2();
                    $events->setET1($ET1);
                    $events->setET2($ET2);

                    $em = $this->getDoctrine()->getManager();
                    $em->persist($events);
                    $em->flush();
                    return $this->redirectToRoute('homepage');
                }
            }
        }

        return $this->render('default/index.html.twig', array(
                    'form' => $form->createView(),
        ));
    }

}

But then i modified the code to display different pages for a user who has already registered and who is registering for the for the first time. The following code gives the error - The controller must return a response (1 given). 500 Internal Server Error - LogicException My guess is that the error lies in statements return $ET1; and return $ET2; Here are the questions I cannot find answers to: 1. Why the error - The controller must return a response (1 given). 500 Internal Server Error - LogicException 2. I have to repeat the same code twice, for new user and already registered user. Is there a work around? 3. How do i set the different $maxLimit parameter values for different events(eg. for poker=12, chess=4, cricket=10 etc.) from inside the config.yml file?

Here is the modified controller code

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\events;
//use AppBundle\Entity\eventtype;
use AppBundle\Entity\users;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class DefaultController extends Controller {

    /**
     * @Route("/home", name="homepage")
     */
    public function indexAction(Request $request) {
        $events = new events();
        // check if the user is registering for the first time or else
        $user = $this->container->get('security.context')->getToken()->getUser();
        $events->setUser($user);
        $x = $events->getUser()->getID();

        $repository = $this->getDoctrine()->getRepository('AppBundle:events');
        $y = $repository->findOneBy(array('user' => $x));

        // If the user is registering for the first time (execute the insert query)
        if (!$y) {
            echo 'Welcome to the Birthday party';
            echo 'You can choose from the below options:';

            $form = $this->createFormBuilder($events)
                    ->add('eT1', ChoiceType::class, array(
                        'choices' => array(
                            'Poker' => 1,
                            'Chess' => 2,
                            'Cricket' => 3,
                            'Marbles' => 4,
                            'Football' => 5,
                        ),
                        'choices_as_values' => true,
                        'expanded' => true,
                        'multiple' => false,
                        'label' => 'After Breakfast Event',
                    ))
                    ->add('eT2', ChoiceType::class, array(
                        'choices' => array(
                            'Poker' => 1,
                            'Chess' => 2,
                            'Cricket' => 3,
                            'Marbles' => 4,
                            'Football' => 5,
                        ),
                        'choices_as_values' => true,
                        'expanded' => true,
                        'multiple' => false,
                        'label' => 'After Snacks Event',
                    ))
                    ->add('save', SubmitType::class, array('label' => 'Submit'))
                    ->getForm();

            if ($request->isMethod('POST')) {
                $form->submit($request);

                $formData = $form->getData();

                //check to see if the after breakfast event (eT1) is full (ie.has reached the maxlimit)
                $ET1 = $formData->getET1();

                $repository = $this->getDoctrine()->getRepository('AppBundle:events');
                $query1 = $repository->createQueryBuilder('p')
                        ->select('count(p)')
                        ->where('p.eT1 = :eT1')
                        ->setParameter('eT1', $ET1)
                        ->getQuery();
                $a = $query1->getSingleScalarResult();
//            var_dump($a);
//            exit;
                if ($a >= $maxLimit = 4) {
                    echo 'choose another event, this one is full';
                } else {
                    return $ET1;
                }

                //check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
                $ET2 = $formData->getET2();

                $query2 = $repository->createQueryBuilder('p')
                        ->select('count(p)')
                        ->where('p.eT2 = :eT2')
                        ->setParameter('eT2', $ET2)
                        ->getQuery();
                $b = $query2->getSingleScalarResult();
//            var_dump($a);
//            exit;
                if ($b >= $maxLimit = 4) {
                    echo 'choose another event, this one is full';
                } else {
                    return $ET2;
                }

                if ($form->isValid()) {

                    $em = $this->getDoctrine()->getManager();
                    // tells Doctrine you want to (eventually) save the Product (no queries yet)
                    $em->persist($events);

                    // actually executes the queries (i.e. the INSERT query)
                    $em->flush();
                    return $this->redirectToRoute('homepage');
                }
            }
        }
        // If the user has registered already and want change his registered events (execute the update query)
        else {
            echo 'Welcome back';
            echo 'You registered for:';
            echo 'After Breakfast event:.$eventName.';
            echo 'After Snacks event:.$eventName.';
            echo 'You can change your selection by choosing again from below options:';

            $form = $this->createFormBuilder($events)
                    ->add('eT1', ChoiceType::class, array(
                        'choices' => array(
                            'Poker' => 1,
                            'Chess' => 2,
                            'Cricket' => 3,
                            'Marbles' => 4,
                            'Football' => 5,
                        ),
                        'choices_as_values' => true,
                        'expanded' => true,
                        'multiple' => false,
                        'label' => 'After Breakfast Event',
                    ))
                    ->add('eT2', ChoiceType::class, array(
                        'choices' => array(
                            'Poker' => 1,
                            'Chess' => 2,
                            'Cricket' => 3,
                            'Marbles' => 4,
                            'Football' => 5,
                        ),
                        'choices_as_values' => true,
                        'expanded' => true,
                        'multiple' => false,
                        'label' => 'After Snacks Event',
                    ))
                    ->add('save', SubmitType::class, array('label' => 'Submit'))
                    ->getForm();

            if ($request->isMethod('POST')) {
                $form->submit($request);

                $formData = $form->getData();

                //check to see if the after Breakfast event (eT1) is full (ie.has reached the maxlimit)
                $ET1 = $formData->getET1();

                $repository = $this->getDoctrine()->getRepository('AppBundle:events');
                $query1 = $repository->createQueryBuilder('p')
                        ->select('count(p)')
                        ->where('p.eT1 = :eT1')
                        ->setParameter('eT1', $ET1)
                        ->getQuery();
                $a = $query1->getSingleScalarResult();
//            var_dump($a);
//            exit;
                if ($a >= $maxLimit = 4) {
                    echo 'choose another event, this one is full';
                } else {
                    return $ET1;
                }

                //check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
                $ET2 = $formData->getET2();

                $query2 = $repository->createQueryBuilder('p')
                        ->select('count(p)')
                        ->where('p.eT2 = :eT2')
                        ->setParameter('eT2', $ET2)
                        ->getQuery();
                $b = $query2->getSingleScalarResult();
//            var_dump($a);
//            exit;
                if ($b >= $maxLimit = 4) {
                    echo 'choose another event, this one is full';
                } else {
                    return $ET2;

                    if ($form->isValid()) {

                        $formData = $form->getData();
                        $ET1 = $formData->getET1();
                        $ET2 = $formData->getET2();
                        $events->setET1($ET1);
                        $events->setET2($ET2);
                        $em = $this->getDoctrine()->getManager();

                        $em->persist($events);
                        $em->flush();
                        return $this->redirectToRoute('homepage');
                    }
                }
            }
        }
        return $this->render('default/index.html.twig', array(
                    'form' => $form->createView(),
        ));

    }

}

Below is the users entity

<?php

namespace AppBundle\Entity;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * users
 *
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\usersRepository")
 */
class users extends BaseUser
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * Get id
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @ORM\OneToOne(targetEntity="events", mappedBy="user")
     */
    protected $event;


//    public function __construct()
//    {
//        parent::__construct(); 
//         }

    }

Below is the events entity

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
//use Symfony\Component\Validator\Constraints as Assert;

/**
 * events
 *
 * @ORM\Table(name="events")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\eventsRepository")
 */
class events {

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var int
     *
     * @ORM\Column(name="ET1", type="integer")
     */
    protected $eT1;

    /**
     * @var int
     *
     * @ORM\Column(name="ET2", type="integer")
     */
    protected $eT2;

    /**
     * @ORM\OneToOne(targetEntity="users", inversedBy="event")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
        protected $user;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId() {
        return $this->id;
    }

    /**
     * Set user
     *
     * @param users $user
     * @return events
     */
    public function setUser($user) {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return events
     */
    public function getUser() {
        return $this->user;
    }


    /**
     * Set eT1
     *
     * @param integer $eT1
     * @return events
     */
    public function setET1($eT1) {
        $this->eT1 = $eT1;

        return $this;
    }

    /**
     * Get eT1
     *
     * @return integer 
     */
    public function getET1() {
        return $this->eT1;
    }

    /**
     * Set eT2
     *
     * @param integer $eT2
     * @return events
     */
    public function setET2($eT2) {
        $this->eT2 = $eT2;

        return $this;
    }

    /**
     * Get eT2
     *
     * @return integer 
     */
    public function getET2() {
        return $this->eT2;
    }

//    public function __construct()
//    {
//        parent::__construct();
//    }
}

Solution

  • to answer your first question: the Controller must always return an object of type Response, if it cannot return a response object then it must forward the control by doing an internal sub-request to a controller that does return a response object. in symfony, twig templates are used to display the outputs to the user, using

    return $this->render('navigation/homepage.html.twig', array('et1' => $et1, 'et2' => $et2));

    would make the two variables et1 and et2 to be available in the homepage.html.twig template.

    to answer the second question: you get the current logged in user by doing $this->getUser() which is a short cut for security.context token link

    i'm making a guess here, you are trying to check if the userId matches with a userId of an 'events' object, you consider it to be a returning user, and if it does't then its a new user, on that premise

    $user = $this->getUser()->getUserId();
    $event = $this->getDoctrine()->getRepository('AppBundle:events')->findOneBy(array('user' => $this->getUser()->getUserId() ));
    if($event instanceof events){ //events refers to 'events' entity
    // code to handle returning user
    }
    

    answer to the third question: avoid using Global variables, by using config.yml to store maxValue, you are making maxValue available for the entire project. you could change things up in your code to not use golbal variables, but just for the sake of answering a question

    store your global variables inside parameters.yml instead of config.yml just to keep things understandable, do something like this link

    parameters:
        cricketMaxLimit: 10
    

    retrieve it with $cricMaxLimit = $this->container->getParameter('cricketMaxLimit');

    sidenote: stuff like if ($a >= $maxLimit = 4) should not even exist in this world, do if ($a >= 4)

    -dheeraj :)