Symfony 4 - form->isValid() return false ale nie pokazuje błędów

0

Cześć,
Mam kolejny problem z symfony i fosrestbundle
Przesyłam takie dane:

{
  "name": "asd",
  "nameKey": "AS",
  "description": "Simple desc", 
  "priority": "1",
  "deadline": "2016-09-01 21:02:20",
  "active": true,
  "assignedCustomers": {},
  "assignedUsers": {}
}

Do kontrolera:

/**
     * @FOSRest\Post("/project")
     */
    public function postProjectAction(Request $request)
    {
        $project = new Project();

        $project->setCreatedBy($this->getUser()->getUser());
        
        $project->setCreatedAt(new \DateTime());

        $form = $this->createForm(ProjectType::class, $project);

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

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($project);
            $em->flush();
            return new JsonResponse([
                'status' => 'created'
            ], 200);
        }
        return new JsonResponse($form->getErrors(true, false), 400);
    }

$form->isValid usilnie zwraca false ($form->isSubmitted() zwraca true), niestety w odpowiedzi w której powinny być błędy dostaję tylko pustą tablicę.
ProjectType:

class ProjectType extends AbstractType
{
    private $priorityToNumberTransformer;
    private $userToNumberTransformer;
    private $customerToNumberTransformer;

    public function __construct(PriorityToNumberTransformer $priorityToNumberTransformer, UserToNumberTransformer $userToNumberTransformer, CustomerToNumberTransformer $customerToNumberTransformer)
    {
        $this->priorityToNumberTransformer = $priorityToNumberTransformer;
        $this->userToNumberTransformer = $userToNumberTransformer;
        $this->customerToNumberTransformer = $customerToNumberTransformer;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class,
                [
                    'label' => 'label.name'
                ]
            )
            ->add('nameKey', TextType::class,
                [
                    'label' => 'label.nameKey'
                ]
            )
            ->add('description', TextareaType::class,
                [
                    'label' => 'label.description'
                ]
            )
            ->add('deadline', DateTimeType::class,
                [
                    'label' => 'label.deadline',
                    'widget' => 'single_text',
                    'html5' => false,
                    'attr' => [
                        'class' => 'bootstrap-datetimepicker'
                    ],
                    'format' => 'yyyy-mm-dd HH:ii'
                ]
            )
            ->add('active', ChoiceType::class,
                [
                    'label' => 'label.active',
                    'choices' => [
                        'label.yes' => true,
                        'label.no' => false
                    ]
                ]
            )
            ->add('priority', EntityType::class,
                [
                    'class' => Priority::class,
                    'choice_label' => 'name',
                    'label' => 'label.priority',
                ]
            )
            ->add('assignedUsers', EntityType::class, 
                [
                    'class' => User::class,
                    'choice_label' => 'email',
                    'label' => 'label.',
                    'multiple' => true,
                ]
            )
            ->add('assignedCustomers', EntityType::class, 
                [
                    'class' => Customer::class,
                    'choice_label' => 'email',
                    'label' => 'label.',
                ]
            )
        ;

        $builder->get('priority')->addModelTransformer($this->priorityToNumberTransformer);
        $builder->get('assignedUsers')->addModelTransformer($this->userToNumberTransformer);
        $builder->get('assignedCustomers')->addModelTransformer($this->customerToNumberTransformer);
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Project::class,
        ]);
    }
}

Dodam że dokładnie to samo przy użyciu zwykłego formularza działa bez problemu.
Macie jakiś pomysł dlaczego nie zwraca błędów lub podpowiecie mi jaka klasa realnie sprawdza form (abym mógł ją zdebugować)

0

Czesc,

Dzieje sie tak po symfony serializer/jms nie widza jak maja serializowac obiekt zwrocony poprzez $form->getErrors() wiec sam go musisz sobie serializowac jak ci pasuje
https://www.google.it/search?client=opera&q=symfony+serialize+form+errors&sourceid=opera&ie=UTF-8&oe=UTF-8

0

@marcio: Dzięki wielkie za pomoc. Po napisaniu mega prostego serializera:

static function FormSerializer(Form $form)
	{
		$errorCollection = array();
		foreach($form->getErrors() as $error){
		     $errorCollection[$error->getOrigin()->getName()] = $error->getMessage();
		}

        return $errorCollection;
	}

Formularz zaczął zgłaszać mi błąd którym był brak tokena csrf. Wyłączyłem csrf po czym znów $form->isValid() zwraca false, natomiast nie zwraca błędów (dodam że w momencie jak zaczął zgłaszać nie pasował mu tylko brak tokena). Masz może jakiś pomysł?

Dodam że na wszelki sprawdziłem jeszcze co zwróci gdy przepuszczę $form->getErrors() przez serializery symfony (Symfony\Component\Serialize) tu również pusta tablica. Puściłem również po prostu obiekt $form i dostałem:

"{"name":[],"nameKey":[],"description":[],"deadline":[],"active":[],"priority":[],"assignedUsers":[],"assignedCustomers":[]}"

0

@marcio:
Entity/Project.php:

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ProjectRepository")
 */
class Project
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=140)
     * @Assert\NotBlank()
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=5)
     * @Assert\NotBlank()
     */
    private $nameKey;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    private $description;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="assignedProjects")
     * @ORM\JoinColumn(nullable=false)
     */
    private $createdBy;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Priority")
     * @ORM\JoinColumn(nullable=false)
     */
    private $priority;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\User", inversedBy="projects")
     */
    private $assignedUsers;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $deadline;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Customer", inversedBy="projects")
     */
    private $assignedCustomers;

    /**
     * @ORM\Column(type="boolean")
     */
    private $active;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Task", inversedBy="assignedProject")
     */
    private $tasks;

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    public function __construct()
    {
        $this->assignedUsers = new ArrayCollection();
        $this->assignedCustomers = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getNameKey(): ?string
    {
        return $this->nameKey;
    }

    public function setNameKey(string $nameKey): self
    {
        $this->nameKey = $nameKey;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): self
    {
        $this->description = $description;

        return $this;
    }

    public function getCreatedBy(): ?User
    {
        return $this->createdBy;
    }

    public function setCreatedBy(?User $createdBy): self
    {
        $this->createdBy = $createdBy;

        return $this;
    }

    public function getPriority()
    {
        return $this->priority;
    }

    public function setPriority($priority): self
    {
        $this->priority = $priority;

        return $this;
    }

    /**
     * @return Collection|User[]
     */
    public function getAssignedUsers()
    {
        return $this->assignedUsers;
    }

    public function addAssignedUser(User $assignedUser): self
    {
        if (!$this->assignedUsers->contains($assignedUser)) {
            $this->assignedUsers[] = $assignedUser;
        }

        return $this;
    }

    public function removeAssignedUser(User $assignedUser): self
    {
        if ($this->assignedUsers->contains($assignedUser)) {
            $this->assignedUsers->removeElement($assignedUser);
        }

        return $this;
    }

    public function getDeadline(): ?\DateTimeInterface
    {
        return $this->deadline;
    }

    public function setDeadline(?\DateTimeInterface $deadline): self
    {
        $this->deadline = $deadline;

        return $this;
    }

    /**
     * @return Collection|Customer[]
     */
    public function getAssignedCustomers()
    {
        return $this->assignedCustomers;
    }

    public function addAssignedCustomer(Customer $assignedCustomer): self
    {
        if (!$this->assignedCustomers->contains($assignedCustomer)) {
            $this->assignedCustomers[] = $assignedCustomer;
        }

        return $this;
    }

    public function removeAssignedCustomer(Customer $assignedCustomer): self
    {
        if ($this->assignedCustomers->contains($assignedCustomer)) {
            $this->assignedCustomers->removeElement($assignedCustomer);
        }

        return $this;
    }

    public function getActive(): ?bool
    {
        return $this->active;
    }

    public function setActive(bool $active): self
    {
        $this->active = $active;

        return $this;
    }

    public function getTasks(): ?Task
    {
        return $this->tasks;
    }

    public function setTasks(?Task $tasks): self
    {
        $this->tasks = $tasks;

        return $this;
    }

    public function getCreatedAt(): ?\DateTimeInterface
    {
        return $this->createdAt;
    }

    public function setCreatedAt(\DateTimeInterface $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }
}

Dodam że jeśli pominę $form->isValid() bez problemu dodaje wpis do bazy.
Normalny formularz działał bez problemu, try/catch nic nie łapie.

0

Domyślam się, że kolejność ma znaczenie. Spróbuj tak:

/**
 * @FOSRest\Post("/project")
 */
public function postProjectAction(Request $request)
{
    $project = new Project();

    $form = $this->createForm(ProjectType::class, $project);

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

    $project->setCreatedBy($this->getUser()->getUser());
    $project->setCreatedAt(new \DateTime());

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($project);
        $em->flush();
        
        return new JsonResponse([
            'status' => 'created'
        ], 200);
    }
    
    return new JsonResponse($form->getErrors(true, false), 400);
}

Tych pól nie masz w formularzu, dlatego nie wywala Ci błędu.

PS. Czemu nie używasz $form->handleRequest($request);?

0
arczinosek napisał(a):

Domyślam się, że kolejność ma znaczenie. Spróbuj tak:

/**
 * @FOSRest\Post("/project")
 */
public function postProjectAction(Request $request)
{
    $project = new Project();

    $form = $this->createForm(ProjectType::class, $project);

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

    $project->setCreatedBy($this->getUser()->getUser());
    $project->setCreatedAt(new \DateTime());

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($project);
        $em->flush();
        
        return new JsonResponse([
            'status' => 'created'
        ], 200);
    }
    
    return new JsonResponse($form->getErrors(true, false), 400);
}

Tych pól nie masz w formularzu, dlatego nie wywala Ci błędu.

PS. Czemu nie używasz $form->handleRequest($request);?

Przy takiej kolejności zachowanie jest takie samo, tz zwraca []. używam $form->submit() bo tak przeczytałem

EDIT
Po instalacji profilera wszystko dość mocno się rozjaśniło. Okazało się że mam coś nie tak z 2 wartościami, jednakże nadal nie wiem czemu nie są one pokazywane po $form->getErrors(). Macie jakieś pomysły?

1 użytkowników online, w tym zalogowanych: 0, gości: 1