Session + php include

Eléphant du PHP | 193 Messages

06 févr. 2007, 12:08

Bonjour à tous amis PHPéistes!

Je me suis encore mis dans la tête aujourd'hui de faire un truc trop compliqué pour moi:

je veux proposer de l'actualité et des dossiers thématiques; cependant, je pense qu'il est important que les internautes aient accés aux anciens dossiers.

J'ai donc mis un double include: un à gauche qui charge le dossier de la semaine, un à droite qui charge la dernière actualité: le problème est bien entendu, que lorsque je charge l'un des liens à gauche, php crée une erreur, et vice versa.

Code : Tout sélectionner

<body> <div id="global"> <?php include('menu_bandeau_piedpage.htm'); ?> <div id="contenu-actu"> <div id="menu-dossier"> <p><a href="http://develop.web.free.fr/actu.php?lien=semaine12">Semaine 12</a></p> <p><a href="http://develop.web.free.fr/actu.php?lien=semaine11">Semaine 11</a></p> <P>...</P> </div> <div id="dossier"> <?php include($_GET['lien'].'.htm'); ?> </div> <div id="menu-actu"> <p><a href="http://develop.web.free.fr/actu.php?lien2=actualite1">Revue de presse Vendée: mercredi 12</a></p> <p><a href="http://develop.web.free.fr/actu.php?lien2=actualite2">Revue de presse Vendée: mardi 11</a></p> <p>...</p> </div> <div id="actu-vendee"> <?php include($_GET['lien2'].'.htm'); ?> </div> <div id="pub"> </div> </div> </div> </body> </html>
J'ai fait un schéma pour mieux comprendre, mais je n'arrive pas à joindre l'image??? :oops:

Existe t-il une solution pour qu'au clic sur l'un des liens, une seule partie se recharge???

Merci par avance!
Modifié en dernier par Neomcdn le 09 févr. 2007, 15:23, modifié 3 fois.

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

06 févr. 2007, 12:22

Ne faudrait il pas tester si les index 'lien' et 'lien2' sont bien définis dans $_GET[] avant de les utiliser, et éventuellement s'assurer que le fichier existe bien avant de l'inclure ? :)
if(isSet($_GET['lien']) && file_exists($_GET['lien'].'.htm') )
  include($_GET['lien'].'.htm'); 
else 
  ...
Pour ne recharger qu'une partie de ta page, il faut te tourner vers ajax. Mais tu peux aussi t'en passer, car contre il te faut à chaque fois renvoyer les deux liens (ou les conserver en session) pour ne pas perdre le premier quand tu changes le second (et vice versa) :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Modérateur PHPfrance
Modérateur PHPfrance | 6037 Messages

06 févr. 2007, 12:29

Ce que tu fais est dangereux, car on peut inclure n'importe quel fichier.
Un peu de lecture (en français): http://www.phpsecure.info/v2/article/php-security.php
Règle n°2 du webmaster : Toujours commencer par le HTML qu'on veut obtenir....toujours ! :priere:
J'aime apprendre de nouvelles choses.

Eléphant du PHP | 193 Messages

06 févr. 2007, 12:31

Salut!

Les fichiers sont bien chargés, puisqu'au clic sur un des "lien" la page se charge: affiche la page htm, mais génère une erreur php, dans la partie droite de ma page. A l'inverse, quand je clique sur un "lien2", la page se charge, affiche à droite la page htm, mais génère une erreur php sur la partie gauche, ce qui est logique puisque l'url devient par exemple: http://develop.web.free.fr/actu.php?lien2=actualite1

L'idée des sessions me plaît assez, (puisque je ne veux pas me lancer dans ajax, avant de bien connaître les autres langages) mais comment on fait??

merci par avance!

Eléphant du PHP | 193 Messages

06 févr. 2007, 12:38

Je viens de lire la partie sur les include et la sécurité et j'avoue que je n'ai pas tout compris: notamment dans les techniques pour empêcher les accès au serveur.

Ajout d'une extension php?
A quoi ça sert? et comment ça marche??

Merci d'avance!!

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

06 févr. 2007, 17:51

En fait, ce qui se passe, c'est que lorsque tu cliques sur le lien de gauche, $_GET['lien2'] n'est pas renseigné et du coup il essaye d'inclure la page ".htm" (idem pour $_GET['lien'] lorsque tu cliques sur le lien de gauche.

Option 1 - en get - tu spécifies à chaque fois dans tes liens les valeurs de lien et lien2, en utilisant les valeurs récupérées :
- à gauche href="actu.php?lien=semaine12&lien2=<?php echo $lien2;?>"
- à droite href="actu.php?lien=<?php echo $lien;?>&lien2=actualite1"

avec un test préalable :
$lien = (isSet($_GET['lien'])) ? $_GET['lien'] : 'page_par_defaut'; // semaine
$lien = (isSet($_GET['lien2'])) ? $_GET['lien2'] : 'page_par_defaut'; // actu
Et tes includes deviennent :
if ( file_exists('./' . $lien . '.htm') )  // si la page .htm existe sur le serveur
  include('./' . $lien . '.htm');  // on l'inclue
Option 2 - par la session - lorsque tu récupères une valeur en get tu la colle en session pour palier les cas ou tu ne la récupère pas.
session_start();
...
// si la donnée est passée en get, on l'utilise, sinon (si la donnée est en session on l'utilise, sinon on prend la valeur par défaut)
$lien = (isSet($_GET['lien'])) ? $_GET['lien'] : (isSet($_SESSION['lien']) ? $_SESSION['lien'] : 'page_par_defaut'); // semaine
$lien2 = (isSet($_GET['lien2'])) ? $_GET['lien2'] : (isSet($_SESSION['lien2']) ? $_SESSION['lien2'] : 'page_par_defaut');  // actu
Il ne te reste plus alors qu'à mettre l'éventuelle nouvelle valeur en session :
$_SESSION['lien'] = $lien;
$_SESSION['lien2'] = $lien2;
Tes includes deviennent :
if ( file_exists('./' . $lien . '.htm') )  // si la page .htm existe sur le serveur
  include('./' . $lien . '.htm');  // on l'inclue
Et tes liens restent :
- à gauche href="actu.php?lien=semaine12"
- à droite href="actu.php?lien2=actualite1"
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 193 Messages

06 févr. 2007, 18:09

Merci Ryle!

Je te remercie tout de suite, parcequ'avant que je réussisse à le faire, il va me falloir un moment. Je pense que je vais prendre ton option 2, puisque je n'ai jamais fait de variables de session, et comme c'est indispensable dans PHP: je vais esssayé ça.

Je vais faire de mon mieux: merci en tout cas!

Eléphant du PHP | 193 Messages

08 févr. 2007, 18:55

Salut Ryle!!

J'ai donc tenté de mettre en oeuvre la session: J'ai malheureusement des erreurs PHP sur ma page.

J'ai donc plusieurs questions:

Dans ton code tu mets:
session_start(); 
... 
-> Faut-il que je nomme la session? Et à quoi correspondent les points de suspension?

Tu places ensuite ce code ci:
$lien = (isSet($_GET['lien'])) ? $_GET['lien'] : (isSet($_SESSION['lien']) ? $_SESSION['lien'] : 'page_par_defaut');
-> Je ne connais pas cette structure: à quoi correspond t'elle? Peut-on l'écrire d'une autre forme avec if, elseif et else?

Enfin si je comprends bien le code à placer dans les include; je ne comprends celui-là:

Code : Tout sélectionner

$_SESSION['lien'] = $lien;
Merci d'avance!

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

09 févr. 2007, 13:25

Alors on va commencer par un p'tit cours rapide sur les sessions :)

Une session, pour faire simple, c'est un tableau php qui s'appelle $_SESSION et qui est stocké en mémoire sur le serveur tant que l'utilisateur est connecté. L'intéret, c'est que tu peux y stocker des valeurs comme sur un tableau d'affichage, que chaque script de ton site peut venir consulter quand il en a besoin.

Pour qu'un script puisse utiliser ce tableau, il faut lui donner l'accès en "démarrant" la session avec la commande session_start().

Dans ton cas, ce que l'on veut faire, c'est se souvenir des pages qui ont été demandées (à droite et à gauche) lorsque l'on change l'une des deux, afin de conserver l'autre. Pour ça on va enregistrer ces infos dans le tableau de session, et venir le lire ensuite pour les ré-afficher.


Pour les trois petits points, c'est juste pour symboliser le code que tu peux avoir entre l'ouverture de la session et la suite :) Ca n'est naturellement pas une instruction php, donc à dégager ;)

Pour la syntaxe particulière "() ? :" il s'agit effectivement d'un if/else sous la forme ternaire (voire la faq) qui prend moins de place que sa forme complète (mais tu peux très bien l'utiliser aussi :))
$lien = 'page_par_defaut'; // valeur par défaut 

if (isSet($_GET['lien'])) { // si la donnée est passée en get
  // elle est explicitement demandée par l'utilisateur, donc on l'utilise :)
  $lien = $_GET['lien'];
}
else { // sinon
  if (isSet($_SESSION['lien'])) { // si la donnée existe en session 
    // c'est qu'elle a été précément demandée par l'utilisateur, donc on l'utilise
    $lien = $_SESSION['lien']; 
  }
  // pas besoin de else
}
faire de même avec $lien2

A partir de là, on sait quelle page afficher à gauche, que ce soit celle par défaut, celle demandée à l'instant par l'utilisateur ou encore celle demandée précédement. On va donc pouvoir l'afficher dans le include, et on va également en profiter pour aller l'écrire dans la session (sur mon tableau destiné aux autres scripts) et mettre à jour la valeur "demandée précédement" par celle-ci :)

C'est ce que je fais ici :
$_SESSION['lien'] = $lien; // stocke la nouvelle valeur de $lien dans la session

C'est y plus clair ? :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 193 Messages

09 févr. 2007, 16:13

Merci beaucoup pour le cours particulier,

Je comprends très bien le fonctionnement:

Juste deux souçis:
1 - Je ne comprends pas le morceau de code suivant:
if ( file_exists( '.  / ' . $lien . '.htm') )
Pourquoi avoir une partie faisant suite à la deuxième parenthèse d'ouverture et précédent $lien?

En gros on dit :
"Si fichier . / semaine12.htm existe, alors,..."

Mais ce fichier n'existe pas; semaine12.htm existe, d'où, est-ce que ' . / ' n'est pas en trop?

2 - J'ai plusieurs erreurs PHP qui sont liées à la session, comme si la session ne pouvait être récupérée. En haut de page:

Code : Tout sélectionner

Warning: session_start() [function.session-start]: open(/mnt/144/sda/4/1/develop.web/sessions/sess_d6fa56898d86060f810e37546ab6a9b9, O_RDWR) failed: No such file or directory (2) in /mnt/144/sda/4/1/develop.web/actu.php on line 3 Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at /mnt/144/sda/4/1/develop.web/actu.php:3) in /mnt/144/sda/4/1/develop.web/actu.php on line 3 Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /mnt/144/sda/4/1/develop.web/actu.php:3) in /mnt/144/sda/4/1/develop.web/actu.php on line 3
et en bas de page:

Code : Tout sélectionner

Warning: Unknown(): open(/mnt/144/sda/4/1/develop.web/sessions/sess_d6fa56898d86060f810e37546ab6a9b9, O_RDWR) failed: No such file or directory (2) in Unknown on line 0 Warning: Unknown(): Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/mnt/144/sda/4/1/develop.web/sessions) in Unknown on line 0
Où est mon erreur de syntaxe? J'ai repris le code que tu m'avais donné: et je l'ai placé en haut de page avant le code HTML.
J'ai placé les include dans le body.

:?: :?: :?:

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

09 févr. 2007, 16:58

Dans la mesure ou le paramètre $lien est envoyé par l'utilisateur (et donc modifiable, puisqu'il lui suffit de bricoler l'url pour en changer la valeur), tu ne peux pas avoir confiance en la valeur qui est passée. Il est par conséquent important de la contrôler un minimum.

La fonction file_exists() te permet de vérifier qu'un fichier existe physiquement sur la machine avant de l'inclure (et évite donc d'avoir une erreur si quelqu'un bricole le nom du fichier).
Dans un système de fichier, le chemin "./" correspond au dossier courant ( "../" correspond au dossier parent, et "/" correspond au dossier racine)

Le fait de tester "./fichier.htm" au lieu de "fichier.htm" te permet de t'assurer que le fichier existe et se trouve bien sur ton serveur. En effet, comme le nom du fichier est libre, si un petit malin glisse dans $file une adresse http pointant vers un script de son serveur, la fonction include() va l'inclure et l'exécuter, ce qui pourrait t'être préjudiciable. (il pourrait par exemple lister les fichiers de ton serveur, les consulter, choper ton mot de passe, pourrir ta base, etc.)

Par contre tu ne devrais pas avoir d'erreur... faut pas d'espace entr ele point et le slash ou le slash et le nom du fichier. Bon pis bien sur si tes fichiers ne sont pas dans le même dossier que le script, il suffit d'adapter le chemin à partir de celui-ci : '../dossier/'.$file.'.htm' par exemple :)

Pour les warning concernant la session, si tu es chez free.fr, pour utiliser les sessions, il te faut créer un dossier "sessions" à la racine de ton site. Tu ne devrais plus avoir les alertes ensuite :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 193 Messages

09 févr. 2007, 18:47

Merci!

-> Ok! C'est une question de sécurité! Effectivement, il faut qu'on se penche sur ce côté là aussi.

-> J'ai testé ta première méthode qui fonctionne nickel: c'est simple et efficace.

-> Tu avais raison pour les erreurs liées aux sessions qui effectivement étaient dues à Free: comme tu me l'as indiqué, j'ai ajouté un dossier appelé sessions à la racine et cela fonctionne très bien.

-> Par contre, il y a encore un problème au niveau de la session:

- Je clique à droite sur mon deuxième lien, la session enregistre effectivement le 1er lien à gauche.
- Si maintenant, je clique sur le 2ème lien à gauche, la page recharge le 1er lien à droite.

Cela donne l'impression que la nouvelle valeur n'est pas enregistrée en session.

Aurais-je fait une erreur de syntaxe?

Code : Tout sélectionner

<?php $_SESSION['lien'] = $lien; // stocke la nouvelle valeur de $lien dans la session $_SESSION['lien2'] = $lien2; // stocke la nouvelle valeur de $lien dans la session session_start(); $lien = 'semaine12'; // valeur par défaut if (isSet($_GET['lien'])) { // si la donnée est passée en get // elle est explicitement demandée par l'utilisateur, donc on l'utilise :) $lien = $_GET['lien']; } else { // sinon if (isSet($_SESSION['lien'])) { // si la donnée existe en session // c'est qu'elle a été précément demandée par l'utilisateur, donc on l'utilise $lien = $_SESSION['lien']; } // pas besoin de else } $lien2 = 'actualite1'; // valeur par défaut if (isSet($_GET['lien2'])) { // si la donnée est passée en get // elle est explicitement demandée par l'utilisateur, donc on l'utilise :) $lien2 = $_GET['lien2']; } else { // sinon if (isSet($_SESSION['lien2'])) { // si la donnée existe en session // c'est qu'elle a été précément demandée par l'utilisateur, donc on l'utilise $lien2 = $_SESSION['lien2']; } // pas besoin de else } ?>
Vous pouvez voir le problème ici:
http://develop.web.free.fr/actu.php

:oops: :roll: Désolé, j'espère que je ne t'embetterai plus pour ce problème. Merci encore!

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

09 févr. 2007, 19:05

C'est juste un petit problème d'ordre :)

pour pouvoir appeller $_SESSION, il te faut avoir démarrer la session, sinon il considera qu'il s'agit d'un simple tableau dans ton script et non au niveau du serveur. Il faudrait donc inverser :
<?php 
session_start();  

$_SESSION['lien'] = $lien; // stocke la nouvelle valeur de $lien dans la session 
$_SESSION['lien2'] = $lien2; // stocke la nouvelle valeur de $lien dans la session 
?>
Mais ca ne suffira pas :) A ce moment là de ton script, $lien et $lien2 n'ont aucune valeur, ces variables ne sont même pas encore définies. C'est donc après les avoir définies et initialisée avec une valeur (du get, de la précédente ou par défaut) qu'il faut mettre à jour ta session :

$lien = 'semaine12'; // valeur par défaut  

if (isSet($_GET['lien'])) { // si la donnée est passée en get 
  // elle est explicitement demandée par l'utilisateur, donc on l'utilise :) 
  $lien = $_GET['lien']; 
} 
else { // sinon 
  if (isSet($_SESSION['lien'])) { // si la donnée existe en session  
    // c'est qu'elle a été précément demandée par l'utilisateur, donc on l'utilise 
    $lien = $_SESSION['lien'];  
  } 
  // pas besoin de else 
} 

$_SESSION['lien'] = $lien; // stocke la nouvelle valeur de $lien dans la session 
Ca devrait le faire :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 193 Messages

10 févr. 2007, 20:41

Bonjour Ryle!!

J'étais prêt à reposter pour dire que cela ne fonctionait pas dans mon cas, mais non, c'est mon cher ie qui ne se mettait pas à jour. Quelle joie de voir qu'après avoir vider le cache, tout fonctionne correctement: j'ajoute que firefox recharge la page de manière transparente. en comparaison ie recharge les sous-menus à chaque clic: vive FF!!!

Merci et encore merci pour tout le temps que tu as passé sur mon post. L'avantage est que j'ai bien compris tout ce que je fais: merci de m'avoir aidé donc mais surtout merci de m'avoir tout traduit, tout expliqué!!

Respect! ça fait plaisir: j'espère que ce post pourra servir à d'autres.

Ce n'est pas sans grande émotion que je place le [résolu] sur mon message!

PS: Merci! :D :D

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

10 févr. 2007, 21:42

Cool !!! :)

Pour le cache de IE, c'est un parametre que les gens peuvent régler dans les options du cache de leur navigateur (vérifier s'il existe une version plus récente à chaque visite de la page). Mais tu peux empêcher l'utilisation du cache avec ces quelques lignes
<?php
header("Expires: Mon, 01 Jan 2000 05:00:00 GMT");             	// Date du passé
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 	// toujours modifiée
header("Cache-Control: no-cache, must-revalidate");           	// HTTP/1.1
header("Pragma: no-cache");
?>
Ce sont des headers, donc à placer avant tout code html, espace ou retour charriot envoyé au navigateur. Le but c'est de dire au navigateur que la version de la page qu'il a en cache est toujours expirée, pour qu'il récupère toujours celle qui est en ligne :)

Content en tout cas que tu ais bien compris le principe des sessions :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...