2017-03-06 5 views
0

Ich habe zwei Einheiten konfiguriert, die Benutzer und ApiKey genannt. Sie haben eine Eins-zu-Eins-Beziehung unten abgebildet.Doctrine Entity Association funktioniert nicht

Benutzer:

/** 
* @var integer 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
protected $id; 

/** 
* @ORM\Column(name="username", type="string", length=225, unique=true) 
* @Assert\NotBlank(message="Please enter a username.") 
* @Assert\Length(
*  min = 2, 
*  max = 180, 
*  minMessage = "Your username must be at least {{ limit }} characters", 
*  maxMessage = "Your username cannot be longer than {{ limit }} characters" 
*) 
*/ 
protected $username; 

/** 
* @ORM\Column(name="email", type="string", length=225) 
* @Assert\NotBlank(message="Please enter a email.") 
* @Assert\Email(message = "The email '{{ value }}' is not a valid email.") 
*/ 
protected $email; 

/** 
* @ORM\Column(name="salt", type="text") 
*/ 
protected $salt; 

/** 
* @ORM\Column(name="password", type="string", length=225) 
* @Assert\NotBlank(message="Please enter a password.") 
* @Assert\Length(
*  min = 7, 
*  minMessage = "Your password must be at least {{ limit }} characters long." 
*) 
*/ 
protected $password; 

/** 
* @Assert\NotBlank(message="Please enter a confirmation password.") 
*/ 
protected $confirmationPassword; 

/** 
* @ORM\Column(name="roles", type="json_array") 
*/ 
protected $roles; 

/** 
* @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user") 
* @ORM\JoinColumn(name="id", referencedColumnName="user_id") 
*/ 
protected $apiKey; 

apikey:

/** 
* @var integer 
* @ORM\Column(name="user_id", type="integer") 
* @ORM\Id 
*/ 
protected $user_id; 

/** 
* @var string 
* @ORM\Column(name="api_key", unique=true, type="string", length=225) 
* @Assert\NotBlank(message="Please enter a username.") 
*/ 
protected $api_key; 

/** 
* @var string 
* @ORM\Column(name="expires", type="datetime") 
* @Assert\NotBlank(message="Please enter a username.") 
*/ 
protected $expires; 

/** 
* @ORM\OneToOne(targetEntity="User", inversedBy="apiKey") 
* @ORM\JoinColumn(name="user_id", referencedColumnName="id") 
*/ 
protected $user; 

Allerdings, wenn ich den folgenden Code ausführen:

$user = new User(); 
    $user->setUsername($request->get('username')); 
    $user->setSalt(uniqid(mt_rand(), true)); 
    $user->setPassword(hash('sha256', $user->getSalt() . $request->get('password'))); 
    $user->setRoles(['ROLE_API']); 

    $apiKey = new ApiKey(); 
    $apiKey->setUser($user); 

    $this->getDoctrine()->getManager()->persist($user); 
    $this->getDoctrine()->getManager()->flush(); 

ich diesen Fehler bekommen, was mache ich falsch?

An exception occurred while executing 'INSERT INTO users (username, email, salt, password, roles, id) VALUES (?, ?, ?, ?, ?, ?)' with params ["bobsmith", "[email protected]", "147423531058bd98d9ac9af4.48409486", "6196012972b1294e7f3fbf9c140bc26f0bf3b354ea37d00753bc1ecba0a72866", "[\"ROLE_API\"]", null]:SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (app . users , CONSTRAINT FK_1483A5E9BF396750 FOREIGN KEY (id) REFERENCES api_key (user_id))

Wechsel:

$user = new User(); 
    $user->setUsername($request->get('username')); 
    $user->setSalt(uniqid(mt_rand(), true)); 
    $user->setPassword(hash('sha256', $user->getSalt() . $request->get('password'))); 
    $user->setRoles(['ROLE_API']); 

    $apiKey = new ApiKey(); 
    $this->getDoctrine()->getManager()->persist($apiKey); 
    $apiKey->setUser($user); 

    $this->getDoctrine()->getManager()->persist($user); 
    $this->getDoctrine()->getManager()->flush(); 

Entity of type AppBundle\Entity\ApiKey is missing an assigned ID for field 'user_id'. The identifier generation strategy for this entity requires the ID field to be populated before EntityManager#persist() is called. If you want automatically generated identifiers instead you need to adjust the metadata mapping accordingly.

+0

versuchen, "$ user-> setApiKey ($ apiKey);" nach $ apiKey = new ApiKey(); –

+0

Ich habe deine Änderung hinzugefügt ^. Aber jetzt erhalten Sie diesen Fehler: Eine neue Entität wurde über die Beziehung 'AppBundle \ Entity \ User # apiKey' gefunden, die nicht für die Kaskade persist Operationen für Entität konfiguriert wurde: AppBundle \ Entity \ ApiKey @ 000000004adc072f00000000540f2869. Um dieses Problem zu lösen: Rufen Sie entweder EntityManager # persist() explizit auf dieser unbekannten Entität auf oder konfigurieren Sie die Kaskade so, dass diese Zuordnung im Mapping beibehalten wird, z. B. @ManyToOne (.., cascade = {"persist"}). Wenn Sie nicht herausfinden können, welches Element das Problem verursacht, implementieren Sie 'AppBundle \ Entity \ ApiKey #__ toString()', um einen Hinweis zu erhalten. – Freid001

+0

Fügen Sie diese Zeile auch vor dem Flush hinzu: $ this-> getDoctrine() -> getManager() -> persist ($ apiKey); –

Antwort

2

Dies ist 2-fach, wh bei Cyril sagte, aber es ist auch, weil Sie zusätzliche Zuordnung in Ihrer Benutzerklasse haben:

/** 
* @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user") 
* @ORM\JoinColumn(name="id", referencedColumnName="user_id") // Remove this line 
*/ 
protected $apiKey; 

Sollte nur sein:

/** 
* @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user") 
*/ 
protected $apiKey; 

Nur die Zuordnung, die die Abbildung tatsächlich tun, die Join-Spalte muss. Mit der Verwendung von mappedBy="user" sagen Sie Lehre, die ApiKey-Klasse user Eigenschaft für die Zuordnung dieser Zuordnung zu betrachten. Eine Join-Spalte in dieser Klasse verursacht Probleme.

+1

In der Tat sollte ich zumindest genauer lesen, was ich kopiere/einfügen. Um zu paraphrasieren, was Chausser gerade gesagt hat, wenn eine Seite der Relation ein 'mappedBy'-Feld hat, ist es der * Besitzer * der Relation und erstellt und verwaltet die versteckte Join-Tabelle. Wenn die andere Seite eine bidirektionale Beziehung möchte, erstellt sie eine 'JoinColumn', um einen Lesezugriff auf die Join-Tabelle des Eigentümers zu erhalten. –

3

Sie scheinen hier eine kaskadierende Problem zu haben. Sie speichern einen Benutzer in der Datenbank, aber dieser Benutzer ist mit einem ApiKey verknüpft, der noch NICHT in der Datenbank gespeichert ist. Um dem Spieler zu sagen, dass sie es ist apikey bestehen bleiben muss zusammen mit ihm die Sie benötigen eine Kaskade hinzufügen auf persistieren zwischen User und apikey

/** 
* @ORM\OneToOne(targetEntity="ApiKey", mappedBy="user", cascade="persist") 
*/ 
protected $api_key; 

Wenn Sie auch die apikey löschen möchten zusammen mit dem Benutzer können Sie cascade={"persist", "remove"} verwenden Sie können alle Lehre Dokumentation über Vereinigungen here

EDIT finden: entfernt die Linie // @ORM\JoinColumn(name="id", referencedColumnName="user_id"), die nicht auf den Eigentümer Seite existieren sollte, so kommentiert von Chausser

+1

Ich habe Ihre Änderung vorgenommen, aber jetzt bekomme ich diesen Fehler: Entität vom Typ AppBundle \ Entity \ ApiKey fehlt eine zugewiesene ID für das Feld 'user_id'. Die Bezeichnergenerierungsstrategie für diese Entität erfordert, dass das ID-Feld vor dem Aufruf von EntityManager # persist() ausgefüllt wird. Wenn Sie stattdessen automatisch generierte Bezeichner haben möchten, müssen Sie das Metadaten-Mapping entsprechend anpassen. – Freid001

Verwandte Themen