sept 28 2009
[Symfony] Doctrine : « onDelete: SET NULL »
Avec Symfony vous pouvez, en utilisant Doctrine, vous servir de l’option « onDelete » sur les clés étrangères (CASCADE, SET NULL, and RESTRICT). SET NULL m’a cependant posé quelques soucis en me déclenchant l’erreur suivante :
SQLSTATE[HY000]: General error: 1005 Can't create table 'sf.#sql-abc_a7' (errno: 150). Failing Query: ALTER TABLE gallery ADD FOREIGN KEY (category_id) REFERENCES gallery_category(id) ON DELETE SET NULL
Si vous aussi vous rencontrez cette erreur, nous allons voir quelques éléments à vérifier. Pour cela, on va utiliser deux tables basiques :
Category: - id : entier - nom : chaine Gallery: - id : entier - category_id : entier - nom : chaine
1. Champs identiques
La première chose à vérifier est que vos deux champs soient identiques au niveau du type, de la longueur, des options, etc. Lorsque vous laissez Symfony et Doctrine s’occuper tout seuls des champs ‘ID’ (qui s’appellera toujours id), il faut que votre champs category_id soit tout simplement du type integer et pas integer(X). Le champs id sera en effet généré en tant que BIGINT(20) dans la base de données. Si vous mettez une autre longueur, ça fera planter la création de la clé étrangère.
Incorrect
Category:
columns:
nom: { type: string(255), notnull: true }
Gallery:
columns:
category_id: { type: integer(10) }
nom: { type: string(255), notnull: true }
relations:
Category: { onDelete: SET NULL, local: category_id, foreign: id }
Correct
Category:
columns:
nom: { type: string(255), notnull: true }
Gallery:
columns:
category_id: { type: integer }
nom: { type: string(255), notnull: true }
relations:
Category: { onDelete: SET NULL, local: category_id, foreign: id }
2. PAS de notnull true
L’autre élément à faire attention c’est à ce que votre champs local puisse être null. Cette remarque s’appliquent surtout à ceux qui passent d’un onDelete: CASCADE à un onDelete: SET NULL en ne modifiant que cette valeur. Il faut aussi penser à supprimer l’option notnull: true de votre champs local.
Incorrect
Category:
columns:
nom: { type: string(255), notnull: true }
Gallery:
columns:
category_id: { type: integer, notnull: true }
nom: { type: string(255), notnull: true }
relations:
Category: { onDelete: SET NULL, local: category_id, foreign: id }
Correct
Category:
columns:
nom: { type: string(255), notnull: true }
Gallery:
columns:
category_id: { type: integer }
nom: { type: string(255), notnull: true }
relations:
Category: { onDelete: SET NULL, local: category_id, foreign: id }
3. Index manquant
Si vous souhaitez faire une clé étrangère sur un champs autre que la clé primaire, comme par exemple le nom, il faut que ce champs possède un index. En théorie, il est crée automatiquement. Si ce n’est pas le cas, il suffit de le créer soit même :
Category:
indexes:
MonIndex:
fields:
nom: []
columns:
nom: { type: string(255), notnull: true }
Gallery:
columns:
category_id: { type: integer }
category_name: { type: integer }
nom: { type: string(255), notnull: true }
relations:
Category: { onDelete: SET NULL, local: category_name, foreign: name }
Conclusion
Rien qu’avec ces trois vérifications, vous devriez ne plus rencontrer d’erreur. Dans le cas contraire, allez faire un tour du coté du forum de Symfony. ;) Notez également que les vérifications 1 et 3 sont aussi utiles quand vous utilisez un onDelete: CASCADE ou RESTRICT.



