Hello

Contexte :

Voilà j'ai un projet web, avec un chat, le but est d'avoir accès à certaines fonctionnalités tel que son profil, des produits en vente etc ...

Objectif :

j'ai plusieurs pages product.php, profile.php, chat.php pour faire simple. J'ai souhaité migré tout dans une page index.php
Pourquoi ? Pour garder le chat en live (socket) je dois eviter à tout prix les refresh de page :).

Avec les includes en php pas de problèmes à vue d'oeil quand je passe par le .load en JQuery ça me fait des erreurs des php genre

Class Not Found
$user undeclared

Solution essayés :

1 - Display none

Alors j'ai déjà pensé à faire dans mon index.php des

<!-- Dans index.php -->
<?php 
<div id = "page">
include('product.php');
include('chat.php');
include('profile.php');
?>
</div>

et de passer 2 en display none et jouer avec le css pour afficher/ cacher les différentes pages.
Mais cette solution de ne me va pas car j'ai des parties de ma pages web que j'ai besoin de rafraichir à certains moment et si le load ne marche pas :/

2 - Jquery .load ou $.ajax

Comme je l'ai signalé au dessus je me retrouve avec des erreurs php, des includes qui sont fait dans mon index.php ne sont pas répercuté dans les sous pages.
Quand je fait $('#pages').load('product.php'); ça ne charge pas les includes et les script inclus dans index.php.

Y a t-il une solution à ce problème (sans passer par les GET & POST pour passer les variables) ?

Je tiens à remercier d'avance ceux qui participeront au sujet.

24 réponses


betaWeb
Réponse acceptée

Le soucis c'est que ta variable $user est déclarée dans ton index.php, mais non dans chat.php, donc tu ne peux potentiellement pas l'utiliser dans ce script.
Deuxièmement, pourquoi veux-tu injecter le contenu dans ta balise ayant l'id #pages alors que vraisemblablement celle-ci contien les liens permettant l'appel des pages (donc en gros ton menu) ??

index.php

<?php $infos = ['user' => 'toto']; ?>

<div id="menu">
    <a class="active" class="pages" data-page="chat" data-infos="<?= json_encode($infos) ?>">chat</a>
</div>

<div id="pages"></div>

app.js

function refresh(pagename, infos) {
    $.ajax({
        url: pagename + '.php',
        data: { 'ajax': '1', 'infos': infos }, // On envoie une variable histoire de vérifier si le script PHP est appelé en AJAX
        method: 'POST',
        type : 'POST',
        dataType: 'html',
        success: function(html) {
            if (0 === html.length) {
                alert('Erreur lors du chargement du contenu');
                return false;
            }

            $("#pages").empty().prepend(html);
            // OU (c'est pareil)
            // $("#pages").html(html);
        }
    });
}

$('#menu').on('click', 'a', function(e){
    e.preventDefault();

    var self = $(this),
        page = self.data('page') || self.attr('data-page'),
        infos = self.data('infos') || self.attr('data-infos');   

    refresh(page, infos);        

    return false;
});

chat.php

<?php
    $infos = json_decode($_POST['infos'], true);

    ob_start(); ?>
    <?php $html = ob_get_clean();
        <p><?= $infos['user']; ?></p>
    <?php $html = ob_get_clean();

    // Fin du script si appelé via ajax
    if (isset($_POST['ajax']) && 1 == $_POST['ajax']) {
        echo $html;
        return false;
    }
    return $html;
?>

Ca devrait NORMALEMENT fonctionner.

Yop !

Alors déjà commence par corriger ton code dans "index.php":

<!-- Dans index.php -->
<div id = "page"> // Cette balise était était l'ouverture de PHP, pas bon
<?php
    include('product.php');
    include('chat.php');
    include('profile.php');
?>
</div>

Et sinon, lorsque tu es sur ta page de chat, tu es sur index.php ou non ? Ce n'est pas très clair ton histoire.

AminMe
Auteur

Oups effectivement mais c'était un exemple :)

Alors je suis en continue sur index.php et je charge dynamiquement le contenu de chat.php, profile.php et product.php. Mon url est toujours site/index.php

Montres voir le contenu de ton JS ?

AminMe
Auteur

Mon app.js

function refresh(link) {

    $('#pages').load(link);

}

Mon index.php (preview)

<?php
include ("classes/classes.php"); //contient classe Database
session_start();
$user = $_SESSION['user'];
?>
...
<li class="mt">
                    <a class="active" onclick=refresh('product.php')>
                        <span>Produits</span>
                    </a>
                </li>

Quand je clique sur le lien Produits ça me dit

Class Database Not Found
$user undeclared

Bah voilà tu as ta réponse, il te faut chercher de ce côté là.
Google est ton ami !

AminMe
Auteur

C'est ce que j'ai déjà fait, après avoir parcouru 10 conversation de stackeoverflow et des tutoriels je n'ai pas eu ma réponse d'ou mon arrivé ici.
J'ai appris que php était chargé bien avant tout et donc les variables php était inconnu par la suite par le js.

Surement je n'ai pas tapé les bon mots-clés :D

Beh en chargeant index.php il te faut déjà avoir déclaré yes variables et instancié les classes dont tu as besoin oui.
Tu fais ça où normalement ?

AminMe
Auteur

Alors je me suis mal exprimé toutes mes variables sont instanciés dans index.php tout en haut du code. Au dessus de tout.
les sous fichiers product.php chat.php profile.php font appel à ces variables.

lors de l'appel d'un include ('profile.php'); dans l'index.php pas de probleme car il va absorbé le code dans profile.php et l'injecter dans index.php et du coup dans profile.php si je fait echo $user;tout se passe bien. avec le load en JQuery non ça va me dire user not declared

Alors ce qu'il te faut faire, c'est au lieu d'un $.load() utiliser un $.ajax(). De cette manière tu vas pouvoir injecter ton contenu HTML généré par le script PHP (produits.php par exmple) dans ta page courante. Alors attention il y a une petite spécificité, il faut "echo" ton contenu en fin de script PHP afin que ton ajax puisse le récupérer et l'afficher. Tu me suis ?

AminMe
Auteur

Alors j'avais utilisé un $.ajax() : mais pas de la bonne manière.

function refresh(link) {

    //$('#pages').load(link);
    $.ajax({
        url: link,
        success: function(html) {
            $("#pages").html(html);
        }
    });
}

Il faut que je echo ou en fait dans chaque sous pages (product, chat, profile) ou dans index.php ?

Pour la partie JS:

function refresh(link, target) { // target correspond au bloc dans lequel tu vas injecter le contenu HTML

    //$('#pages').load(link);
    $.ajax({
        url: link,
        data: { 'ajax': '1' }, // On envoie une variable histoire de vérifier si le script PHP est appelé en AJAX
        method: 'post',
        dataType: 'html',
        success: function(response) {
            if (0 === response.length) {
                alert('Erreur lors du chargement du contenu');
                return false;
            }
            $(target).empty().prepend(response);
            // OU (c'est pareil)
            $(target).html(response);
        }
    });

    // Ou tu peux aussi utiliser la mixin $.post() qui fait la même chose
    $.post(link, { 'ajax': '1' }, function(response){
            if (0 === response.length) {
            alert('Erreur lors du chargement du contenu');
            return false;
            $(target).empty().prepend(response);
            // OU (c'est pareil)
            $(target).html(response);
    });
}

En fin de script PHP:

/* Traitements PHP + Génération de ton HTML (pour lequel je te conseille d'utiliser les fonctions ob_start() et ob_get_clean() ) */

// Fin du script si appelé via ajax
if (isset($_POST['ajax']) && 1 == $_POST['ajax']) {
    die($html); // On coupe l'execution ici en affichant le contenu de la variable $html, en l'occurrence ton contenu
}
return $html; // Fin du script si non appelé via ajax

Si tu as des questions n'hésites pas ;)

AminMe
Auteur

Si j'ai bien compris si je transforme toutes ma page php en une string il n'y aura plus de problème.

J'ai cherché sur le net mais faire des echo avec plein de concaténations, à toutes les lignes c'est la seul solution ?

j'ai essayer de faire

$html = <<<EOD

mais je n'ai pas l'impression que ça marche très bien

De plus quand je fait un test à la main du style :

            $("#pages").empty().prepend('<p>test</p><?php echo "aie"; echo "hello : ".$user; ?>');

sur la page ça ne m'affiche que test, le php est mis en commentaire

En même temps si tu mets du PHP dans un JS ça ne risque pas de fonctionner !
De plus, il y a la concaténation oui, mais ce n'est pas très propre si le HTML généré est conséquent. Il vaut mieux utiliser ob_start() et on_get_clean():

<?php
  // Début du script php

  $html = "";  
  ob_start(); ?>
        // Génération de ton contenu HTML (SANS echo justement)
        // Exemple:
            <h1><?= $titre ?></h1>
            <?php if (!empty($nom)) : ?>
                 <p><?= $nom ?></p>
            <?php endif; ?>
            <p><?= $contenu ?></p>
            <ul>
                <?php foreach ($liste as $entry) : ?>
                    <li><?= $entry ?></li>
                <?php endforeach; ?>
            </ul>
        // !Exemple (ce n'est qu'un exemple)
  <?php $html = ob_get_clean();

  // Traitements PHP éventuels

// Fin du script si appelé via ajax
if (isset($_POST['ajax']) && 1 == $_POST['ajax']) {
    echo $html;
    return false;
}
return $html;
?>

Comme tu peux le voir, on met le HTML en "dur" entre les balises ob_start() & ob_get_clean().

AminMe
Auteur

Ah d'accord.

Néamoins j'ai toujours la même erreur Notice: Undefined variable: user in Project/test.php on line 7 je dois m'y prendre mal :

Avant tout j'ai une question <h1><?= $user ?></h1> c'est normal que la balise commence par <?= ? j'ai essayé avec la balise d'ouverture php ça ne fonctionne pas non plus.

<?php
// Début du script php

$html = "";
ob_start(); ?>

    <h1><?= $user ?></h1>

<?php $html = ob_get_clean();

// Traitements PHP éventuels

// Fin du script si appelé via ajax
if (isset($_POST['ajax']) && 1 == $_POST['ajax']) {
    echo $html;
    return false;
}
return $html;
?>

Je suis assez sur que la variable $user est défini :) dans index.php

<?php
include ("classes/classes.php");
session_start();

//$user = $_SESSION['user'];
if(!array_key_exists('user',$_SESSION)){
    header("Location:login.php");
    exit;
}
else {
    $user = $_SESSION['user'];

    // affichage de index.php
    ?>

Bien sûr que c'est normal, "<?=" c'est le raccourci pour echo ;)

Eh beh fais un petit var_dump() de $_SESSION voir ce qu'il contient. Peut être que ta fonction login ne rempli pas correctement l'array $_SESSION ?

AminMe
Auteur

var_dump() me donne

array (size=1)
  'user' => string 'test@test.fr' (length=XX)

j'ai juste caché la length. mais sinon ça marche très bien ma session est bien rempli.

On récapitule pour voir si on n'est pas parti sur un quiproco

index.php
Déclaration des variables $user etc ...+ appel de la fonction ajax refresh()
pour injecter les pages product, chat, profile dans la page index.php
app.js
contient la fonction refresh pour appeler les sous fichiers product, chat, profile
product.php, chat.php, profile.php

appel la variable $user déclaré dans index.php + ob_start() et ob_get_clean()

Tu as un session_start(); au début de chaque script PHP ?

AminMe
Auteur

non j'ai rien mis pour le moment

on retrouve ces 2 lignes

include ("classes/classes.php");
session_start();

seulement dans index.php

alors remets ces deux lignes au début de tous tes scripts PHP et ré-essaye.

AminMe
Auteur

J'ai essayé mais ça ne change rien :/

on va faire un cas de figure simple (oublions les includes + session_start). c'est censé marcher ?
moi je veux que cette chose marche xD

index.php
<?php
$user = 'toto';
?>

<div id="pages">
    <a class="active" onclick=refresh('chat.php')>chat</a>
</div>
chat.php
<?php
ob_start();
?>
<?= $user ?>
<?php $html = ob_get_clean();
// Traitements PHP éventuels

// Fin du script si appelé via ajax
if (isset($_POST['ajax']) && 1 == $_POST['ajax']) {
    echo $html;
    return false;
}
return $html;
?>
app.js
function refresh(link) {

    $.ajax({
        url: 'test.php',
        data: { 'ajax': '1' }, // On envoie une variable histoire de vérifier si le script PHP est appelé en AJAX
        method: 'POST',
        type : 'POST',
        dataType: 'html',
        success: function(html) {
            if (0 === html.length) {
                alert('Erreur lors du chargement du contenu');
                return false;
            }

            $("#pages").empty().prepend(html);
            // OU (c'est pareil)
            //$("#product-part").html(html);
        }
    });
AminMe
Auteur

C'était un exemple. Je n'ai pas mis de menu à proprement dit dans l'exemple. Mais effectivement tu as raison.

Petit problème ma page chat.php utilise app.js pour d'autres raisons. Quand je fait donc un clique sur ma page chat tout s'affiche correctement mais les boutons ne répondent plus au app.js.

Alors qu'avant si, une action était enclenché.

AminMe
Auteur

Bon je reviens sur le sujet

Au final j'ai changé de stratégie, je ne savais pas que je pouvais sérialiser en JSON les sockets et les faire passer dans le sessionStorage (ou localStorage) du coup ça m'aide à garder une variable de socket en continu.

Merci de m'avoir aidé tout de même :D !

Oh je t'en prie, content que tu aies solutionné ton problème. Effectivement le sessionStorage est une solution (que j'utilise régulièrement dans mes apps JS), mais il ne faut pas en abuser et faire attention à la sécurité car tu vas stocker des infos user côté client et non côté serveur.