0

I have showUsersAction()-method inside the Defaultcontroller which should render a form where it should be possible to select a user from a list, press a submit-button and then redirects to a route /showItems/{userId} where the items of a user are shown.

I know that it would be possible to do that easy with a link, but I want to make use of ChoiceType:

First I copied an example of ChoiceType from the Symfony documentation with a minimal change:

/**
 * @Route("/showUsers", name="showUsers")
 */
public function showUsersAction(){
    $users = $this->getDoctrine()->getManager()->getRepository('AppBundle:User')->findAll();

    $form = $this->createFormBuilder()
        ->setMethod('POST')
        ->add('user', ChoiceType::class, [
            'choices' => $users,
            'choice_label' => function($user) {
                /** @var User $user */
                return strtoupper($user->getUsername());//here is the problem
            },
            'choice_attr' => function($user) {
                return ['class' => 'user_'.strtolower($user->getUsername())];
            },
        ])
        ->getForm();

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

I am sure $users gives an array with objects of the class User. When I execute the route in the browser I get following error message:

Error: Call to a member function getUsername() on a non-object 
in src\AppBundle\Controller\DefaultController.php at line 50

Line 50 is the commented line return strtoupper($user->getUsername());

  1. What is the problem and how can I solve?
  2. And how can I get the selected User after I submitted via a submit button to the same route?

EDIT: (because of possible duplication) Of course I know that the method getUsername() can not be called, because $user is a non-object, which should not be related to the Symfony documentation. So my question relates to a Symfony special solution which has absolutly nothing to do with 100 of other problems where the Error is the same.

goulashsoup
  • 2,639
  • 2
  • 34
  • 60
  • Possible duplicate of [Reference - What does this error mean in PHP?](http://stackoverflow.com/questions/12769982/reference-what-does-this-error-mean-in-php) – Charlotte Dunois Aug 25 '16 at 16:45
  • Have you tried inspecting what $user contains inside that callback function? Your code should work according to the docs if $users indeed was an array of objects – georaldc Aug 25 '16 at 17:08
  • I think `$user` if not defined inside the callback function. If I add the if statement: `if($user){...}` the error appears for the 2. callback function. But why? Has it something todo with how I add the `choices` ? – goulashsoup Aug 25 '16 at 17:15

2 Answers2

3

Use entity type instead. Here is a link to documentation. It's a child type of a choice type, with exactly same functionality, and also every option returns an entity object.

xurshid29
  • 4,172
  • 1
  • 20
  • 25
0

Because I had trouble with setting up the entity type field too, I decided to post my solution for the whole action function and the twig file here:

action method:

/**
 * @Route("/showUsers", name="showUsers")
 */
public function showUsersAction(Request $request){
    // gets array of all users in the database
    $users = $this->getDoctrine()->getManager()->getRepository('AppBundle:User')->findAll();

    $form = $this->createFormBuilder()
    ->setMethod('POST')
    ->add('users', EntityType::class, array(
        'class' => 'AppBundle:User',
        'choices' => $users,

        // This combination of 'expanded' and 'multiple' implements radio buttons
        'expanded' => true,
        'multiple' => false,    
        'choice_label' => function ($user) {
                return $user->__toString();
        }
    ))

    // Adds a submit button to the form. 
    // The 'attr' option adds a class to the html rendered form
    ->add('selected', SubmitType::class, array('label' => 'Show User Items', 'attr' => array('class' => 'button')))
    ->getForm();

    $form->handleRequest($request);

    if ($form->isSubmitted()  && $form->isValid()) {
        // gets the selected user
        $selectedUser = $form["users"]->getData();

        // redirects to route 'showItems' with the id of the selected user
        return $this->redirectToRoute('showItems', array('userId' => $selectedUser->getId()));
    }

    // renders 'default/showUsers.html.twig' with the form as an argument
    return $this->render('default/showUsers.html.twig', array('form' => $form->createView()));
}

twig file:

{# 
    // app/Resources/views/default/showUsers.html.twig

    Description:
    twig file that implements a form in which one of all users can get
    selected via radio button to show the items of the user after a click
    on the submit button.

    @author goulashsoup

 #}
{% extends 'base.html.twig' %}
{% block title %}Users{% endblock %}
{% block body %}
    <div class="users">
        {{ form_start(form) }}
            {% for user in form.users %}
                {{ form_widget(user) }}
                {{ form_label(user) }}
                <br>
            {% endfor %}
            <br>
        {{ form_end(form) }}
    </div>
{% endblock %}
goulashsoup
  • 2,639
  • 2
  • 34
  • 60