Un CPT praticien relié à un CPT rendez_vous par un champ meta _praticien_id : c’est la structure la plus courante pour gérer un cabinet pluridisciplinaire dans WordPress. Elle fonctionne très bien tant que personne ne supprime une fiche praticien qui a encore des rendez-vous à venir. Le jour où cela arrive, la fiche disparaît, mais les rendez-vous restent en base, pointant vers un post_id qui n’existe plus.
Ce genre d’incident est rarement provoqué par malveillance. C’est un remplaçant qui part, un stagiaire qui fait le ménage dans la liste des utilisateurs, un import mal filtré. Le résultat est le même : un patient reçoit un rappel de rendez-vous pour un praticien qui n’apparaît plus nulle part sur le site, et le secrétariat découvre le problème au téléphone, en direct.
Ce qu’on voit en pratique
Sur la plupart des installations, la suppression d’un praticien passe par l’écran standard de gestion des contenus, sans aucune vérification préalable. WordPress exécute la suppression, déclenche le hook before_delete_post, puis deleted_post, sans jamais se soucier des entités qui référencent ce praticien ailleurs dans la base. Rien dans le cœur ne relie automatiquement un CPT à un autre par une clé étrangère au sens SQL du terme : c’est entièrement à la charge du développeur.
Quand la vérification manque, trois symptômes reviennent systématiquement : des rendez-vous affichés avec un nom de praticien vide dans le back-office, des notifications automatiques encore envoyées pour un rendez-vous devenu incohérent, et une réconciliation manuelle fastidieuse pour retrouver qui aurait dû être notifié du changement.
Pourquoi c’est un problème
Dans un cabinet médical, un rendez-vous orphelin n’est pas qu’un défaut d’affichage : c’est un patient qui se déplace pour rien, ou à l’inverse un praticien remplaçant qui n’est jamais informé qu’un créneau lui était en réalité destiné. La confiance dans l’outil de planification s’érode vite dès qu’un secrétariat découvre ce genre d’incohérence, et le réflexe naturel devient de tout vérifier à la main avant chaque suppression, ce qui annule tout le bénéfice de l’automatisation.

Quoi faire
La correction tient dans un hook, à condition de l’attacher au bon endroit. before_delete_post s’exécute avant la suppression effective et accepte de bloquer l’opération en levant une exception filtrée par WordPress via wp_die() dans le contexte admin, ou plus proprement en interceptant la capacité de suppression avec map_meta_cap.
add_filter( 'user_has_cap', function( $allcaps, $caps, $args ) {
if ( empty( $args[0] ) || 'delete_post' !== $args[0] ) {
return $allcaps;
}
$post_id = $args[2] ?? 0;
if ( 'praticien' !== get_post_type( $post_id ) ) {
return $allcaps;
}
$rdv_futurs = get_posts( array(
'post_type' => 'rendez_vous',
'meta_key' => '_praticien_id',
'meta_value' => $post_id,
'meta_compare'=> '=',
'date_query' => array(
array( 'column' => 'meta_value', 'after' => 'now', 'inclusive' => true ),
),
'fields' => 'ids',
'numberposts' => 1,
) );
if ( ! empty( $rdv_futurs ) ) {
foreach ( $caps as $cap ) {
$allcaps[ $cap ] = false;
}
}
return $allcaps;
}, 10, 3 );
Ce filtre neutralise la capacité de suppression pour ce praticien précis dès qu’un rendez-vous futur lui est rattaché, quel que soit l’écran par lequel passe l’administrateur : liste des contenus, action groupée, ou même une suppression déclenchée par une requête REST. C’est ce dernier point qui compte le plus : bloquer uniquement le bouton dans l’interface ne protège rien contre un script ou une extension tierce qui appelle wp_delete_post() directement.
Afficher un message utile plutôt qu’un blocage muet
Un blocage silencieux frustre plus qu’il ne protège. Sur l’écran d’édition du praticien, un message contextuel via admin_notices doit expliquer pourquoi la suppression est refusée et, idéalement, lister les rendez-vous concernés avec un lien direct vers chacun. Le secrétariat peut alors décider en connaissance de cause : annuler les rendez-vous, les réaffecter à un confrère, ou attendre qu’ils passent.
- Lister les rendez-vous bloquants avec date et patient dans la notice admin
- Proposer un lien direct « réaffecter à » pointant vers l’outil de duplication de planning
- Ne jamais transformer ce garde-fou en blocage permanent : une fois les rendez-vous traités, la suppression doit redevenir possible sans intervention développeur
Un garde-fou qui n’explique rien finit systématiquement contourné à coups de suppression forcée en base ; mieux vaut un message clair qu’une protection qu’on désactive par lassitude.
En résumé
Le cœur de WordPress ne connaît pas la relation métier entre un praticien et ses rendez-vous : il faut la matérialiser explicitement, et la faire respecter au niveau des capacités plutôt qu’au niveau de l’affichage. Un filtre sur user_has_cap, une requête date_query bien ciblée sur les rendez-vous à venir, et une notice qui explique la situation suffisent à éliminer ce type d’incident sans complexifier l’interface pour l’équipe administrative.