sept 28

[Symfony] Doctrine : « onDelete: SET NULL »

Catégorie(s): Développement,PHPSébastien @ 20:28

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: nom }


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.

Aucun article à afficher.

3 Responses to “[Symfony] Doctrine : « onDelete: SET NULL »”

  1. Delphine LEMIRE

    Merci de cette info…

  2. nderoche

    Hello

    interessant, merci !
    typo dans la dernière ‘boite’

    Incorrect:
    relations:
    Category: { onDelete: SET NULL, local: category_name, foreign: name }

    Correct:
    relations:
    Category: { onDelete: SET NULL, local: category_name, foreign: nom }

  3. Sébastien

    Hello,

    Bien vu pour l’erreur de frappe, je corrige ça.

Laisser un commentaire