Php symfony 4创建多对多关系和嵌入表单无法正常工作
我创建了两个实体。第一类员额和第二类员额。该实体具有多对多关系。 我从帖子中创建表单,并添加使用ChoiceType的嵌入表单类别。 该表单工作正常,我可以为每个帖子添加多达多个类别。 但是在数据库orm中创建一个posts\u categories当我查看它的数据时,posts\u id是正确的,并且来自posts表,但是我不知道categories\u id来自哪里 我是指未保存在posts\u categories表中的类别的真实id。这个身份证从哪里来?我如何配置表上保存的真实id App\Entity\Posts.phpPhp symfony 4创建多对多关系和嵌入表单无法正常工作,php,symfony,many-to-many,symfony4,formbuilder,Php,Symfony,Many To Many,Symfony4,Formbuilder,我创建了两个实体。第一类员额和第二类员额。该实体具有多对多关系。 我从帖子中创建表单,并添加使用ChoiceType的嵌入表单类别。 该表单工作正常,我可以为每个帖子添加多达多个类别。 但是在数据库orm中创建一个posts\u categories当我查看它的数据时,posts\u id是正确的,并且来自posts表,但是我不知道categories\u id来自哪里 我是指未保存在posts\u categories表中的类别的真实id。这个身份证从哪里来?我如何配置表上保存的真实id Ap
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\PostsRepository")
*/
class Posts
{
public $newFormTitle = 'Add New Post';
public $editFormTitle = 'Edit Post';
public $listFormTitle = 'Posts List';
public $adminList = 'postList';
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=200)
*/
private $title;
/**
* @ORM\Column(type="text")
*/
private $content;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Categories" , orphanRemoval=true, cascade={"persist"})
*/
private $categories;
public function __construct()
{
$this->categories = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(?string $content): self
{
$this->content = $content;
return $this;
}
/**
* @return Collection|Categories[]
*/
public function getCategories(): Collection
{
return $this->categories;
}
public function addCategory(Categories $category): self
{
if (!$this->categories->contains($category)) {
$this->categories[] = $category;
}
return $this;
}
public function removeCategory(Categories $category): self
{
if ($this->categories->contains($category)) {
$this->categories->removeElement($category);
}
return $this;
}
}
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\CategoriesRepository")
*/
class Categories
{
public $newFormTitle = 'Add New Post';
public $editFormTitle = 'Edit Post';
public $listFormTitle = 'Categories List';
public $adminList = 'categoriesList';
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=100)
*/
private $name;
public function __construct()
{
}
public function getId()
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
<?php
namespace App\Form;
use App\Entity\Posts;
use App\Form\CategoriesPostsType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class PostsType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', null, [
'attr' => ['autofocus' => true ,'class'=>'form-control'],
'label' => 'label.title',
'label_attr' => ['class'=>'label-control'],
])
->add('content', null, [
'attr' => ['rows' => 8 ,'class'=>'form-control'],
'label' => 'label.content',
'label_attr' => ['class'=>'label-control'],
])
;
/*
$builder->add('categories', CollectionType::class, array(
'entry_type' => CategoryType::class,
'entry_options' => array('label' => false),
'allow_add' => true,
));
*/
$builder->add('categories', CollectionType::class, array(
'entry_type' => CategoriesPostsType::class,
'entry_options' => array('label' => false),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => true,
'label' => false,
));
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Posts::class,
]);
}
}
<?php
namespace App\Form;
use App\Entity\Categories;
use App\Form\Type\CategoryInputType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use App\Repository\CategoriesRepository;
class CategoriesPostsType extends AbstractType
{
private $categories;
public function __construct(CategoriesRepository $category)
{
$categories = $category->findAll();
$choise = array();
foreach ($categories as $key => $value)
//$choise[] = new Categories($categories[$key]->getId();
$choise[$categories[$key]->getName()] = $categories[$key]->getId();
$this->categories = $choise;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', ChoiceType::class, [
'attr' => ['autofocus' => true ,'class'=>'form-detail-control formChoiceType'],
'label' => false,
'label_attr' => ['class'=>'label-control'],
'choices' => $this->categories,
])
/* ->add('category', CategoryInputType::class, [
'label' => 'label.category',
'required' => false,
])*/
;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Categories::class,
]);
}
}
为什么要“配置”生成的类别id?您在类别实体中指定了@ORM\GeneratedValue()。因此,您的数据库会生成id(例如,如果MySQL使用自动增量),我不想生成id?我希望在我的表中,为我创建多对多关系的类别插入正确的类别id。我不知道该id是如何生成的,它保存在哪里,我再次担心我的答案。它是由DBMS生成的,因为您在类别实体中指定了@ORM\GeneratedValue()。因此,例如MySQL使用自动增量在category表中为您的类别生成id。完成后,它将使用posts\u categories表中的id添加关系。
{% extends 'theme/basickTheme/form.html.twig' %}
{% block body_id 'content_new_posts' %}
{% block defaultFormHeader entity.newFormTitle %}
{% block defaultFormBody %}
<div class="row">
<div class="col-12">
{{ form_start(form) }}
<div class="col-12">
{{ form_errors(form) }}
</div>
<div class="col-12">
{{ form_row(form.title) }}
</div>
<div class="col-12">
{{ form_row(form.content) }}
</div>
<div class="col-12 form-group">
<h3>Categories</h3>
</div>
<div class="col-12">
<button type="button" class="btn add-detail-botton" onclick="addCategoriesForm(1)">
<img src="{{ asset('img/custum-icon/add-small.png') }}">
<i class="fa fa-save" aria-hidden="true"></i> {{ button_label|default('categories.label.add.category'|trans) }}
</button>
<ol class="detail-list" data-prototype="{{ form_widget(form.categories.vars.prototype)|e('html_attr') }}">
{# iterate over each existing tag and render its only field: name #}
{% for Category in form.categories %}
<li>{{ form_widget(Category.name) }}</li>
{% endfor %}
</ol>
<button type="button" class="btn add-detail-botton" onclick="addCategoriesForm(2)">
<img src="{{ asset('img/custum-icon/add-small.png') }}">
<i class="fa fa-save" aria-hidden="true"></i> {{ button_label|default('categories.label.add.category'|trans) }}
</button>
</div>
<div class="col-12 form-footer-botton">
<button type="submit" class="btn btn-primary">
<i class="fa fa-save" aria-hidden="true"></i> {{ button_label|default('Label.save'|trans) }}
</button>
<a href="{{ backUrl }}" class="btn btn-primary">
<i class="fa fa-list-alt" aria-hidden="true"></i> {{ 'Label.back.to.list'|trans }}
</a>
</div>
{{ form_end(form) }}
</div>
</div>
{% endblock %}
{% block javascripts %}`
<script>
var $collectionHolder;
jQuery(document).ready(function() {
// Get the ul that holds the collection of tags
$collectionHolder = $('ol.detail-list');
$collectionHolder.find('li').each(function() {
addCategoriesFormDeleteLink($(this));
});
// count the current form inputs we have (e.g. 2), use that as the new
// index when inserting a new item (e.g. 2)
$collectionHolder.data('index', $collectionHolder.find(':input').length);
});
function addCategoriesForm( $appendType = 1) {
var $collectionHolder = $('ol.detail-list');
// Get the data-prototype explained earlier
var prototype = $collectionHolder.data('prototype');
// get the new index
var index = $collectionHolder.data('index');
var newForm = prototype;
// You need this only if you didn't set 'label' => false in your tags field in TaskType
// Replace '__name__label__' in the prototype's HTML to
// instead be a number based on how many items we have
// newForm = newForm.replace(/__name__label__/g, index);
// Replace '__name__' in the prototype's HTML to
// instead be a number based on how many items we have
newForm = newForm.replace(/__name__/g, index);
newForm = newForm.replace(/form-detail-control/g, 'form-detail-control-new');
// increase the index with one for the next item
$collectionHolder.data('index', index + 1);
// Display the form in the page in an li, before the "Add a tag" link li
var $newFormLi = $('<li class="prototye"></li>').prepend(newForm);
if($appendType == 1)
$collectionHolder.prepend($newFormLi);
else
$collectionHolder.append($newFormLi);
//$newLinkLi.before($newFormLi);
addCategoriesFormDeleteLink($newFormLi);
}
function addCategoriesFormDeleteLink($tagFormLi) {
//var $removeFormButton = $('<button type="button" class="detailDeleteButton">Delete</button>');
var $removeFormButton = $('<button type="button" class="btn delte-detail-botton"><img src="{{ asset('img/custum-icon/delete-smal.png') }}"><i class="fa fa-save" aria-hidden="true"></i>{{ button_label|default('categories.label.delete.category'|trans) }}</button>');
$tagFormLi.append($removeFormButton);
$removeFormButton.on('click', function(e) {
// remove the li for the tag form
$tagFormLi.remove();
});
}
</script>
{% endblock %}