如何在 React + Symfony 6 后端表单中链接两个表?

问题描述 投票:0回答:1

我有一个带有 Symfony 6.4 后端的 React Form,我试图将两个表链接在一起(Tiers 和 GroupeDdo),其中每个 Tiers 有一个 GroupeDdo。这是我的 Tiers.php :

<?php

namespace App\Entity;

use App\Repository\TiersRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: TiersRepository::class)]
class Tiers
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne(inversedBy: 'tiers')]
    private ?GroupeDdo $groupe_ddo = null;


[...]

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

    public function getGroupeDdo(): ?GroupeDdo
    {
        return $this->groupe_ddo;
    }

    public function setGroupeDdo(?GroupeDdo $groupe_ddo): self
    {
        $this->groupe_ddo = $groupe_ddo;

        return $this;
    }
} 

这是我的 GroupeDdo.php :

<?php

namespace App\Entity;

use App\Repository\GroupeDdoRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: GroupeDdoRepository::class)]
class GroupeDdo
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $groupe_ddo_nom = null;

    #[ORM\OneToMany(targetEntity: Ddo::class, mappedBy: 'groupe_ddo')]
    private Collection $ddos;

    #[ORM\OneToMany(targetEntity: Tiers::class, mappedBy: 'groupe_ddo')]
    private Collection $tiers;

    #[ORM\OneToMany(targetEntity: User::class, mappedBy: 'groupe_ddo')]
    private Collection $users;

    public function __construct()
    {
        $this->ddos = new ArrayCollection();
        $this->tiers = new ArrayCollection();
        $this->users = new ArrayCollection();
    }

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

    public function getGroupeDdoNom(): ?string
    {
        return $this->groupe_ddo_nom;
    }

    public function setGroupeDdoNom(string $groupe_ddo_nom): static
    {
        $this->groupe_ddo_nom = $groupe_ddo_nom;

        return $this;
    }

    /**
     * @return Collection<int, Ddo>
     */
    public function getDdos(): Collection
    {
        return $this->ddos;
    }

    public function addDdo(Ddo $ddo): static
    {
        if (!$this->ddos->contains($ddo)) {
            $this->ddos->add($ddo);
            $ddo->setGroupeDdoId($this);
        }

        return $this;
    }

    public function removeDdo(Ddo $ddo): static
    {
        if ($this->ddos->removeElement($ddo)) {
            // set the owning side to null (unless already changed)
            if ($ddo->getGroupeDdoId() === $this) {
                $ddo->setGroupeDdoId(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection<int, Tiers>
     */
    public function getTiers(): Collection
    {
        return $this->tiers;
    }

    public function addTier(Tiers $tier): static
    {
        if (!$this->tiers->contains($tier)) {
            $this->tiers->add($tier);
            $tier->setGroupeDdoId($this);
        }

        return $this;
    }

    public function removeTier(Tiers $tier): static
    {
        if ($this->tiers->removeElement($tier)) {
            // set the owning side to null (unless already changed)
            if ($tier->getGroupeDdoId() === $this) {
                $tier->setGroupeDdoId(null);
            }
        }
    }

}

这是我的表格的完整版本:

import React, { useState, useEffect } from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import { useAuth } from '../context/AuthContext';
import Cookies from 'js-cookie';


// L'interface Tiers définit les champs de la table Tiers et leur types
interface Tiers {
    tiers_raison_sociale: string | null;
    tiers_intitule: string | null;
    tiers_heures_ouverture: {
        [key: string]: { ouverture: string; fermeture: string }[];
    } | null;
    tiers_telephone: string | null;
    tiers_courriel: string | null;
    tiers_rdv: boolean | null;
    groupe_ddo_id: number | null;
    tiers_adresse: string | null;
    tiers_ville: string | null;
    tiers_cp: string | null;
    tiers_pays: string | null;
}


// L'interface GroupeDDo définit les champs de la table GroupeDdo et leur types
interface GroupeDDO {
    id: number;
    groupeDdoNom: string;
}

const TiersForm: React.FC = () => {
    //Utilisation d'un useState de l'API
    const [apiError, setApiError] = useState('');
    const [groupeDDOList, setGroupeDDOList] = useState<GroupeDDO[]>([]);
    const [selectedGroupeId, setSelectedGroupeId] = useState<number | null>(0);
    const { isAuthenticated } = useAuth();

    if (!isAuthenticated) {
        window.location.href = '/';
    }

    useEffect(() => {
        const fetchGroupeDDOList = async () => {
            try {
                const response = await fetch('http://127.0.0.1:8000/api/liste-groupe-ddo');
                if (!response.ok) {
                    throw new Error('Erreur lors de la récupération des données des groupes');
                }
                const data = await response.json();
                setGroupeDDOList(data);
            } catch (error) {
                console.error(error);
            }
        };

        fetchGroupeDDOList();
    }, []);

    //Valeur initiales du formulaire 
    const initialValues: Tiers = {
        tiers_raison_sociale: '',
        tiers_intitule: '',
        tiers_heures_ouverture: {
            lundi: [{ ouverture: '', fermeture: '' }],
            mardi: [{ ouverture: '', fermeture: '' }],
            mercredi: [{ ouverture: '', fermeture: '' }],
            jeudi: [{ ouverture: '', fermeture: '' }],
            vendredi: [{ ouverture: '', fermeture: '' }],
            samedi: [{ ouverture: '', fermeture: '' }],
            dimanche: [{ ouverture: '', fermeture: '' }],
        },
        tiers_telephone: '',
        tiers_courriel: '',
        tiers_rdv: false,
        groupe_ddo_id: null,
        tiers_adresse: '',
        tiers_ville: '',
        tiers_cp: '',
        tiers_pays: '',
    };

    const onSubmit = async (values: Tiers) => {
        try {

            if (!isAuthenticated) {
                throw new Error('Vous devez être connecté pour effectuer cette action');
            }

            const token = Cookies.get('authToken');

            const selectedGroupe = groupeDDOList.find(groupe => groupe.id === (selectedGroupeId as number));

            if (!selectedGroupe) {
                throw new Error('Le groupe selectionné est introuvable');
            }

            if (selectedGroupe) {
                values.groupe_ddo_id = selectedGroupe.id;
            }


            const response = await fetch('http://127.0.0.1:8000/api/create/tiers', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${token}`
                },
                body: JSON.stringify(values),
            });

            if (!response.ok) {
                throw new Error('Erreur lors de la création de la société');
            }

            // Réinitialiser les champs du formulaire après la soumission réussie
            setApiError('');
            window.location.href = '/';
        } catch (error) {
            setApiError('Impossible d\'envoyer le formulaire');
        }
    };

    // Conditions de chaque champ du formulaire
    const validate = (values: Tiers) => {
        const errors: Partial<Tiers> = {};
        // Si le code de société n'est pas entré, écrire qu'il est requis
        if (!values.tiers_raison_sociale) {
            errors.tiers_raison_sociale = 'Raison sociale de la société requise';
        }

        return errors;
    };

    return (
        <>
            {groupeDDOList.length === 0 ? (
                <p>Chargement en cours...</p>
            ) : (
                <Formik
                    {...{ initialValues, onSubmit, validate }}
                >
                    {({ isSubmitting, values, handleChange }) => (
                        <Form>

                            <fieldset>
                                
                                <legend>A Quel Groupe de Société doit-il être lié ?</legend>
                                <Field as="select" name="groupe_ddo_id" label="Groupe Société d'un tiers" value={selectedGroupeId} onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
                                    // const selectedValue = (e.target as HTMLSelectElement).value;
                                    const selectedValue = parseInt(e.target.value);
                                    // const selectedGroupe = selectedGroupeId ? groupeDDOList.find(groupe => groupe.id === parseInt(selectedValue)) : null;
                                    // if (selectedGroupe) {
                                    setSelectedGroupeId(selectedValue);
                                    // }
                                }}>
                                    {groupeDDOList.map((groupe, index) => (
                                        <option key={index} value={groupe.id}>
                                            {groupe.groupeDdoNom}
                                        </option>
                                    ))}
                                </Field>
                                <ErrorMessage name="id" component="div" className="error" />


                                {apiError && <div className="error">{apiError}</div>}
                                <br />
                                <button type="submit" disabled={isSubmitting}>
                                    {isSubmitting ? 'Création en cours...' : 'Créer Tiers'}
                                </button>
                            </fieldset>
                        </Form>
                    )}
                </Formik >
            )}
        </>
    );
};

export default TiersForm;

这里的问题是,当我尝试获取 GroupeDdo 列表以创建选择字段时,我看不到它们,并显示错误:警告:未定义的数组键“groupe_ddo_id”。我应该怎么做才能获取我所有的 GroupeDdo 并确保它是数据库中 GroupeDdo 的值?

谢谢!

php reactjs symfony formik symfony6
1个回答
0
投票

来自我的控制器,我使用 findAll 函数来获取所有内容。但在这样做的过程中,我也试图获取集合,这不是我想要的,因为其中一个集合是 Tiers,这正是我试图使用表单创建的。

因此,我创建了一个函数,仅从 GroupeDdo 实体获取我需要的内容。

© www.soinside.com 2019 - 2024. All rights reserved.