J'ai deux entités dans notre projet utilisant Doctrine:
$user = new User(); $user->setUsername('test'); $user->setEmail('test@example.com'); $user->setPassword(password_hash('password', PASSWORD_BCRYPT)); $em->persist($user); $em->flush(); $userProfile = new UserProfile(); $userProfile->setFirstName('test'); $userProfile->setLastName('user'); $user->setProfile($userProfile); $em->persist($user); $em->flush();
Et j'essaye de générer de nouvelles lignes dans la base de données en utilisant quelque chose comme:
class User { /** * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ private $user_id; /** * @ORM\Column(type="string") */ private $username; /** * @ORM\Column(type="string") */ private $password; /** * @ORM\OneToOne(targetEntity="UserProfile", cascade={"persist", "remove"}) * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id", unique=true) * @var UserProfile */ private $profile; //... } class UserProfile { /** * @ORM\Id * @ORM\OneToOne(targetEntity="User") * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id") */ private $user; /** * @ORM\Id * @ORM\Column(type="integer") */ private $user_id; /** * @ORM\Column(type="string") */ private $first_name = ''; /** * @ORM\Column(type="string") */ private $last_name = ''; //... }
3 Réponses :
La relation entre les entités User
et UserProfile
est conservée sur la propriété UserProfile :: user
, cependant, lorsque vous appelez User :: setProfile () , vous ne définissez pas cette propriété.
Modifiez votre fonction User :: setProfile ()
comme suit:
function setProfile(UserProfile $profile): self { $profile->setUser($this); $this->profile = $profile; return $this; }
Merci pour la suggestion, mais cela entraîne une erreur similaire, bien que maintenant il se plaint: UserProfile n'a pas d'ID attribué pour le champ 'user_id'. La stratégie de génération d'identifiant pour cette entité nécessite que le champ ID soit rempli avant que EntityManager # persist () soit appelé. Si vous souhaitez plutôt des identificateurs générés automatiquement, vous devez ajuster le mappage des métadonnées en conséquence. dans /home/ddc/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException. php en ligne 87
Dans votre code, vous appelez $ em-> persist ($ user);
deux fois, plutôt que $ em-> persist ($ userProfile);
Le changer en $ em-> persist ($ userProfile);
ne change pas l'erreur. L'association doit de toute façon cascade de user -> userProfile.
Avez-vous validé vos relations?
Je viens de lancer orm: validate-schema
et je me suis plaint d'avoir le champ $ user
dans UserProfile
comme id. J'ai supprimé cela et l'outil validé. La même erreur se produit cependant.
Avez-vous une colonne ID sur votre entité UserProfile
? Pouvez-vous publier votre code mis à jour? Parce que les annotations sur les propriétés $ user_id
et $ user
semblent incorrectes. Ils ont des annotations @ORM \ Id
, ce qui est faux.
J'ai supprimé @ORM \ Id
de la propriété $ user
. Je n'ai pas de colonne d'identifiant distincte sur cette table, juste un index unique sur la colonne user_id
.
Votre mappage n'est pas valide. Validez votre schéma - il manque mappedBy
et inversedBy
. Lorsque vous corrigez le mappage, cela fonctionnera comme prévu.
Validation du schéma dans Symfony:
php public/index.php orm:schema-tool:validate
Dans ZF:
bin/console doc:sch:val
./vendor/bin/doctrine orm: validate-schema
dit que c'est correct (je n'utilise pas de framework). De plus, l'exemple sur le site de doctrine ne mentionne pas mappedBy ou inversedBy. J'ai essayé de les ajouter auparavant, mais cela n'a pas aidé.
Il y a de toute façon quelque chose qui ne va pas avec votre schéma. Pourquoi avez-vous besoin de cette propriété $ user_id
dans les deux entités, dans le cadre de Id
lol? Cela n'a aucun sens. Conservez uniquement le $ profile
dans l'entité User
, le $ user
dans l'entité UserProfile
et liez-les ensemble en utilisant inversedBy
sur l'utilisateur et mappedBy
sur le profil. Supprimez la propriété $ user_id
inutile des deux entités. Vous n'avez pas non plus besoin du paramètre "unique" lorsque vous utilisez les relations OneToOne
car il est défini par défaut. Corrigez votre cartographie, mettez à jour votre question puis nous pouvons continuer. Ne pensez pas à la base de données, concentrez-vous sur le modèle
Grâce à @emix et @fubar, les deux ont contribué à la solution. C'est ce qui a fonctionné à la fin:
class User { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ private $user_id; /** * @ORM\Column(type="string") */ private $username; /** * @ORM\Column(type="string") */ private $password; /** * @ORM\OneToOne(targetEntity="UserProfile", mappedBy="user", cascade={"persist", "remove"}) * @var UserProfile */ private $profile; //... public function setProfile(UserProfile $profile) : self { $profile->setUser($this); $this->profile = $profile; return $this; } } class UserProfile { /** * @ORM\Id * @ORM\OneToOne(targetEntity="User", inversedBy="profile") * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id") */ private $user; /** * @ORM\Column(type="string") */ private $first_name = ''; /** * @ORM\Column(type="string") */ private $last_name = ''; //... }
Ce qui impliquait de supprimer $ user_id
de l'entité UserProfile
et d'ajouter un paramètre inversedBy au OneToOne .
Suppression de JoinColumn
de l'entité User
et correction du setter pour setProfile ()
afin qu'il définit $ user
sur l'entité UserProfile.
Pouvez-vous poster le code de la fonction
User :: setProfile ()
?Ce n'est rien de spécial:
public function setProfile (UserProfile $ profile): self {$ this-> profile = $ profile; retourne $ this; }