Conseils Sessions
Bonjour a tous,
je suis toujours sur ma page fiche produits et j'aurais besoin de conseils .
J'ai une page modification de produits existants (càd que le produit a déjà été encodé dans la base de données et que l'on peut le mettre à jour si on le veut). Cette page contient des champs dont les valeurs sont préremplie par les données correspondantes dans la base de données. Chacun de ces champs peut être modifié par l'utilisateur.
S'affichent également sur cette page les images du produit (au nombre de 5) qui sont également dans la bd. Pour chacune des images, j'ai la possibilité de les modifier. Pour cela, on clique sur un bouton "changer image" qui renvoie vers une autre page qui permet de sélectionner une nouvelle image. De cette page en cliquant sur un bouton "upload", on retourne sur le formulaire puis si on le désir on peut changer les images suivantes par la même technique.
J'ai choisi cette méthode pour que l'image changée puisse être prévisualisée.
Bref, les images sont ± au milieu de mon formulaire et donc avant d'arriver aux champs images, l'utilisateur aura peut etre déjà changé certains champs texte. La solution à laquelle j'avais pensé, était d'utiliser les sessions (tout nouveau pour moi) afin de conserver les données déjà encodées. Mais là où je rencontre un problème, c'est que les données des champs sont lus depuis la base de données et sont donc mis dans des variables de session et que si on retourne sur le formulaire (après avoir uploadé une nouvelle image) il n'a pas conservé les modifications faites puisque dans la session sont enregistrées les données lues dans la base de données.
Je ne vois pas trop comment 1° lire les données de la bd et les stocker dans des variables de sessions ?
2° stocker les modifications dans ces mêmes variables de sessions? En gros, ne doivent être modifiées que les champs modifiés
Vos conseils sont donc les bienvenu.
Réponses apportées à cette discussion
Salut Paintbox,
une idée comme ça : Crée une variable de session parallèle, par exemple $_SESSION['modifications'] dans laquelle tu pourrais conserver les saisies du formulaire à partir du formulaire d'upload. Ça veut dire plusieurs choses :
- Du dois accéder au formulaire d'upload à partir d'un bouton du formulaire de modification et non à partir d'un lien : ce bouton doit soumettre le formulaire non pas vers le traitement mais vers le formulaire d'upload d'image; au chargement de ce dernier, tu pourras alors récupérer toutes les données du formulaire de modif;
- Au chargement du formulaire de modification, teste l'existence de la variable de session $_SESSION['modifications'] : si elle existe, utilise la pour pré-remplir le formulaire, sinon, utilise les données de la base.
- Lors de la validation du formulaire de modification, si les données sont bonnes et enregistrées, n'oublie pas de détruire la variable de session en question histoire de ne pas avoir de surprises en voulant modifier la fiche d'un autre article.
Autre option quoique peut-être moins évidente, upload avec AJAX, comme ça tu restes sur le formulaire de modification sans changer de page, simplement tu fais afficher un formulaire d'upload dans un DIV. Mais d'abord au niveau accessibilité, c'est moins heureux, ensuite si tu n'as pas un minimum de connaissances en JavaScript et AJAX, tu vas ramer peu pour réussir ça.
Hello Cyrano,
merci pour tes suggestions.
Effectivement ton idée de créer un $_SESSION['modifications'] est une excellente idée. Je vais tenter cette solution.
Je ne m'y connais pas en JavaScript ou Ajax même si il y a certainement moyen de trouver des solutions toutes faites sur le net.
J'essaie de mettre cela en place et je te tiens au courant.
Merci
Hello Cyrano,
me revoilà avec mon problème.
J'ai suivi tes conseils concernant l'utilisation d'une session (pour conserver les champs modifiés). Cela fonctionne correctement, mais j'ai quand même un problème car dans mon formulaire "modification", l'affichage des images se fait par consultation de la base de données. Elle ont chacune un numéro de "rang" qui me permet simplement lorsque je les ai enregistré (au début) de leur attribuer un nom selon la nomenclature suivante (type_de_bien+numéro_de_rang).
Donc là ou je rencontrais un problème c'est que j'ai eu beau créer une variable de session nommée ('rang_image') lorsque j'essayais de modifier cette image, le numéro de rang était chaque fois le numéro maximum et non le numéro courant.
Bref cela m'a permis de me familiariser avec les sessions, mais mon problème est toujours là. J'ai donc décidé de forcer l'upoad d'images avant de modifier la fiche produit.
J'ai donc fais des recherche sur le net et suis tombé sur un script en JavaScript qui permet d'ajouter autant de boutons 'ajouter une image' qu'on veut (on peut qd même limiter). Ceci m'arrange bien parce que je voulais justement donner cette possibilité à l'utilisateur.
J'ai pu intégrer cela à mon code php, mais là où je bloque à présent est que je n'arrive pas (ne connaissant pas JavaScript) à récupérer le nom du fichier uploadé pour pouvoir ensuite le renomer et l'enregistrer dans ma base de données et lui donner également un numéro de "rang". Ma fonction "ajout_image" permet de vérifier si une image est uploadée, la vérifie et la sauve dans un répertoire.
Pour info, ma page permet d'abord de rechercher l'article, puis affiche l'article recherche.
Je me tourne donc vers toi pour voir si tu sais m'aider à ce niveau. J'avais pensé utiliser un $_FILES['file']['name'] comme en PHP mais visiblement, ca ne marche pas.
J'ai également suivi tes conseils en tachant de mieux structurer mon code. J'espère que cela se remarque.
Voilà d'avance merci pour ton aide.
Voici mon code :
[code]
function create_champ(i) {
var i2 = i + 1;
document.getElementById('leschamps_'+i).innerHTML = '';
document.getElementById('leschamps_'+i).innerHTML += (i
Salut Paintbox,
Je crains que ton code ne m'aide pas des masses. Au passage, dans la barre d'outil du forum, il y un un petit logo « **** » pour insérer du code, sélectionne le langage correspondant, ce sera plus facile à lire et surtout, ça gardera la mise en forme.
Ceci étant, j'ai l'impression qu'il y a un point que tu n'as peut-être pas bien assimilé : le JavaScript est un langage client, le PHP est un langage serveur. Ça veut dire qu'il n'y a aucune interaction directe entre les deux, chacun s'exécutant sur une machine différente, le serveur pour le PHP, la machine de l'internaute pour le JavaScript. Par conséquent, lorsque ton formulaire est envoyé au serveur, le JavaScript n'intervient plus et perd toute information sur la page, page qu'on est en fait en train de quitter. Pour retrouver une valeur depuis le serveur dans le JavaScript de la page qui se charge, il te faut dans ce cas envoyer un code depuis le serveur incluant du code JavaScript dans lequel on crée une variable avec pour valeur une variable PHP. Illustration :
<?php
$uneVariable = "Une valeur quelconque";
$code_js = <<<CODE_JS
<script type="application/javascript">/* <![CDATA[ */
var ma_variable_js = '{$uneVariable}';
/* ]]> */</script>
CODE_JS;
echo($code_js);
?>
Et là, tu peux voir que coté serveur, je prépare une variable. Ensuite je prépare une autre variable qui va contenir le code JavaScript à envoyer vers le navigateur. Ce code JS contient lui-même une variable dont la valeur est préparée par PHP coté serveur. Une fois la page chargée dans le navigateur, en faisant afficher la source, tu vas trouver ceci :
<script type="application/javascript">/* <![CDATA[ */
var ma_variable_js = 'Une valeur quelconque';
/* ]]> */</script>
Voilà, partant de là, peut-être pourrais-tu reformuler ta question parce que je ne saisis pas bien ce que tu veux faire en JavaScript avec le nom du fichier... ;-)
Hello Cyrano,
merci pour tes explications. Je n'avais effectivement pas saisi que le Javascript s'exécute coté client (il me reste encore beaucoup de choses à assimiler mais je ne perds pas espoir).
En fait ce à quoi je souhaite arriver est qu'à partir d'un formulaire qui sert à encoder (en back-office) les différentes données sur le produit, qu'on puisse également enregistre un nombre x d'images. En gros que l'utilisateur puisse mettre un nombre non limité (avec un maximum malgré tout) d'images. Ce qui était pratique avec ce script Javascript, c'est qu'à partir d'un simple lien "ajouter une image", il rajoutait un bouton "choisir un fichier". C'est l'utilisateur qui choisit le nombres d'images qu'il souhaite mettre su cette fiche.
Je ne vois pas trop comment en PHP générer en cliquant sur un simple lien, un nouveau bouton "choisir un fichier". De plus, il faut que je rajoute une variable compteur qui intervient dans le nom qu'aura le fichier sur le serveur.
Jusque là je limitais à 5 le nombre d'images à charger.
Peut-être une fonction "créér un input type='file' " serait une piste ?
As-tu une idée, une piste?
Ok, là je saisis mieux la nature de ton problème.
Demande-toi ce que reçoit le serveur lorsque tu soumets le formulaire ? Des données $_POST, et éventuellement des données $_FILE. Pour ce dernier cas, tu as des identifiants de champ à utiliser pour traiter chaque image individuellement. Il faut donc que tu aies une manière de nommer dynamiquement les champs générés coté client en JavaScript de façon à pouvoir les reconstruire et les traiter coté serveur. La super-globale te permet au départ de savoir combien de fichiers sont reçus. Là, on parle de nombre : alors utilisons des nombres : suppose que le premier champ de type «file» de ton formulaire ait pour attribut name la valeur img_produit_1. Si tu fais générer un nouveau champ coté client, il serait pratique de le nommer img_produit_2, puis au besoin img_produit_3, etc...
Coté serveur, tu commences par récupérer le nombre d'images reçues. Ensuite, tu construis dynamiquement le nom dans une boucle commençant à 1 jusqu'au nombre d'image.
Éventuellement dans tes tests dans la page de traitement, utilise la fonction var_dump pour afficher ce qui est reçu en mettant par exemple :
<?php//...echo('<pre>' . "\n");var_dump($_FILE);echo('</pre>' . "\n");
Ajoute quelques champs avec ta fonction JavaScript et soumets le formulaire, puis regarde ce que tu obtiens de l'autre coté.
Ça devrait te permettre d'avancer pas mal ;-)
Hello Cyrano,
je reviens avec mon problème. J'ai réussi à récupérer et afficher les informations concernant mes fichiers uploadés via un " foreach($_FILES as $nom_champ => $fichier)". A ce niveau cela fonctionne.
Par contre, lorsque je veux traiter mon image càd vérifier son extension, son poids et la sauvegarder à l'aide de ma fonction "ajout_images", j'ai un message d'erreur "Undefined index: file". C'est visiblement au niveau de ma boucle "for ($i=0; $i
Salut Paintbox,
as-tu utilisé le petit bout de code que je t'ai suggéré ?
<?php
echo("<pre>\n");
var_dump($_FILES);
echo("</pre>\n");
Si oui, qu'as-tu vu s'afficher ? Ce que j'essaye de te faire voir, c'Est que peut-être bien que tu ne comptes pas le bon élément.
Par ailleurs, habitue-toi à optimiser ton code : au lieu de
<?php
//...
for ($i=0; $i<count($_FILES['file']['name']); $i++)
Écris plutôt :
<?php
//...
$nf = count($_FILES['file']['name']);
for ($i = 0; $i < $nf; $i++)
Quelle différence me demanderas-tu peut-être ? Tout simplement le le comptage dans le second exemple n'est effectué qu'une seule fois et on utilise seulement le résultat dans la boucle. Dans ton code, la fonction count() est exécutée à chaque tour de boucle. S'il doit y avoir 10000 tours, il y aura 10000 exécution de count(). Sur quelques tours, ce n'est certes pas significatif, mais sur l'ensemble d'une application, quelques fractions de secondes ici et là et on ralentit l'ensemble de façon parfois notable.
Enfin, sois logique dans la disposition de ton code : là, tu définis ta page et ensuite tu ajoutes les fonctions : n'oublie pas que le code est lu du début à la fin. Si tu fais un appel à une fonction avant que celle-ci ne soit définie, tu vas avoir des erreurs. Je suggère d'ailleurs que tu mettes tes fonctions dans des fichiers externes et que tu les insères lorsque c'est nécessaire, exactement de la même manière que tu fais une inclusion de ton code de connexion à la base de données.
Hello Cyrano,
oui effectivement j'ai directement mis les fonctions sur cette page parce que ces fonctions sont également utilisées par d'autres pages, et je voulais éviter de tout modifier. Je sui d'accord avec toi, c'est plus facile et propre avec un import de fonction. Quand à l'ordre effectivement j'ai inversé mais c'était pour tester et j'ai oublié de remettre mes fonctions en début de code.
Oui j'ai essayé ton bout de code :
<?phpecho("<pre>\n");var_dump($_FILES);echo("</pre>\n");
il me retourne ceci comme résultat:
array(1) { ["file_0"]=> array(5) { ["name"]=> string(14) "maison_025.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(36) "/Applications/MAMP/tmp/php/phpnHo91s" ["error"]=> int(0) ["size"]=> int(60773) }}
Je me rends bien compte que mon imput type="file" dans le Scrip Java se nomme ' name="file_'+i+'" ' . J'ai essayé de changer le
$_FILES['file']['name']
en
$_FILES['file_']['name']
mais cela ne change rien.
En même temps, ton var_dump($FILES) montre bien que $FILES n'est pas vide.
Je ne vois pas ?
Ok, comment boucluer sur un tableau dont on ne connait pas le nom exact de l'index de premier niveau ? Au lieu d'utiliser une boucle for(), utilises foreach().
On peut aunsi écrire :
<?php
foreach($_FILES as $index => $valeur)
{
//....
}
Ainsi, tu n'as pas besoin de savoir le nom exact de l'index, il sera dynamiquement retrouvé. Pas besoin de compteur non plus puisque la boucle foreach s'arrêtera lorsqu'il n'y aura plus d'élément.
Ici dans l'exemple, $index prendra donc la valeur de 'file_0' puis au tour suivant s'il y en a un 'file_1'. Mais si cet index s'appelait 'toto', ça marcherait pareil et lesuivant titi, même chose. Donc dans la boucle, on peut travailler sur un fichier à partir de $_FILES[$index] qui est également un tableau contenant les index *name*, *type*, *tmp_name*, *error* et *size*. Et en fait, c'Est la même chose que ce qu'il y a dans $valeur qui prend effectivement la valeur correspondant à l'index $index.
Je me doute que ce n'est peut-être pas très clair, enrichissons donc un peu l'exemple :
<?php
echo("<pre>\n");
var_dump($_FILES);
echo("</pre>\n");
foreach($_FILES as $index => $valeur)
{
$tmp_file1 = $_FILES[$index]['tmp_name'];
echo("<pre>Nom temporaire du fichier, première méthode :\n");
var_dump($tmp_file1);
echo("</pre>\n");
// Ou bien encore :
$tmp_file2 = $valeur['tmp_name'];
echo("<pre>Nom temporaire du fichier, seconde méthode :\n");
var_dump($tmp_file2);
echo("</pre>\n---------\n");
}
Adapte ça (il est quasiment utilisable tel quel) et teste le, observe le résultat.