So erstellen Sie ein Formular mit mehreren Zeilen einer Entität in Symfony2

Zunächst habe ich Dokumente für beide gelesenSammlungsfeldtyp undWie binde ich eine Sammlung von Formularen ein? ... Das Beispiel handelt von einer Entität (Task), die eine Eins-zu-Viele-Beziehung zu einer anderen Entität (Tag) hat, und ich verstehe es, aber ich kann es nicht an das anpassen, was ich will!

Um es einfacher zu machen, sagen wir, ich habe eine Task-Entität, diese Task-Entität hat einige Beziehungen zu anderen Objekten wie Benutzer und Projekt (jede Task kann einen Benutzer und ein Projekt haben)

Ich möchte ein Formular erstellen, in dem eine Liste von Aufgaben enthalten ist, wobei jede Aufgabe in einer Zeile einer Tabelle enthalten ist, in der Informationen wie @ angezeigt werde task.title, task.startdate, task.user.name, task.user.company.name, task.project.name, Und es hat 2 bearbeitbare Felder,textbox "Description" undcheckbox "active". Sie können mehrere Aufgaben bearbeiten und das Formular über eine Schaltfläche am Ende der Tabelle im Hauptformular senden. Daher sollten Sie grundsätzlich in der Lage sein, mehrere Datensätze in einer Transaktion zu aktualisieren (anstatt ein Formular und eine Senden-Schaltfläche pro Zeile und dafür zu erstellen) ein Datensatzupdate pro Einreichung).

Ich habe viele Probleme mit diesem komplizierten Design:

Zunächst wollte ich dem Beispiel folgen, um eine Sammlung von Formularen in das Hauptformular einzubetten. Daher habe ich einen Formulartyp für meine Aufgabe erstellt, der wie ein Formular pro Zeile aussehen sollte. Ich habe diese Dateien erstellt:

Formulartyp für Aufgabe:

// src/Acme/TaskBundle/Form/Type/TaskType.php
namespace Acme\TaskBundle\Form\Type;

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

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $builder->add('description', 'text', ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'description']]);
         $builder->add('active', 'checkbox', ['label' => false, 'required' => false, 'data' => true]);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\TaskBundle\Entity\Task',
        ));
    }

    public function getName()
    {
        return 'taskType';
    }
}

Form Type für Hauptformular:

// src/Acme/TaskBundle/Form/Type/SaveTasksType.php
namespace Acme\TaskBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Acme\TaskBundle\Form\Type\TaskType.php;

class SaveTasksType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('tasksCollection', 'collection', ['type' => new TaskType()]);
        $builder->add('tasksSubmit', 'submit', ['label' => 'Save']);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults([
            'attr' => ['class' => 'form-horizontal'],
            'method' => 'POST'
        ]);
    }

    public function getName()
    {
        return 'saveTasksType';
    }
}

Tasks Form Controller:

// src/Acme/TaskBundle/Controller/ManageTasksController.php
namespace Acme\TaskBundle\Controller;

use Acme\TaskBundle\Entity\Task;
use Acme\TaskBundle\Form\Type\SaveTaskType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class ManageTasksController extends Controller
{
    public function showListAction(Request $request)
    {
        $repository = $this->getDoctrine()->getRepository('ExampleBundle:Task');
        $tasks = $repository->findAll();

        $taskSaveForm = $this->createForm(new SaveTasksType(['tasks' => $tasks]));

        return $this->render('AcmeTaskBundle:Task:list.html.twig', array(
            'taskSaveForm' => $taskSaveForm->createView(),
        ));
    }
}

Task Form Twig Template (nur verwandter Teil):

<div class="innerAll">
    {{ form_start(taskSaveForm) }}
    {{ form_errors(taskSaveForm) }}

    <table class="table table-bordered table-striped table-primary list-table">
        <thead>
            <tr>
                <th>Task ID</th>
                <th>Title</th>
                <th>Start Date</th>
                <th>User</th>
                <th>Company</th>
                <th>Project</th>
                <th>Description</th>
                <th>Active</th>
            </tr>
        </thead>
        <tbody>
            {% for task in taskSaveForm.tasksCollection %}

                <tr>
                    <td>{{ task.id }}</td>
                    <td><a href="https://localhost/taskid={{ task.id }}">{{ task.title }}</a></td>
                    <td>{{ task.startDate }}</td>
                    <td>{{ task.userName }}</td>
                    <td>{{ task.companyName }}</td>
                    <td>{{ task.projectName }}</td>
                    <td>{{ form_widget(task.description) }}</td>
                    <td>{{ form_widget(task.active) }}</td>
                    <td></td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <div>{{ form_row(taskSaveForm.tasksSubmit) }}</div>
    {{ form_end(taskSaveForm) }}
</div>

ABER hier gibt es ein Problem. Wenn ich das Ergebnis vom Abfrage-Generator erhalte, handelt es sich um ein Durcheinander von Arrays, die Objekte enthalten, und ich erhalte eine Fehlermeldung über

s wird erwartet, dass die Anzeigedaten des Formulars eine Instanz der Klasse Acme \ TaskBundle \ Entity \ Task sind, es sich jedoch um ein (n) Array handelt. Sie können diesen Fehler vermeiden, indem Sie die Option "data_class" auf "null" setzen oder einen Ansichtstransformator hinzufügen, der ein (n) Array in eine Instanz von "Acme \ TaskBundle \ Entity \ Task" umwandelt.

Dies ist die Abfrage:

createQueryBuilder()
    ->select(
            "
            task.id,
            task.title,
            task.startDate,
            task.description,
            user.name as userName,
            company.name as companyName,
            project.name as projectName,
            "
    )
        ->from('Acme\TaskBundle\Entity\Task', 'task')
        ->innerJoin('task.project', 'project')
        ->innerJoin('task.user', 'user')
        ->innerJoin('Acme\TaskBundle\Entity\Company', 'company', 'with', 'store.company = company')
        ->where('task.active = :isActive')->setParameter('isActive', true);

Soooo, ich habeTeilobjekte Leitfaden, um zu sehen, ob es helfen kann, es hilft, das Task-Objekt im Abfrageergebnis zu machen, und ich könnte es extrahieren und an Formular senden, aber es scheint, dass der Rest der Form den Rest der Objekte nicht kennt ...

Ok, vielleicht wähle ich den falschen Ansatz, ich bin mir nicht sicher! Bitte, wenn Sie Vorschläge haben, was ich tun soll, tragen Sie hier eine Notiz ein ... Ich habe seit mehr als einer Woche damit zu kämpfen! Vielen Dank im Voraus für Ihre Zeit! Auch wenn Sie keine Notiz hinterlassen, ich freue mich, dass Sie Zeit damit verbringen, meine sehr lange Frage zu lesen! Vielen Dank! :)

Antworten auf die Frage(4)

Ihre Antwort auf die Frage