我目前正在学习PHP和Symfony。我正在尝试用登录用户创建的食谱制作食谱。在我的食谱创建页面中,我的表单类型包含几个TextType
,CollectionType
和SubmitType
。
这个想法是,当用户创建食谱时,他/她可以向创建的食谱添加成分列表。我的问题是我不能坚持我创建的实体数组。我收到这条消息:
类型" Doctrine \ Common \ Collections \ Collection | array"的预期值对于协会领域" AppBundle \ Entity \ Recipe#$ ingredients",得到"字符串"代替。
我尝试创建addIngredient()
函数,并在ArrayCollection
函数中创建了一个新的__construct()
。我不知道这是不是我长时间盯着这个问题。
以下是我的实体:
配方实体
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
*@ORM\Entity
*@ORM\Table(name="Recipees")
*/
class Recipe{
/**
*@ORM\Id
*@ORM\GeneratedValue(strategy="AUTO")
*@ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="recipe")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id",
* nullable=false, onDelete="CASCADE")
*/
private $user;
/**
*@ORM\Column(type="string", name="title", length=100)
*/
private $title;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ingredients",
* mappedBy="recipe")
* @ORM\JoinTable(name="ingredients")
*/
private $ingredients;
/**
*@ORM\Column(type="text", name="instructions")
*/
private $instructions;
/**
*@ORM\Column(type="datetime", name="created_at")
*@ORM\GeneratedValue(strategy="AUTO")
*/
private $created_at;
/**
*@ORM\Column(type="datetime", name="modified_at")
*@ORM\GeneratedValue(strategy="AUTO")
*/
private $modified_at;
public function __construct() {
$this->ingredients = new ArrayCollection();
$this->created_at = new \DateTime();
$this->modified_at = new \DateTime('now');
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* @param string $title
*
* @return Recipe
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @return mixed
*/
public function getIngredients()
{
return $this->ingredients;
}
public function addIngredients($ingredients){
$this->ingredients->add($ingredients);
return $this;
}
/**
* @param mixed $ingredients
*/
public function setIngredients($ingredients)
{
$this->ingredients = $ingredients;
}
/**
* Set instructions
*
* @param string $instructions
*
* @return Recipe
*/
public function setInstructions($instructions)
{
$this->instructions = $instructions;
return $this;
}
/**
* Get instructions
*
* @return string
*/
public function getInstructions()
{
return $this->instructions;
}
/**
* Set createdAt
*
* @param \DateTime $createdAt
*
* @return Recipe
*/
public function setCreatedAt($createdAt)
{
$this->created_at = $createdAt;
return $this;
}
/**
* Get createdAt
*
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->created_at;
}
/**
* Set modifiedAt
*
* @param \DateTime $modifiedAt
*
* @return Recipe
*/
public function setModifiedAt($modifiedAt)
{
$this->modified_at = $modifiedAt;
return $this;
}
/**
* Get modifiedAt
*
* @return \DateTime
*/
public function getModifiedAt()
{
return $this->modified_at;
}
/**
* Set rUser
*
* @param \AppBundle\Entity\User $user
*
* @return Recipe
*/
public function setUser(User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get rUser
*
* @return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
}
成分实体
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="ingrediens")
*/
class Ingredients
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Recipe", inversedBy="ingredients")
* @ORM\JoinColumn(name="recipe_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
*/
private $recipe;
/**
* @ORM\Column(type="string", length=50)
*
*/
private $name;
/**
* @return mixed
*/
public function getRecipe()
{
return $this->recipe;
}
/**
* @param mixed $recipe
*/
public function setRecipe($recipe)
{
$this->recipe = $recipe;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
我的控制器
use AppBundle\Entity\Ingredients;
use AppBundle\Entity\Recipe;
use AppBundle\Form\AddRecipeFormType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class RecipeController extends Controller
{
/**
* @Route("/recipe/new", name = "newRecipe")
*/
public function addRecipe(Request $request){
$ingredients = new Ingredients();
$recipe = new Recipe();
$user = $this->getUser();
$recipe->setUser($user);
$formRecipe = $this->createForm(AddRecipeFormType::class, $recipe);
$formRecipe->handleRequest($request);
if ($formRecipe->isSubmitted() && $formRecipe->isValid()){
$em = $this->getDoctrine()->getManager();
$recipe->addIngredients($ingredients);
$em->persist($recipe);
$em->flush();
dump($recipe);
die;
// return $this->redirectToRoute('fos_user_profile_show');
}
return $this->render('/CookBook/addRecipe.html.twig', [
'newRecipe' => $formRecipe->createView(),
]);
}
我的表格
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AddRecipeFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class)
->add('ingredients', CollectionType::class, array(
'entry_type' => TextType::class,
'allow_add' => true,
'prototype' => true
))
->add('instructions', TextareaType::class)
->add('submit', SubmitType::class, array('label' => 'Create Recipe'));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data' => 'AppBundle\Entity\Recipe']);
}
public function getBlockPrefix()
{
return 'app_bundle_new_recipe_form_type';
}
}
My Twig(如果有帮助的话)
{% extends 'base.html.twig' %}
{% block body %}
<h1>Create your own Recipe</h1>
{{ form_start (newRecipe) }}
{{ form_row(newRecipe.title) }}
<ul id="ingredient-fields-list"
data-prototype="{{ form_row(newRecipe.ingredients.vars.prototype)|e }}">
{% for Recipe in newRecipe.ingredients %}
<li>
{{ form_errors(newRecipe.ingredients) }}
{{ form_row(newRecipe.ingredients) }}
</li>
{% endfor %}
</ul>
<a href="#" id="add-another-ingredient">Add Ingredient</a>
{{ form_widget(newRecipe) }}
{{ form_end(newRecipe) }}
{% endblock %}
{% block javascripts %}
<script type="text/javascript">
// keep track of how many email fields have been rendered
var IngredientCount = '{{ newRecipe.ingredients|length }}';
jQuery(document).ready(function() {
jQuery('#add-another-ingredient').click(function(e) {
e.preventDefault();
var ingredientList = jQuery('#ingredient-fields-list');
// grab the prototype template
var newWidget = ingredientList.attr('data-prototype');
// replace the "__name__" used in the id and name of the prototype
// with a number that's unique to your emails
// end name attribute looks like name="contact[emails][2]"
newWidget = newWidget.replace("Ingredients", IngredientCount);
IngredientCount++;
// create a new list element and add it to the list
var newLi = jQuery('<li></li>').html(newWidget);
newLi.appendTo(ingredientList);
});
})
</script>
{% endblock %}
答案 0 :(得分:0)
在Recipe中尝试这个
public function addIngredients($ingredients){
$this->ingredients[] = $ingredients;
$ingredients->setRecipe($this);
答案 1 :(得分:0)
使用此
更改您的表单public function buildForm(FormBuilderInterface $builder, array $options) {
$builder ->add('title', TextType::class)
->add('ingredients', CollectionType::class, array( 'entry_type' => EntityType::class,
'allow_add' => true, 'prototype' => true ))
->add('instructions', TextareaType::class)
->add('submit', SubmitType::class, array('label' => 'Create Recipe'));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Ingredients::class,
));
}