Tompo
Tompo

Reputation: 341

400 Bad Request Symfony 3 with Angular

I'm trying to figure out what am I doing wrong. I'm getting 400 bad request trying to send a post request via angular service. I have 2 entities - Document and DocumentCategory (many to many relation). I can post document itself (without categories) with no problem.

document-create.component.ts

createDocument(title, body, categories) {
    let document = {title: title, body: body, categories: categories};
    this._crudService.createDocument(document).subscribe(
        data => {
            return true;
        },
        error => {
            console.error("Error saving document! " + error);
            return Observable.throw(error);
        }
    );
} 

crudService.ts

createDocument(document) {
    let headers = new Headers({'Content-Type': 'application/json'});
    let options = new RequestOptions({headers: headers});
    //let body = JSON.stringify(document);
    let body = document;
    return this.http.post
        ('http://localhost:8000/documents', body, headers);
}

The form

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
            ->add('title', TextType::class)
            ->add('body', TextType::class)
            //->add('categories', TextType::class)
            ->add('categories', EntityType::class, array(
                'class' => 'AppBundle:DocumentCategory',
                'multiple' => true,
                'expanded' => true,
                'by_reference' => false,
                'choice_label' => 'id',
            ))
    ;
}

Document.php

/**
 * @ORM\ManyToMany(targetEntity="DocumentCategory", mappedBy="documents") 
 * @JMSSerializer\Expose
 */
private $categories;

DocumentCategory.php

/**
 * @ORM\ManyToMany(targetEntity="Document", inversedBy="categories")
 * @ORM\JoinTable(name="document_category_document")
 * @JMSSerializer\Expose
 */
private $documents;

Request

POST /documents HTTP/1.1 Accept: application/json, text/plain, / Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.8 Connection: keep-alive Content-Length: 213 Content-Type: application/json Host: localhost:8000 Origin: http://localhost:4200 Referer: http://localhost:4200/admin/document/create User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 X-Php-Ob-Level: 1

{
  "title": "t",
  "body": "<p>b</p>",
  "categories": [
    {
      "id": 1,
      "name": "cat1",
      "documents": []
    },
    {
      "id": 2,
      "name": "cat2",
      "documents": []
    }
  ]
}

As I said if I remove categories, everything works. I can't figure it out :(

EDIT: Postman shows this in response when I try to send above json as application/json:

{
  "children": {
    "title": {},
    "body": {},
    "categories": {
      "errors": [
        "This value is not valid."
      ],
      "children": {
        "1": {},
        "2": {},
        "3": {},
        "4": {}
      }
    }
  }
}

Upvotes: 0

Views: 1335

Answers (1)

Tompo
Tompo

Reputation: 341

After looong time I finally made it. Here's my result in case someone has a simmilar problem. It's not the most elegant solution and I will try to find a better one but at least it works. The problem was in controller. Now the post method looks like this:

public function postAction(Request $request) { 
    $form = $this->createForm(DocumentType::class, null, [
        'csrf_protection' => false,
    ]);
    $form->submit($request->request->all());
    if (!$form->isValid()) {
        return $form;
    }

    $em = $this->getDoctrine()->getManager();
    $document = $form->getData();
    $categories = $request->request->get('categories'); 

    foreach ($categories as $categoryId) {
        $category = $em->getRepository('AppBundle:DocumentCategory')->find((int)$categoryId['id']);
        $category->addDocument($document);
        $document->addCategory($category);
        $em->persist($category);            
    }

    $em->persist($document);
    $em->flush();

    $routeOptions = [
        'id' => $document->getId(),
        '_format' => $request->get('_format'),
    ];

    return $this->routeRedirectView('get_document', $routeOptions, Response::HTTP_CREATED);
}

And my form is simply:

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
            ->add('title', TextType::class)
            ->add('body', TextType::class)
    ;         
}

Upvotes: 0

Related Questions