Bonjour,
Auriez vous une idée de comment supprimer automatiquement la plus ancienne donnée d'une table quand elle contient 7 entrées?
De manière à ce que si j'ai
id message
1 rrrrr
2 rrrrr
3 ffffff
4 rtyutr
5 rrr
6 er(-y

A la 7e entrée le 1 est supprimé et j'obtient :
id message
2 rrrrr
3 ffffff
4 rtyutr
5 rrr
6 er(-y
7 ozkro

15 réponses


Bonjour.
Si j'ai bien compris, tu veux supprimer l'enregistrement le plus ancien d'une table SQL lorsque celle-ci à 7 enregistrements.
Si c'est bien le cas, il va te falloir faire deux requêtes SQL, une pour récupérer le nombre d'enregistrements de la table et la seconde pour supprimer l'enregistrement le plus ancien.
Par contre, le contenu de ton sujet est assez pauvre car il n'est pas très explicite, car tu es dans le forum PHP mais tu ne nous a mis aucun code qui nous permette de savoir ce que tu as déja essayé de faire et que veux tu dire par automatiquement ?
Si tu veux dire que le script qui permet de lancer la requête SQL afin de vérifier le nombre d'enregistrements de la table et celui de la requête SQL qui permet de supprimer un enregistrement dans le cas ou il y ait bien 7 enregistrements se fassent tout seul, dans ce cas il va te falloir faire tache CRON.
Il y a quand même quelque chose que tu ne semble pas prendre en compte, car dans le cas où il y ait plus de 7 enregistrements et que tu fasses une comparaison du type :

$verif = $bdd->query('SELECT id FROM chatt');
if ($verif->columnCount() === 7) {
    $id = $verif[0]['id'];
    $bdd->query("DELETE FROM chatt WHERE id = $id");
}

Dans ce cas là si tu as plus de 7 enregistrements la condition ne sera pas respectée par conséquence aucune suppression ne sera faite.
Sinon dans le cas suivant :

$verif = $bdd->query('SELECT id FROM taTable');
if ($verif->columnCount() >== 7) {
    $id = $verif[0]['id'];
    $bdd->query("DELETE FROM chatt WHERE id = $id");
}

Si le nombre d'enregistrements retourné est supérieur ou égale à 7, tu auras bien la suppression du plus ancien enregistrement, mais tu peux toujours avoir 7 enregistrements ou plus.

Ynèv
Auteur

oui tu as bien compris c'est ce que je souhaite faire.
Je n'ai pas mis de code car tout ce que j'ai tenté ne m'a vraiment servi a rien ça n'aurait pas été productif .
Je suis vraiment obligé de passé par CRON ? ce n'est pas faisable juste en php ? Car le bout de code que tu as mis me parait pouvoir fonctionner sans CRON en le mettant dans une condition ou j'enregistre dans la base de donnée les messages : par exemple a chaque nouveau message enregistrer on lance la verif et la BDD agis en caonsequence .

[Edit] j'ai tenté ton bout de code :

$verifi = $bdd->query('SELECT id FROM chatt');
if ($verifi->columnCount() >== 7) {
    $id = $verifi[0]['id'];
    $bdd->query("DELETE FROM chatt WHERE id = $id");
}

le site me renvoi:
Parse error: syntax error, unexpected '=' in C:\wamp\www\CHAT_PROJET\chat.php on line 55

Je suis vraiment obligé de passé par CRON ? ce n'est pas faisable juste en php ?

Si j'ai parlé de CRON, c'est parce que j'avais un doute sur le sens du terme automatiquement.
Ne connaisant pas le contexte de l'exécution du script, je ne savais pas si tu voulais dire que le script devait s'effectuer tout seul ou non, dans le contexte dont tu parles là, ce n'est pas le cas, donc inutile d'utiliser une tache CRON.

Parse error: syntax error, unexpected '=' in C:\wamp\www\CHAT_PROJET\chat.php on line 55

Le code que je t'ai montré, c'est juste un exemple, je ne peux pas savoir quel type de retour pour les données tu as pour tes requête SQL, du genre si c'est sous forme d'array ou d'objet, j'ai donc juste fais sous forme de tableau, si tu as un retour sous forme d'objet, ce n'est pas $verifi[0]['id'] mais $verifi[0]->id.

Ynèv
Auteur

oui mais j'ai toujours le meme probleme.

Ynèv
Auteur

j'ai finalement mis :

$verifi = $bdd->query('SELECT id FROM chatt');
if ($verifi->columnCount() === 7) {
    $id = $verifi[0]->id;
    $bdd->query('DELETE FROM chatt WHERE id = $id');
}

Aucun bug affiché mais le code semble ne pas agir

Ynèv
Auteur

if(isset($_POST['pseudoo'] , $_POST['messagee']) )
{

        $merdee = $_POST['pseudoo'];
        $merdeee =  $_POST['messagee'];

$req = $bdd->prepare('INSERT INTO chatt (message, pseudo) VALUES(?, ?)');
$req->execute(array($merdeee, $merdee));

$verifi = $bdd->query('SELECT id FROM chatt');
if ($verifi->columnCount() == 7) {
    $id = $verifi[0]->id;
    $bdd->query('DELETE FROM chatt WHERE id = $id');
}
if ($verifi->columnCount() > 7) {
    $id = $verifi[0]->id;
    $bdd->query('DELETE FROM chatt WHERE id = $id');
}

}

Aucun bug affiché mais le code semble ne pas agir

Que veux-tu dire par semble ne pas agir ?
Ensuite, si tes deux conditions exécutent exactement le même code, tu peux facilement le simplifier/réduire :

if ($verifi->columnCount() >= 7) {
    $first = $verify->fetch();
    $delete = $bdd->prepare('DELETE FROM chatt WHERE id = ?');
    $delete->execute([$first->id]);
}

Au passage, lorsque tu veux passer une/des variable(s) dans une requête SQL, tu dois utiliser les doubles quotes et non les simples, sinon ta variable ne sera pas interprétée.

Ynèv
Auteur

Correction du code :

$verifi = $bdd->query('SELECT id FROM chatt');
if ($verifi->columnCount() >= 7) {
    $first = $verify->fetch();
    $delete = $bdd->prepare("DELETE FROM chatt WHERE id = ?");
    $delete->execute([$first->id]);
}

Pas d'erreur mais dans la base de donnée rien n'est supprimé donc le code ne foctionne pas comme attendu.

Je ne peux t'aider plus actuellement, tu devrais débugger ta condition en deux étapes, la première en vérifiant que tu rentres bien dans la condition et la seconde en vérifiant si la requête est bien exécutée ou non.
Pour ceci tu as deux solution, soit dans ton application tu as fait un système de messages Flash, dans ce cas là tu fais tes messages Flash avec des messages qui énoncent l'étape et l'état, ou alors tu le fais avec de simples echo et pareil avec des messages qui énoncent l'étape et l'état.
Par exemple :

$flash = new FlashService();
$total = $verifi->columnCount();
if ($total >= 7) {
    $flash->add('Condition remplie', 'success');
    $first = $verify->fetch();
    $delete = $bdd->prepare("DELETE FROM chatt WHERE id = ?");
    if ($delete->execute([$first->id])) {
        $flash->add("Enregistrement {$first->id} supprimé", 'success');
    } else {
        $flash->add("Enregistrement {$first->id} non supprimé", 'error');
    }
} else {
    $flash->add("Condition non remplie : $total enregistrements", 'error');
}
Ynèv
Auteur

en faisant ton code la base de donnée enregistre les valeurs en commencant par ID = 29 et il enregistre dans la base de donnée aléatoirement ?!

Ynèv
Auteur

https://www.noelshack.com/2019-14-3-1554309185-bdd.png

je les ai enregistré ds l'orde des numméros.

Ynèv
Auteur

J'ai été obligé de ne pas mettre les $flash car PHP ne reconnaissait pas new FlashService() .

en faisant ton code la base de donnée enregistre les valeurs en commencant par ID = 29 et il enregistre dans la base de donnée aléatoirement ?!

Dans tous mes codes, il n'y a que le SELECT et le de DELETE, donc aucune insertion en base de données, il est donc impossible que l'un de mes codes modifie ton insertion d'origine.

J'ai été obligé de ne pas mettre les $flash car PHP ne reconnaissait pas new FlashService() .

C'est tout à fait normal, FlashService est une classe factice, c'est juste pour te donner l'exemple d'une méthode pour suivre pas à pas le code et avoir un visuel, c'est à toi de l'adapter selon si tu as un système de messages Flash afin d'avoir un visuel sur le dérouelement du script et plus spécifiquement la condition et la requête SQL de suppression.

Salut Ynèv,

Pourquoi vouloir une table ne contenant que 7 valeurs ?

Je pense que tu veux afficher uniquement 7 actualités ou les 7 derniers messages ou un truc dans le genre ?
Si c'est ça, il ne faut pas chercher à effacer tes données mais à filtrer l'affichage, ça sera beaucoup plus simple.

Par exemple

SELECT
    *
FROM
    maTable
ORDER BY
    id DESC
LIMIT 7

Ensuite, si tu veux faire du nettoyage par peur de prendre de la place, sache que ce n'est pas vraiment nécessaire. Tu pourrais avoir 1000 enregistrement que ça ne te poserait pas de problème. Toutefois, si tu veux nettoyer, tu peux faire une requête de temps en temps qui purge la table (avec un CRON par exemple mais tu peux aussi l'appeler à chaque mise à jour)

Sinon, si vraiment tu veux déclencher une action à chaque insertion et que ça soit gérer directement par la base de données, tu peux regarder du côté des triggers MySQL

Ynèv
Auteur

Merci pour votre aide.
J'ai finalement trouvé.