[RESOLU] table sous forme de variable qui me met en erreur

Eléphant du PHP | 63 Messages

23 sept. 2016, 16:44

bonjour à tous.
voilà j'expose...
je me fais un genre de livre de compte
mes principales tables sont 01 pour janvier, 02 pour février, etc...
je souhaite sélectionner mon extrait de compte ou enregistrer mes écritures selon le mois en cours.
je le génère de la façon suivante qui est un peu simple.
je montre simplement ce quoi je décris plus haut.

Code : Tout sélectionner

<?php $annee= date("Y"); $mois= date("m"); $query=$db->prepare("SELECT * FROM $mois"); $query->execute(); echo'<table> <tr><td>mois</td><td>année</td><td>detail</td><td>commentaire</td><td>total</td></tr>'; while($data=$query->fetch()) { echo'<tr><td>'.$data['mois'].'</td><td>'.$data['annee'].'</td><td>'.$data['detail'].'</td><td>'.$data['commentaire'].'</td><td>'.$data['total'].'</td></tr>'; } echo'</table>'; ?>
la page me génère une erreur SQL du type

Code : Tout sélectionner

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '09' at line 1' in /home/julien/www/compta/index.php:29 Stack trace: #0 /home/julien/www/compta/index.php(29): PDOStatement->execute() #1 {main} thrown in /home/julien/www/compta/index.php on line 29

Eléphant du PHP | 63 Messages

23 sept. 2016, 16:46

une idée pour mettre mes table en variable?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 sept. 2016, 17:15

Bonjour,

Un nom de table peut comporter des chiffres, mais ne devrait pas être exclusivement numérique. MySQL te permet de le faire en utilisant les apostrophes inversées ` à l'intérieure desquels tu peux mettre n'importe quoi, mais c'est à un mon sens une très mauvaise pratique. Mieux vaut simplement préfixer le nom de tes tables (ex : mois_01, mois_02 ...). Tu pourras alors faire un " SELECT * FROM mois_$mois".

Pour autant, l'année prochaine, ta table 01 correspondant à janvier contiendra aussi bien les informations du mois de janvier 2016 que celles de 2017. Ca ne parait donc pas vraiment pertinent d'avoir un tel découpage par mois. Mieux vaux associer une date à tes écritures et filtrer en fonction de celle-ci :
SELECT ... FROM ma_table_ecriture WHERE MONTH(date_ecriture) = $mois AND YEAR(date_ecriture) = $year
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 63 Messages

23 sept. 2016, 17:27

merci de ta réactivité
j'ai conçu mes tables des mois de cette manière....
CREATE TABLE IF NOT EXISTS `01` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`annee` text NOT NULL,
`total` decimal(10,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
donc 12 au total.
et une 13ème qui s'appelle détail qui contient mois année et le détail des écritures...
je vais testé ce que tu m'as conseillé et je re pour dire
merci encore.

Eléphanteau du PHP | 26 Messages

25 sept. 2016, 10:36

Bonjour,
je vois que tu as intégré une variable dans ta requête sql mais ça n'est pas possible de le réaliser comme ça, je pense que c'est l'origine du plantage.

tu as deux solution pour utiliser une variable dans une requête sql soit tu fait de la concaténation c'est assez chiant et on se perd vite enfin va voir sur internet,
soit tu utilise prepare et execute mais correctement cette fois :
$query= $db->prepare('"SELECT * FROM :mois ');
$req->execute(array('mois' => $mois'));

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

26 sept. 2016, 10:01

@mineyou sa syntaxe php est correcte et ne pose pas trop de problème, ce qui est con c'est d'utiliser une requête préparée pour rien ;)
@Juvamine : + un pour un changement du modèle la c'est rapidement un merdier sans nom pour trouver les données.
comme l'indique Ryle une colonne de type date te permet de différencier rapidement les donnés.
si tu veux le mois de septembre 2016 tu peux faire simplement un truc dans ce genre :
select les,champs, from tableCompte where month(champDate)=9 and year(champDate) = 2016
(pour mysql).

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 63 Messages

26 sept. 2016, 14:42

ok
merci encore
@Ryle: ok ça fonctionne pour le SELECT * FROM mois_$mois
@Moogli: donc mon champ annee je le met en type year ou autre que texte alors comme j'ai indiqué plus haut?
je test un peu tout ça et je re.

en revanche si quelqu'un a une meilleur idée que moi sur l'agencement de mes tables ce serait la bienvenue ;)
j'ai fais de cette manière:
12 tables pour chaque mois comprenant 3 champs: id; annee; total
1 table detail pour le détail des écritures: id; jour; mois; annee; descrition; credit; debit; fixe; montant

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

26 sept. 2016, 17:21

ben
id : int pk
dateOperation : date
descrition varchar
typeOperation : int check in(1,2) => 1 debut, 2 crédit (ou l'inverse)
fixe => la je sais pas ce que sais :)
montant : decimal x,2

avec une table comme ça tu insères les données toujours de la même façon.
ensuite pour récupérer les données d'un moi pour une année c'est le select que j'ai mis plus haut
select les,champs, from tableCompte where month(dateOperation )=9 and year(dateOperation ) = 2016
pour les opérations du mois de septembre 2016
je fais un truc dans le genre, et j'ai fait la base ainsi : https://github.com/tipounet/go-bank/blo ... o-bank.sql
C'est loin surement pas une référence, mais ça colle au besoin sans problème de données ou tables dupliquées.

@+
Il en faut peu pour être heureux ......

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

26 sept. 2016, 18:44

Je plussois, il vaut mieux tout mettre dans une seule table, tant pis si elle contient des tonnes d'enregistrements, c'est robuste une base sql :))

Par contre pour typeOperation je verrais plus une enum('D', 'C') => D débit, C crédit ... c'est quand même plus simple que de se demander si 2 c'est un crédit ou un débit ;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 63 Messages

26 sept. 2016, 21:31

encore merci de vos lumières c'est cool d'avoir plusieurs avis pour ce faire une bonne idée.
@moogli: la partie fixe c'est ce que je renseignerai pour le salaire ou edf/gdf, FAI par exemple comme ça chaque mois les partie debit/credit fixe incrémentera automatiquement mon tableau. ché pas si j'ai bien expliqué.
je vais tester tout ça et je vous tiens au jus.
encore merci à tous.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

27 sept. 2016, 09:08

@Ryle : wé c'est pas con, moi j'ai fait une table pour le casoù XD ceci dit l'enum suffit et est parlante.

@juvamine : mais de rien :)
pour le reste faut voir en fonction des besoins, mais plus tes tables collent aux données et non au métier moins tu te fait chier.
si tu as des dépense récurrente rien ne t'empeche de coder un cron qui les ajoutes (genre une table qui stocke les récurences (image de celle des dépences) et en début de chaque moi un cron qui copie de l'une vers l'autre avec le bonne date ;)

c'est une idée parmis pas mal d'autre
Il en faut peu pour être heureux ......

Eléphant du PHP | 63 Messages

29 sept. 2016, 15:26

salut à tout :)
bon tout se passe bien pour l'avancement de ce projet d'ailleurs bientôt fini.
j'ai juste un problème de calcul sur le champ 'typeOperation' de la valeur c et d pour calculer le restant sur le compte.
j'ai fait une requête du genre

Code : Tout sélectionner

$query=$db->prepare("SELECT SUM(typeOperation)=c AS TOTAL AND SUM(typeOperation)=d AS TOTAL FROM detail WHERE mois=9 AND annee=:annee"); $query->execute(array('c'=>$c,'d'=>$d,'annee'=>$a)); $data=$query->fetch();
et ça me met ça comme message d'erreur
Notice: Undefined variable: c in /home/juju/www/test/liste_mois.php on line 210
Notice: Undefined variable: d in /home/juju/www/test/liste_mois.php on line 210
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens' in /home/juju/www/test/liste_mois.php:210 Stack trace: #0 /home/juju/www/test/liste_mois.php(210): PDOStatement->execute(Array) #1 {main} thrown in /home/juju/www/test/liste_mois.php on line 210
donc ma requête n'est pas bonne
pouvez-vous m'aider sur cette requête?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

29 sept. 2016, 16:10

salut,

oula oui c'est pas du sql de compete ça !!
il faut tester (toujours) ses requêtes dans un client sql dans ce genre de cas

La il te faut utiliser group by (c'est fait les fonctions de groupe comme sum ou count)
SELECT  SUM(lacolonnequivabienQuicontientLesMontants) AS TOTAL, typeOperation FROM detail group by typeOperation WHERE mois=:mois AND annee=:annee
et du coup j'ai mis le mois en paramètre ;-)~
comme ça tu va avoir une somme pour chaque type d'opération.

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 63 Messages

29 sept. 2016, 23:38

re-salut
la req ne fonctionne pas.
je dois m'y prendre très mal.
je te donne mon ptit bout de code pour que tu comprennes ce que je veux faire.
le but est de récupérer le total (t) des débit (typeOperation(d)) et crédit (typeOperation(c)) pour connaître ce qui reste sur le compte

Code : Tout sélectionner

//-----------MANQUE A TROUVER LA BONNE REQ LOL------------- //ancienne req foireuse de ma part=>$query=$db->prepare("SELECT SUM(typeOperation)=c AS TOTAL AND SUM(typeOperation)=d AS TOTAL FROM detail WHERE mois=9 AND annee=:annee"); //ta req=>$query=$db->prepare("SELECT SUM(t) AS TOTAL, typeOperation FROM detail group by typeOperation WHERE mois=:mois AND annee=:annee"); //$query->bindValue(':c', $c, PDO::PARAM_STR); //$query->bindValue(':d', $d, PDO::PARAM_STR); //$query->bindValue(':mois', $m, PDO::PARAM_STR); //$query->bindValue(':annee', $a, PDO::PARAM_STR); //$query->execute(); //$rest=$c-$d; //----------------------------------------------------- echo'<table> <tr><td>total crédit</td><td>total débit</td><td>restant</td></tr> <tr><td>'.$c.'</td><td>'.$d.'</td><td>'.$rest.'</td></tr> </table>'; //-----------
les champs concernés sont comme ceci:
typeOperation=>enum('d','c')
t=>decimal(x,2)

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

30 sept. 2016, 08:14

c'est quoi la table actuellement ?

la requête que je t'ai indiqué fait ce que tu demandes et retourne deux lignes (une pour chaque type d'opération,, tu fais la différence et tu as le delta sur le mois.
Par contre, effectivement sans le solde il faut faire le calcul depuis le début (donc virer le prédicat) et faire la différence crédit - débit, si c'est négatif t'es dans le rouge XD

@+
Il en faut peu pour être heureux ......