我有一个带有 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 的值?
谢谢!
来自我的控制器,我使用 findAll 函数来获取所有内容。但在这样做的过程中,我也试图获取集合,这不是我想要的,因为其中一个集合是 Tiers,这正是我试图使用表单创建的。
因此,我创建了一个函数,仅从 GroupeDdo 实体获取我需要的内容。