Symfony 5.4 - How to fix Neither the property nor one of the methods exist and have public access in class "Symfony\Component\Form\FormView"?

74 views Asked by At

I'm having trouble understanding what I'm doing wrong here. I have a "Project" entity that has a relation (ManyToMany) with another entity, "Service". In turn, Service is related to a "Task" entity, which is itself related to a "Section" entity. In the ProjectType I create a form field using FormBuilder for the property that identifies the Project - Service relation. In the twig template I'm trying to access Service's properties. I can't seem to access the property "section" of the task property in Service.

Project entity

<?php
/**
 * App_Entity_Project
 */

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Eleva\BackofficeBundle\Entity\BaseEntity;
use App\Repository\ProjectRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class Project
 *
 * Main Project entity.
 * @author Eleva
 * @package App\Entity
 * @license © 2023 Eleva SRL
 * @ORM\Entity(repositoryClass=ProjectRepository::class)
 */
class Project extends BaseEntity
{
    /**
     * @var int|null $id
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

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

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $soReferral;

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

    /**
     * @ORM\ManyToOne(targetEntity=Customer::class, inversedBy="projects")
     * @ORM\JoinColumn(nullable=false)
     */
    private $customer;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $pm;

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

    /**
     * @ORM\ManyToMany(targetEntity=Service::class, inversedBy="projects")
     */
    private $services;

    /**
     * @ORM\OneToMany(targetEntity=ProjectProduct::class, mappedBy="project", cascade={"persist"})
     */
    private $projectProducts;

    public function __construct()
    {
        $this->services = new ArrayCollection();
        $this->projectProducts = new ArrayCollection();
    }

    /**
     * getId
     *
     * Returns the id value.
     */
    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 getSoReferral(): ?string
    {
        return $this->soReferral;
    }

    public function setSoReferral(?string $soReferral): self
    {
        $this->soReferral = $soReferral;

        return $this;
    }

    public function getNotes(): ?string
    {
        return $this->notes;
    }

    public function setNotes(?string $notes): self
    {
        $this->notes = $notes;

        return $this;
    }

    public function getCustomer(): ?Customer
    {
        return $this->customer;
    }

    public function setCustomer(?Customer $customer): self
    {
        $this->customer = $customer;

        return $this;
    }

    public function getPm(): ?string
    {
        return $this->pm;
    }

    public function setPm(?string $pm): self
    {
        $this->pm = $pm;

        return $this;
    }

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

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

        return $this;
    }

    /**
     * @return Collection<int, Service>
     */
    public function getServices(): Collection
    {
        return $this->services;
    }

    public function addService(Service $service): self
    {
        if (!$this->services->contains($service)) {
            $this->services[] = $service;
        }

        return $this;
    }

    public function removeService(Service $service): self
    {
        $this->services->removeElement($service);

        return $this;
    }

    /**
     * @return Collection<int, ProjectProduct>
     */
    public function getProjectProducts(): Collection
    {
        return $this->projectProducts;
    }

    public function addProjectProduct(ProjectProduct $projectProduct): self
    {
        if (!$this->projectProducts->contains($projectProduct)) {
            $this->projectProducts[] = $projectProduct;
            $projectProduct->setProject($this);
        }

        return $this;
    }

    public function removeProjectProduct(ProjectProduct $projectProduct): self
    {
        if ($this->projectProducts->removeElement($projectProduct)) {
            // set the owning side to null (unless already changed)
            if ($projectProduct->getProject() === $this) {
                $projectProduct->setProject(null);
            }
        }

        return $this;
    }
}

Service entity

<?php
/**
 * App_Entity_Service
 */

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Eleva\BackofficeBundle\Entity\BaseEntity;
use App\Repository\ServiceRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class Service
 *
 * Main Service entity.
 * @author Eleva
 * @package App\Entity
 * @license © 2023 Eleva SRL
 * @ORM\Entity(repositoryClass=ServiceRepository::class)
 */
class Service extends BaseEntity
{
    /**
     * @var int|null $id
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

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

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

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

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

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

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

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

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

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

    /**
     * @ORM\ManyToOne(targetEntity=JobPosition::class, inversedBy="services")
     */
    private $jobPosition;

    /**
     * @ORM\ManyToMany(targetEntity=Project::class, mappedBy="services")
     */
    private $projects;

    /**
     * @ORM\ManyToOne(targetEntity=Task::class, inversedBy="services")
     */
    private $task;

    /**
     * @ORM\Column(type="string", length=45)
     */
    private $overtime;

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

    /**
     * getId
     *
     * Returns the id value.
     */
    public function getId(): ?int
    {
        return $this->id;
    }

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

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

        return $this;
    }

    public function getEstimatedTime(): ?int
    {
        return $this->estimatedTime;
    }

    public function setEstimatedTime(?int $estimatedTime): self
    {
        $this->estimatedTime = $estimatedTime;

        return $this;
    }

    public function getEstimatedTimeAway(): ?int
    {
        return $this->estimatedTimeAway;
    }

    public function setEstimatedTimeAway(?int $estimatedTimeAway): self
    {
        $this->estimatedTimeAway = $estimatedTimeAway;

        return $this;
    }

    public function getNumberOfTechnicians(): ?int
    {
        return $this->numberOfTechnicians;
    }

    public function setNumberOfTechnicians(?int $numberOfTechnicians): self
    {
        $this->numberOfTechnicians = $numberOfTechnicians;

        return $this;
    }

    public function getTimeAwayTechnicians(): ?int
    {
        return $this->timeAwayTechnicians;
    }

    public function setTimeAwayTechnicians(?int $timeAwayTechnicians): self
    {
        $this->timeAwayTechnicians = $timeAwayTechnicians;

        return $this;
    }

    public function getTotalEstimatedHours(): ?int
    {
        return $this->totalEstimatedHours;
    }

    public function setTotalEstimatedHours(?int $totalEstimatedHours): self
    {
        $this->totalEstimatedHours = $totalEstimatedHours;

        return $this;
    }

    public function getActualTime(): ?int
    {
        return $this->actualTime;
    }

    public function setActualTime(?int $actualTime): self
    {
        $this->actualTime = $actualTime;

        return $this;
    }

    public function getHoursAway(): ?int
    {
        return $this->hoursAway;
    }

    public function setHoursAway(?int $hoursAway): self
    {
        $this->hoursAway = $hoursAway;

        return $this;
    }

    public function getActualHoursAway(): ?int
    {
        return $this->actualHoursAway;
    }

    public function setActualHoursAway(?int $actualHoursAway): self
    {
        $this->actualHoursAway = $actualHoursAway;

        return $this;
    }

    public function getJobPosition(): ?JobPosition
    {
        return $this->jobPosition;
    }

    public function setJobPosition(?JobPosition $jobPosition): self
    {
        $this->jobPosition = $jobPosition;

        return $this;
    }

    /**
     * @return Collection<int, Project>
     */
    public function getProjects(): Collection
    {
        return $this->projects;
    }

    public function addProject(Project $project): self
    {
        if (!$this->projects->contains($project)) {
            $this->projects[] = $project;
            $project->addService($this);
        }

        return $this;
    }

    public function removeProject(Project $project): self
    {
        if ($this->projects->removeElement($project)) {
            $project->removeService($this);
        }

        return $this;
    }

    public function getTask(): ?Task
    {
        return $this->task;
    }

    public function setTask(?Task $task): self
    {
        $this->task = $task;

        return $this;
    }

    public function getOvertime(): ?string
    {
        return $this->overtime;
    }

    public function setOvertime(string $overtime): self
    {
        $this->overtime = $overtime;

        return $this;
    }
}

Task entity

<?php
/**
 * App_Entity_Task
 */

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Eleva\BackofficeBundle\Entity\BaseEntity;
use App\Repository\TaskRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class Task
 *
 * Main Task entity.
 * @author Eleva
 * @package App\Entity
 * @license © 2023 Eleva SRL
 * @ORM\Entity(repositoryClass=TaskRepository::class)
 */
class Task extends BaseEntity
{
    /**
     * @var int|null $id
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

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

    /**
     * @ORM\ManyToOne(targetEntity=ServiceSection::class, inversedBy="tasks")
     * @ORM\JoinColumn(nullable=false)
     */
    private $section;

    /**
     * @ORM\OneToMany(targetEntity=Service::class, mappedBy="task", cascade={"persist"})
     */
    private $services;

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

    /**
     * getId
     *
     * Returns the id value.
     */
    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 getSection(): ?ServiceSection
    {
        return $this->section;
    }

    public function setSection(?ServiceSection $section): self
    {
        $this->section = $section;

        return $this;
    }

    /**
     * @return Collection<int, Service>
     */
    public function getServices(): Collection
    {
        return $this->services;
    }

    public function addService(Service $service): self
    {
        if (!$this->services->contains($service)) {
            $this->services[] = $service;
            $service->setTask($this);
        }

        return $this;
    }

    public function removeService(Service $service): self
    {
        if ($this->services->removeElement($service)) {
            // set the owning side to null (unless already changed)
            if ($service->getTask() === $this) {
                $service->setTask(null);
            }
        }

        return $this;
    }
}

ServiceSection entity

<?php
/**
 * App_Entity_ServiceSection
 */

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Eleva\BackofficeBundle\Entity\BaseEntity;
use App\Repository\ServiceSectionRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class ServiceSection
 *
 * Main ServiceSection entity.
 * @author Eleva
 * @package App\Entity
 * @license © 2023 Eleva SRL
 * @ORM\Entity(repositoryClass=ServiceSectionRepository::class)
 */
class ServiceSection extends BaseEntity
{
    /**
     * @var int|null $id
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

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

    /**
     * @ORM\OneToMany(targetEntity=Task::class, mappedBy="section")
     */
    private $tasks;

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

    /**
     * getId
     *
     * Returns the id value.
     */
    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;
    }

    /**
     * @return Collection<int, Task>
     */
    public function getTasks(): Collection
    {
        return $this->tasks;
    }

    public function addTask(Task $task): self
    {
        if (!$this->tasks->contains($task)) {
            $this->tasks[] = $task;
            $task->setSection($this);
        }

        return $this;
    }

    public function removeTask(Task $task): self
    {
        if ($this->tasks->removeElement($task)) {
            // set the owning side to null (unless already changed)
            if ($task->getSection() === $this) {
                $task->setSection(null);
            }
        }

        return $this;
    }
}

ProjectType excerpt

$serviceBuilder = $builder->create('services', ServiceType::class, [
            'required' => false,
            'by_reference' => true,
            'data_class' => Service::class
        ]);

ServiceType excerpt

$builder->add('task', EntityType::class, [
            'required' => false,
            'class' => \App\Entity\Task::class,
            'multiple' => false,
            'expanded' => false,
            'mapped' => true,
            'choice_label' => 'name',
            'empty_data' => '',
            'constraints' => [],
            'query_builder' => function (EntityRepository $er) {
                return $er->createQueryBuilder('u')
                    ->where('u.del = 0 ')
                    ->orderBy('u.id', 'DESC');
            },
            'row_attr' => [
                'class' => 'container_task_id',
                'id' => 'container_task_id'
            ],
            'attr' => [
                'class' => 'selectize',
                'data-field-column' => 'task_id',
                'data-field-name' => 'task'
            ]
        ]);

TaskType excerpt

$builder->add('section', EntityType::class, [
            'required' => false,
            'class' => \App\Entity\ServiceSection::class,
            'multiple' => false,
            'expanded' => false,
            'mapped' => true,
            'choice_label' => 'name',
            'empty_data' => '',
            'constraints' => [],
            'query_builder' => function (EntityRepository $er) {
                return $er->createQueryBuilder('u')
                    ->where('u.del = 0 ')
                    ->orderBy('u.id', 'DESC');
            },
            'row_attr' => [
                'class' => 'container_service_section_id',
                'id' => 'container_service_section_id'
            ],
            'attr' => [
                'class' => 'selectize',
                'data-field-column' => 'service_section_id',
                'data-field-name' => 'section'
            ]
        ]);

What I'm trying to do is render the section property of task as a dropdown

<div class="flex-col col-1-2 container_service_section_id">
                                <h6 class="required">
                                    {{ 'BACKOFFICE_SERVICE_SECTION' |trans }}
                                </h6>
                                <div class="field-container {% if form_errors(form.services.task.section) is not empty %}alert-field{% endif %}">
                                    {{ form_widget(form.services.task.section) }}
                                    <span class="alert">
                                        {{ form_errors(form.services.task.section) ?: 'EMPTY_FIELD' | trans }}
                                    </span>
                                </div>
                            </div>

but this is the error I'm getting:

Neither the property "section" nor one of the methods "section()", "getsection()"/"issection()"/"hassection()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView".

Am I completely stupid and I'm missing something obvious or did I do everything wrong?

0

There are 0 answers