2016-12-29 3 views
0

У меня есть сущность книги, которая содержит:Комбинирование 2 формы в Symfony

/** 
* @var \Doctrine\Common\Collections\ArrayCollection 
* @ORM\OneToMany(targetEntity="Reviewr\ReviewsBundle\Entity\Review", mappedBy="bookID") 
*/ 
protected $reviews; 

В пределах объекта обзора у меня есть поля для представления:

userID 
bookID 
posted 
comment 

В пределах моего Booktype, я пытаюсь создать форма, которая также включает в себя поля из формы ReviewType:

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('author') 
     ->add('title') 
     ->add('summary') 
     ->add('reviews', ReviewType::class) 
     ->add('submit', SubmitType::class); 
} 

Однако, я не могу показаться, чтобы получить эту работу , im просто пытается иметь форму, которая использует поля из объекта книги и объекта обзора в одном.

Я получаю эту ошибку:

The form's view data is expected to be an instance of class Reviewr\ReviewsBundle\Entity\Review, but is an instance of class Doctrine\Common\Collections\ArrayCollection. 

Кто-нибудь знает, что им делать неправильно?

UPDATE С текущим ответом, он, наконец, показывает что-то .. просто строку «Отзывы», а не поля из формы ReviewType (USERID, BookID, публикуемые и комментария), как показано на рисунке ниже:

enter image description here

Почему это не отображает поля?

+0

ли вы пытались использовать EntityType в вашем ReviewType? –

+0

@DanCostinel Я обновил вопрос, чтобы вы поняли, что происходит лучше. – KTOV

+0

Я предполагаю, что строка «Reviews» отображается вашей '{{form_end (form)}}'. Посмотрите, правильно ли вы отобрали соответствующее поле. –

ответ

0

Поскольку ваша книга имеет много обзоров (а не один), необходимо сопоставить обзор как тип коллекции, каждая запись которого будет иметь тип обзора

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('author') 
     ->add('title') 
     ->add('summary') 
     ->add('reviews', CollectionType::class, array(
      'entry_type' => ReviewType::class 
     )) 
     ->add('submit', SubmitType::class); 
} 

подробнее в documentation.

+0

Когда я это делаю, он просто отображает строку «Отзывы» в форме, а не все ее поля (идентификатор пользователя, bookID и комментарий) – KTOV

+0

Я обновил вопрос, чтобы показать вам, что я имею в виду – KTOV

+0

Это нормальное поведение. Вам нужно сделать кнопку «добавить», которую пользователь вашей формы может нажать, чтобы добавить новый отзыв. Только если вы редактируете существующую книгу, в которой уже есть отзывы, вы увидите отзывы. Я думаю, что вам нужно работать на этом курсе: https://symfony.com/doc/current/form/form_collections.html –

0

Для отображения для конкретной книги отзывов, вам нужно реализовать OneToMany соотношения в Book сущности (в качестве обратной стороны), и ManyToOne отношения в Review сущности (как владеющему стороны).

Я искал для полных примеров, и я не мог найти, так вот моя попытка:

1) Создание Book и Review сущности, без каких-либо отношений, а также создавать их в базе данных тоже. Вы получите сообщение об ошибке, если попытаетесь создать таблицы вместе с отношениями, если эти таблицы еще не присутствуют в базе данных.

2) Теперь вы можете создать отношения

# AppBundle\Entity\Book.php 
use Doctrine\Common\Collections\ArrayCollection; 
... 
class Book 
... 
/** 
* @ORM\OneToMany(targetEntity="Review", mappedBy="book") 
*/ 
private $reviews; 

public function __construct() 
{ 
    $this->reviews = new ArrayCollection(); 
} 
//... getters and setters for extra fields you might have 
/** 
* @return ArrayCollection|Review[] 
*/ 
public function getReviews() 
{ 
    return $this->reviews; 
} 
// Notice here you don't need the setReviews() setter! 



# AppBundle/Entity/Review.php 
use AppBundle\Entity\Book; 
... 
class Review 
... 
/** 
* @ORM\ManyToOne(targetEntity="Book", inversedBy="reviews") 
*/ 
private $book; 
//... getters and setters for extra fields you might have 
/** 
* @return Review 
*/ 
public function getBook() 
{ 
    return $this->book; 
} 

/** 
* Notice here is passed the entire book object 
* @param Book $book 
* @return $this 
*/ 
public function setBook(Book $book) 
{ 
    $this->book = $book; 
    return $this; 
} 

3) применять эти отношения путем создания миграции или с помощью doctrine:schema:update --force команды.

4) Создание форм, на основе сущностей

-> BookType: php bin/console doctrine:generate:form AppBundle:Book

-> ReviewType: php bin/console doctrine:generate:form AppBundle:Review, и вы должны использовать EntityType для того, чтобы получить книгу, принадлежащую этому массиву обзоров.

# AppBundle/Form/ReviewType.php 
use Symfony\Bridge\Doctrine\Form\Type\EntityType; 
use Doctrine\ORM\EntityRepository; 
... 
class ReviewType extends AbstractType 
... 
->add('book', EntityType::class, [ 
    'class' => 'AppBundle:Book', 
    'placeholder' => ' ', 
    'query_builder' => function(EntityRepository $er) { 
     return $er->createQueryBuilder('b'); 
    }, 
    'choice_label' => function($book){ 
     return $book->getId();// in the <select> options put the ids from Book entity 
    }, 
    'multiple' => false, // a user can select only one option per submission 
    'expanded' => false // options will be presented in a <select> dropdown; set this to true, to present the data in checkboxes 
]) 

5) Действие для создания и сохранения книги, в контроллере:

# AppBundle/Controller/DefaultController.php 
use AppBundle\Entity\Book; 
use AppBundle\Form\BookType; 
... 
/** 
* @Route("/book", name="book") 
*/ 
public function bookAction(Request $request) 
{ 
    $book = new Book(); 
    $form = $this->createForm(BookType::class, $book, [ 
     'action' => $this->generateUrl('book'), 
     'method' => 'POST' 
    ]); 
    $form->handleRequest($request); 
    if ($form->isSubmitted() && $form->isValid()) { 
     $em = $this->getDoctrine()->getManager(); 
     $em->persist($book); 
     $em->flush(); 

     return $this->redirectToRoute('book'); 
    } 
    return $this->render('default/book.html.twig', ['form'=>$form->createView()]); 
} 

6) Действие для создания и сохранения обзора в контроллере

# AppBundle/Controller/DefaultController.php 
use AppBundle\Entity\Review; 
use AppBundle\Form\ReviewType; 
... 
/** 
* @Route("/review", name="review") 
*/ 
public function reviewAction(Request $request) 
{ 
    $review = new Review(); 
    $form = $this->createForm(ReviewType::class, $review, [ 
     'action' => $this->generateUrl('review'), 
     'method' => 'POST' 
    ]); 
    $form->handleRequest($request); 
    if ($form->isSubmitted() && $form->isValid()) { 
     $em = $this->getDoctrine()->getManager(); 
     $em->persist($review); 
     $em->flush(); 

     return $this->redirectToRoute('review'); 
    } 
    return $this->render('default/review.html.twig', ['form'=>$form->createView()]); 
} 

7) Для отображения отзывов для определенной книги:

# AppBundle/Controller/DefaultController.php 
/** 
* @Route("/", name="homepage") 
*/ 
public function indexAction() 
{ 
    $reviews = $this->getDoctrine()->getRepository('AppBundle:Review')->findAll(); 

    if (!$reviews) { 
     throw $this->createNotFoundException('No review(s) found!'); 
    } 

    return $this->render('default/index.html.twig',['reviews'=>$reviews]); 
} 

8) Вид, чтобы отобразить отзывы (для книги и обзора, просто распечатать формы, поэтому я не буду размещать код, как это тривиально)

# app/Resources/views/default/index.html.twig 
{% extends 'base.html.twig' %} 

{% block body %} 
    {% for review in reviews %} 
     {{ review.comment ~ '-' ~ review.book.name }} 
    {% endfor %} 
{% endblock %} 
Смежные вопросы