Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving ManyToOne-Relationships with Symfony an FOSRestBundle

I'm using symfony with FOSRestBundle for my project. I made this example out of my code to reduce complexity. maybe forgot to rename a variable.

I have problems saving a article that has ONE category. the categories are already existing in the database. I don't want to create new categories

I'm not sure what's the best practice to do the job. so I tried a few ways and documented the error messages (see The Form-Type)

The Entities

class Article
{
  private $id;
  private $name;
  /* this is ManyToOne */
  private $category;

  function getId() {/* ... */}
  function setName($name) {/* ... */}
  function getName() {/* ... */}
  function setCategory(Category $cat) {/* ... */}
  function getCategory() {/* ... */}
}

class Category
{
  private $id;
  private $name;

  function getId() {/* ... */}
  function setName($name) {/* ... */}
  function getName() {/* ... */}
}

The JSON POST

{
  "name": "testName"
  "category": {
    "name": "nameOfAExistingCategory"
  }
}

The Form-Type

class ArticleType extends AbstractType
{
  /**
   * @param FormBuilderInterface $builder
   * @param array $options
   */
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
      $builder
          ->add('name')

          // here i tried out several ways of saving the category
          ->add('category')
          // error-message
          //Argument 1 passed to AppBundle\\Entity\\Article::setCategory() must be an instance of AppBundle\\Entity\\Category, array given, called in \...../vendor\/symfony\/symfony\/src\/Symfony\/Component\/PropertyAccess\/PropertyAccessor.php on line 410 and defined",

          // OR
          ->add('category', new CategoryType())
          // error-message
          // A new entity was found through the relationship 'AppBundle\\Entity\\Article#category' that was not configured to cascade persist operations for entity: AppBundle\\Entity\\Category@000000000c958844000000003bf8ec58. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist  this association in the mapping for example @ManyToOne(..,cascade={\"persist\"}). If you cannot find out which entity causes the problem implement 'AppBundle\\Entity\\Category#__toString()' to get a clue


          // OR
          ->add('category', 'entity', array(
              'class' => 'AppBundle:Category',
          ))
          // error-message
          // message":"category:\n                    ERROR: This value is not valid
      ;
  }

  /* ... */
}

The Controller

public function postAction(Request $request) {
  $form = $this->createForm(
      new ArticleType(),
      new Article(),
      array('method' => 'POST'));

  $form->submit($request->request->all());

  if (!$form->isValid()) {
      throw new HttpException(Codes::HTTP_BAD_REQUEST, $form->getErrors(true, false));
  }

  $em = $this->getDoctrine()->getManager();

  $article = $form->getData();
  $em->persist($article);
  $em->flush();

  return $article;
}
like image 425
MontyBurns Avatar asked Nov 21 '25 14:11

MontyBurns


1 Answers

Here is the working example:

The Entities

class Article
{
  ...
  private $category;

  ...
  function setCategory(Category $cat) {/* ... */}
  function getCategory() {/* ... */}
}

class Category
{
  private $id;

  ...

  function getId() {/* ... */}
}

The JSON POST

{
  "name": "testName",
  "category": 1
}

The Form-Type

public function buildForm(FormBuilderInterface $builder, array $options)
{
  $builder
      ->add('name')
      ->add('category', 'entity', [
        'class' => CATEGORY_CLASS,
        'property' => 'id'
      ])
  ;
}

The Controller

public function postAction(Request $request) {
  $article = new Article();
  $form = $this->createForm(
      new ArticleType(),
      $article,
      array('method' => 'POST'));

  $form->handleRequest($request);

  if (!$form->isValid()) {
      throw new HttpException(Codes::HTTP_BAD_REQUEST, $form->getErrors(true, false));
  }

  if ($form->isValid()) {
    $em = $this->getDoctrine()->getManager();
    $em->persist($article);
    $em->flush();

    return $article; 
  }

  return $form;
}
like image 149
xurshid29 Avatar answered Nov 23 '25 04:11

xurshid29