2015-01-14 13 views
6

Đầu tiên tôi đã đọc tài liệu cho cả hai Collection Field TypeHow to Embed a Collection of Forms ... Ví dụ này là về một thực thể (Tác vụ) có quan hệ một-nhiều với thực thể khác (Tag), và tôi hiểu nó, nhưng tôi không thể thích nghi nó với những gì tôi muốn!Cách tạo biểu mẫu có nhiều hàng của một thực thể trong Symfony2

Để làm cho nó đơn giản hơn, chúng ta hãy nói rằng tôi có một tổ chức công tác, thực hiện nhiệm vụ này có một số mối quan hệ với các đối tượng khác như người dùng và dự án (mỗi nhiệm vụ có thể có một người dùng và một dự án)

Tôi muốn làm một hình thức, bên trong mẫu đơn này một danh sách các nhiệm vụ, mỗi nhiệm vụ trong một hàng của một bảng hiển thị thông tin như task.title, task.startdate, task.user.name, task.user.company.name, task.project.name và có 2 trường có thể chỉnh sửa được, hộp văn bản " Mô tả "hộp kiểm" đang hoạt động ". Bạn có thể chỉnh sửa nhiều tác vụ và gửi biểu mẫu bằng một nút ở cuối bảng trong biểu mẫu chính, vì vậy về cơ bản bạn có thể cập nhật nhiều bản ghi trong một giao dịch (thay vì tạo một biểu mẫu và một nút gửi cho mỗi hàng và một bản cập nhật cho mỗi lần gửi).

Tôi có rất nhiều vấn đề với thiết kế phức tạp này:

Trước tiên tôi muốn làm theo mẫu để nhúng một tập hợp các hình thức bên trong các hình thức chính, Vì vậy, tôi đã thực hiện một loại mẫu cho công tác của tôi rằng nên giống như một hình thức mỗi hàng. Tôi đã thực hiện những tập tin này:

Mẫu Kiểu cho công tác:

// 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'; 
    } 
} 

Mẫu Kiểu cho hình thức chính:

// 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'; 
    } 
} 

Nhiệm vụ Mẫu Bộ điều khiển:

// 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(), 
     )); 
    } 
} 

công tác Mẫu Twig Template (chỉ là một phần liên quan):

<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> 

NHƯNG có một vấn đề ở đây, khi tôi nhận được kết quả từ xây dựng truy vấn nó là một mớ hỗn độn của mảng chứa các đối tượng trong họ, tôi nhận được một lỗi về

Dữ liệu chế độ xem của biểu mẫu được mong đợi là một thể hiện của lớp Acme \ TaskBundle \ Entity \ Task, nhưng là một mảng (n). Bạn có thể tránh lỗi này bằng cách đặt tùy chọn "data_class" thành null hoặc bằng cách thêm trình biến đổi chế độ xem biến đổi mảng (n) thành một phiên bản của Acme \ TaskBundle \ Entity \ Task.

Đây là truy vấn:

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, tôi sử dụng Partial Objects dẫn để xem nếu nó có thể giúp đỡ, nó giúp để làm cho đối tượng nhiệm vụ trong kết quả truy vấn và tôi có thể giải nén nó và gửi nó để hình thành, nhưng vẫn có vẻ như phần còn lại của hình thức là không biết phần còn lại của các đối tượng ...

Ok, vì vậy có thể tôi đang chọn cách tiếp cận sai, tôi không chắc chắn! xin vui lòng nếu bạn có bất cứ đề nghị về những gì tôi nên làm, đặt một lưu ý ở đây ... Tôi đang đấu tranh với điều này trong hơn một tuần! Cảm ơn trước cho thời gian của bạn! Ngay cả khi bạn không đặt bất kỳ ghi chú nào, tôi đánh giá cao việc bạn dành thời gian đọc câu hỏi rất dài của tôi! Cảm ơn! :)

Trả lời

4

Đây là sự khởi đầu cho một giải pháp khả thi. Ví dụ dưới đây lấy một thực thể Kỹ năng và trình bày tất cả chúng trên một trang duy nhất. Những gì tôi không biết là liệu kỹ thuật này có thể được sử dụng để tồn tại các đối tượng trẻ em hay không. Tôi hy vọng người ta có thể lặp qua các dữ liệu trả về và tồn tại theo yêu cầu.

Mã bên dưới dẫn đến một trang có danh sách tất cả các kỹ năng có thể có và hộp kiểm để khai báo từng bật hoặc bật.

Trong một bộ điều khiển:

$skills = $em->getRepository("TruckeeMatchingBundle:Skill")->getSkills(); 
    $formSkills = $this->createForm(new SkillsType(), array('skills' => $skills)); 
    ... 
     if ($request->getMethod() == 'POST') { 
      $formSkills->handleRequest($request); 
      foreach ($skills as $existingSkill) { 
       $em->persist($existingSkill); 
      } 
     } 
    ... 
    return ['formSkills' => $formSkills->createView(),...] 

Trong một mẫu:

{% for skill in formSkills.skills %} 
    {{ skill.vars.value.skill }} 
      <input type="hidden" name="skills[skills][{{ loop.index0 }}][skill]" value="{{ skill.vars.value.skill }}"> 
      <input type="checkbox" name="skills[skills][{{ loop.index0 }}][enabled]" 
      {%if skill.vars.value.enabled %}checked="checked"{%endif%} 
{% endfor %} 
+0

Xin lỗi vì tôi đã không trả lại cho bạn! Chuỗi nhiệm vụ của tôi đã thay đổi nên tôi đang làm việc trên các nội dung khác ngay bây giờ ... Tôi sẽ liên hệ lại với bạn và sẽ cho bạn biết nếu nó hoạt động! Tôi có một ý tưởng từ câu trả lời của bạn, và tôi hy vọng nó hoạt động! cảm ơn vì đã dành thời gian và gửi câu trả lời ... :) – Monica

+0

Xin lỗi vì đã kiểm tra câu trả lời của bạn với một sự chậm trễ lớn! Câu trả lời của bạn đã giúp tôi rất nhiều, tôi sẽ chấp nhận câu trả lời của bạn! :) Tôi cũng sẽ cập nhật câu hỏi của riêng mình sau, với phiên bản cuối cùng! – Monica

+0

Không phải lo lắng về sự chậm trễ. Vui mừng nó đã giúp. – geoB

0

tôi sử dụng một chiến lược khác nhau. Tập tin TWIG của tôi tương tự như câu hỏi của Monica. Nhưng có một vài khác biệt nhưng rất hữu ích. Ở đây mã của bạn:

 {{ form_start(form) }} 
    {% for docente in docentes %} 
     Id: <input type="integer" name="{{ docente.id }}" required="required" style="width:30px" value="{{ docente.id }}" readonly> 
     Apellido: <input type="text" name="{{ docente.apellido }}" required="required" style="width: 80px" value="{{ docente.apellido }}" readonly> 
     Nombres: <input type="text" name="{{ docente.nombres }}" required="required" style="width: 80px" value="{{ docente.nombres }}" readonly> 
    Discrecional: <input type="checkbox" name="D{{ docente.id }}" value="{{ docente.discrecional }}" {% if docente.discrecional==1 %}checked{% endif %}> <br> 
     <br> 
    {% endfor %}   
     <input type="submit" value="Grabar" />  
{{ form_end(form) }} 

Trong tệp TWIG, tôi tiến hành tạo tên khác cho mỗi bản ghi trong biểu mẫu cho trường "không phù hợp". Điều này sẽ giúp tôi xác định từng bản ghi trong bộ điều khiển. Theo dõi.

Khi người dùng nhấn vào nút "submit" Tôi thực hiện một lần lặp trong tập tin điều khiển của tôi, như hình dưới đây:

if ($form->isSubmitted() && $form->isValid()) {  
      $i=0; 
       foreach ($defaultData as $value) { 
        $data2= array('id' =>$request->request->get($defaultData[$i]['id']), 
        'discrecional' =>$request->request->get('D'.$defaultData[$i]['id'])); 

        if (($request->request->get('D'.$defaultData[$i]['id'])== '0' and $defaultData[$i]['discrecional']=='0') or 
         ($request->request->get('D'.$defaultData[$i]['id'])== NULL and $defaultData[$i]['discrecional']=='1'))  
        { 
        $em->getRepository('BackendBundle:Docentes')->findDocenteFiltId2($data2); 
        } 
        $i=$i+1; 
       } 

Nhưng bản cập nhật của sổ đăng ký, là một tác phẩm được thực hiện trong tập tin Repository của tôi thông qua một truy vấn bằng cách sử dụng UPDATE, thay vì thực hiện nó trong tệp Bộ điều khiển. Để tránh các truy vấn không cần thiết và quá tải máy chủ, tôi chỉ cập nhật các bản ghi đã được thay đổi trước đó. Trong ví dụ này, các dòng sau trong bộ điều khiển của tôi kiểm tra nếu có thay đổi trong bản ghi (trong trường hợp của tôi, tôi chỉ đang chỉnh sửa một trường có tên là "discrecional". Nếu trường đã thay đổi, thì tôi gọi truy vấn và cập nhật kỷ lục):

if (($request->request->get('D'.$defaultData[$i]['id'])== '0' and $Data[$i]['discrecional']=='0') or 
        ($request->request->get('D'.$defaultData[$i]['id'])== NULL and $defaultData[$i]['discrecional']=='1'))  
       { 
       $em->getRepository('BackendBundle:Docentes')->findDocenteFiltId2($data2); 
       } 

hoàn chỉnh tập tin điều khiển của tôi là ở đây:

public function discrecionalAction(Request $request) 
{ 
    $em = $this->getDoctrine()->getManager();  
    $defaultData= $em->getRepository('BackendBundle:Docentes')->buscarDocentesActivos2(); 


// construimos un formulario "vacío" sin campos definido 
      $form = $this->createFormBuilder($defaultData); 
     $form = $form->getForm(); 

      $form->handleRequest($request);  


      if ($form->isSubmitted() && $form->isValid()) { 


      $i=0; 
       foreach ($defaultData as $value) { 
        $data2= array('id' =>$request->request->get($defaultData[$i]['id']), 
        'discrecional' =>$request->request->get('D'.$defaultData[$i]['id'])); 

        if (($request->request->get('D'.$defaultData[$i]['id'])== '0' and $defaultData[$i]['discrecional']=='0') or 
         ($request->request->get('D'.$defaultData[$i]['id'])== NULL and $defaultData[$i]['discrecional']=='1'))  
        { 
        $em->getRepository('BackendBundle:Docentes')->findDocenteFiltId2($data2); 
        } 
        $i=$i+1; 
       } 

    return $this->redirectToRoute('docentes_discrecional'); 

       }   


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

hoàn chỉnh truy vấn Repository đầu tiên của tôi là ở đây:

public function buscarDocentesActivos2() 
{ 


     $fields = array('d.id', 'd.apellido', 'd.nombres', 'd.discrecional'); 
$query = $this->getEntityManager()->createQueryBuilder(); 
     $query 
      ->select($fields) 
      ->from('BackendBundle:Docentes', 'd') 
      ->where('d.activo=true') 
      ->orderBy('d.apellido, d.nombres');  

     $consulta = $query->getQuery()->getResult(); 

     return $consulta; 
    } 

hoàn toàn thức truy vấn Repository của tôi với chức năng UPDATE ở đây:

public function findDocenteFiltId2($filtro) 
{ 

if (is_null($filtro['discrecional'])){ 
    $discrec= '0'; 
}; 

if ($filtro['discrecional']=='0'){ 
    $discrec= '1'; 
}; 

$em = $this->getEntityManager(); 

    $consulta = $em->createQuery(' 
     UPDATE BackendBundle:Docentes d 
     SET d.discrecional = :disc 
     WHERE d.id = :idver 
    '); 

    $consulta->setParameters(array(

    'idver' => $filtro['id'], 
    'disc' => $discrec,  
     )); 
     return $consulta->getArrayResult(); 

} 
Các vấn đề liên quan