php - How to display many to one relation objects in index action

71

I'm trying to create a symfony based forum. on the index page I need to show users sections they can choose to enter. however each section has categories, and all of those need to be displayed in one view. it should look like this.

  • Section1
    • category1
    • category2
  • Section2
    • category3

etc.

I'm following symblog.co.uk tutorial, and try to do it basing on their blogs/comments example, there is one simple problem, they define comments in show action, have $comments variable for each blog, and I need my categories to be accessible from $sections variable. For each Section user must be able to read categories AND add new ones

here's how my files look like.

index action, basic view where everything I wrote about takes place

{% block body %}
  IndexAction of Page Controller


  <form action="{{ path("EpiForumBundle_section_create") }}" method="post" {{ form_enctype(form) }} >
    {{ form_errors(form) }}

    {{ form_row(form.name) }}
        {{ form_rest(form) }}
    <input type="submit" value="Submit" />
  </form>

    <table>
      <th>date created
      <th>name
  {% for section in sections %}
        <tr>
          <td>
      <div ><time datetime="{{ section.created|date('c') }}">{{ section.created|date('l, F j, Y') }}</time></div>
          </td>
          <td>  
        <p><span >{{ section.name }}</span></p>
          </td>
        </tr>
  {% else %}
    <p>There are no sections for this forum</p>
  {% endfor %}
  </table>
{% endblock %}

Page Controller

<?php

namespace Epi\ForumBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Epi\ForumBundle\Entity\Section;
use Epi\ForumBundle\Form\SectionType;

class PageController extends Controller
{
    public function indexAction()
    {       
            $section = new Section();
                $form = $this->createForm(new SectionType(), $section);

        $em = $this->getDoctrine()
                   ->getEntityManager();

        $sections = $em->getRepository('EpiForumBundle:Section')
                    ->getLatestSections();

        return $this->render('EpiForumBundle:Page:index.html.twig', array('sections' => $sections, 'form' => $form->createView()));
    }
}

Section Controller

<?php

namespace Epi\ForumBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Epi\ForumBundle\Entity\Section;
use Epi\ForumBundle\Form\SectionType;

class SectionController extends Controller
{
    public function createAction()
    {
        $section = new Section();
            $form = $this->createForm(new SectionType(), $section);
            $em = $this->getDoctrine()->getManager();

            $request = $this->getRequest();

            if($request->getMethod() == 'POST'){
                $form->bind($this->getRequest());/*or  $form->handleRequest($request); depends on symfony version */
                $em->persist($section);
                $em->flush();
                return $this->redirect("/");
            }
            return $this->redirect("/");
    }
}

Section Type:

<?php

namespace Epi\ForumBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class SectionType extends AbstractType
{
        /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name');
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Epi\ForumBundle\Entity\Section'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'epi_forumbundle_section';
    }
}

So now where do I put those forms for categories? How those forms should be written to know about section_id?

91

Answer

Solution:

You need a bidirectional relation between Section & Category.

Actualy you have a section attribute in your Category entities thats is mapped ManyToOne right?

So now, you need a Categorys attribute in your Section attribute, that is mapped OneToMany.

With that, you can access Category from Section, and so show them whitout using any request.

There is an example, I have two entities, Division & Teacher. One teacher can teach to multiple divisions. Heres my mapping in Division entity

/**
 *
 * @ORM\ManyToOne(targetEntity="Acme\DemoBundle\Entity\Teacher", inversedBy="divisions")
 * @ORM\JoinColumn(nullable=false)
 */
private $teacher;

And in Teacher entity

/**
 * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\Division", mappedBy="teacher", cascade={"remove"})
 */
private $divisions;

Theres many division in divisions, its a collection. We need an ArrayCollection, like this:

public function __construct()
{
    parent::__construct(); (optional)
    $this->divisions = new \Doctrine\Common\Collections\ArrayCollection();
}

This is bidirectionnal, so you have to writh both $teacher->setDivision($division) & $division->setTeacher($teacher), one easiest way is to make on of these function call the other one. Like this:

/**
 * Set teacher
 * 
 * @param Acme\DemoBundle\Entity\Teacher $teacher
 */
public function setTeacher(\Acme\DemoBundle\Entity\Teacher $teacher)
{
    $this->teacher = $teacher;
    $teacher->setDivision($this);
}

For the second problem, about section_id into your form. In your Category type, add one line like this =>

->add('section', 'entity', array('class' => 'YourBundle:Section', 'property' => 'name','label' => 'Section'))

It will allow you to select the section you want for this category.

Hope I helped, sorry for my english.

People are also looking for solutions to the problem: php - How do I make Text Editor display an apostrophe instead of a single quote?

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.