747 votes

Comment faire passer des variables et des données de PHP à JavaScript ?

J'ai une variable en PHP, et j'ai besoin de sa valeur dans mon code JavaScript. Comment puis-je faire passer ma variable de PHP à JavaScript ?

J'ai un code qui ressemble à ceci :

<?php
$val = $myService->getValue(); // Makes an API and database call

Sur la même page, j'ai du code JavaScript qui a besoin de la valeur de la balise $val à passer en tant que paramètre :

<script>
    myPlugin.start($val); // I tried this, but it didn't work
    <?php myPlugin.start($val); ?> // This didn't work either
    myPlugin.start(<?=$val?>); // This works sometimes, but sometimes it fails
</script>

3 votes

Est-ce que la parenthèse fermante manquante dans myPlugin.start(<?=$val?> intentionnel ? Est-il vrai que "ça marche parfois" ?

2 votes

En fait, c'est Ben qui l'a fait, mais disons que si $val est "42)" ça va bien marcher :D

986voto

Second Rikudo Points 59550

Il existe en fait plusieurs approches pour y parvenir. Certaines exigent plus de frais généraux que d'autres, et certaines sont considérées comme meilleures que d'autres.

Sans ordre particulier :

  1. Utilisez AJAX pour obtenir du serveur les données dont vous avez besoin.
  2. Faites écho des données dans la page quelque part, et utilisez JavaScript pour obtenir les informations du DOM.
  3. Faites écho aux données directement en JavaScript.

Dans cet article, nous allons examiner chacune des méthodes ci-dessus, et voir les avantages et les inconvénients de chacune, ainsi que la façon de les mettre en œuvre.

1. Utilisez AJAX pour obtenir du serveur les données dont vous avez besoin.

Cette méthode est considérée comme la meilleure, car vos scripts côté serveur et côté client sont complètement séparés. .

Pour

  • Meilleure séparation entre les couches - Si demain vous cessez d'utiliser PHP et souhaitez passer à une servlet, à une API REST ou à un autre service, vous n'aurez pas à changer grand-chose au code JavaScript.
  • Plus lisible - JavaScript est JavaScript, PHP est PHP. Sans mélanger les deux, vous obtenez un code plus lisible dans les deux langages.
  • Permet le transfert asynchrone des données - Obtenir les informations à partir de PHP peut être coûteux en temps et en ressources. Parfois, vous n'avez pas envie d'attendre l'information, de charger la page, et que l'information arrive à tout moment.
  • Les données ne se trouvent pas directement sur la balise - Cela signifie que vos balises sont exemptes de toute donnée supplémentaire et que seul JavaScript les voit.

Cons

  • Latence - AJAX crée une demande HTTP, et les demandes HTTP sont transportées sur le réseau et ont des latences de réseau.
  • État - Les données extraites par une requête HTTP distincte ne contiendront aucune information provenant de la requête HTTP qui a extrait le document HTML. Vous pouvez avoir besoin de ces informations (par exemple, si le document HTML est généré en réponse à la soumission d'un formulaire) et, dans ce cas, vous devrez les transférer d'une manière ou d'une autre. Si vous avez exclu l'intégration des données dans la page (ce qui est le cas si vous utilisez cette technique), cela vous limite aux cookies/sessions qui peuvent être soumis à des conditions de course.

Exemple de mise en œuvre

Avec AJAX, vous avez besoin de deux pages, l'une où PHP génère la sortie, et la seconde où JavaScript obtient cette sortie :

get-data.php

/* Do some operation here, like talk to the database, the file-session
 * The world beyond, limbo, the city of shimmers, and Canada.
 *
 * AJAX generally uses strings, but you can output JSON, HTML and XML as well.
 * It all depends on the Content-type header that you send with your AJAX
 * request. */

echo json_encode(42); // In the end, you need to echo the result.
                      // All data should be json_encode()d.

                      // You can json_encode() any value in PHP, arrays, strings,
                      //even objects.

index.php (ou quel que soit le nom de la page actuelle)

<!-- snip -->
<script>
    function reqListener () {
      console.log(this.responseText);
    }

    var oReq = new XMLHttpRequest(); // New request object
    oReq.onload = function() {
        // This is where you handle what to do with the response.
        // The actual data is found on this.responseText
        alert(this.responseText); // Will alert: 42
    };
    oReq.open("get", "get-data.php", true);
    //                               ^ Don't block the rest of the execution.
    //                                 Don't wait until the request finishes to
    //                                 continue.
    oReq.send();
</script>
<!-- snip -->

La combinaison des deux fichiers ci-dessus donnera l'alerte 42 lorsque le chargement du fichier est terminé.

Quelques lectures supplémentaires

2. Faites écho des données dans la page quelque part, et utilisez JavaScript pour obtenir les informations du DOM.

Cette méthode est moins préférable à AJAX, mais elle a tout de même ses avantages. Elle est toujours relativement séparé entre PHP et JavaScript dans le sens où il n'y a pas de PHP directement dans le JavaScript.

Pour

  • Rapidement - Les opérations DOM sont souvent rapides, et vous pouvez stocker et accéder à un grand nombre de données relativement vite.

Cons

  • Balisage potentiellement non sémantique - Habituellement, ce qui se passe, c'est que vous utilisez une sorte de <input type=hidden> pour stocker l'information, parce qu'il est plus facile d'obtenir l'information à partir de inputNode.value mais cela signifie que vous avez un élément sans signification dans votre HTML. Le HTML a le <meta> pour les données concernant le document, et HTML 5 introduit l'élément data-* des attributs pour des données spécifiquement destinées à être lues avec JavaScript et qui peuvent être associées à des éléments particuliers.
  • Salir la source - Les données générées par PHP sont directement transmises à la source HTML, ce qui signifie que vous obtenez une source HTML plus grande et moins ciblée.
  • Plus difficile d'obtenir des données structurées - Les données structurées devront être du HTML valide, sinon vous devrez échapper et convertir les chaînes vous-même.
  • Couplage étroit de PHP à votre logique de données - Comme PHP est utilisé dans la présentation, vous ne pouvez pas séparer les deux proprement.

Exemple de mise en œuvre

L'idée est de créer une sorte d'élément qui ne sera pas affiché pour l'utilisateur, mais qui sera visible pour JavaScript.

index.php

<!-- snip -->
<div id="dom-target" style="display: none;">
    <?php
        $output = "42"; // Again, do some operation, get the output.
        echo htmlspecialchars($output); /* You have to escape because the result
                                           will not be valid HTML otherwise. */
    ?>
</div>
<script>
    var div = document.getElementById("dom-target");
    var myData = div.textContent;
</script>
<!-- snip -->

3. Echo des données directement en JavaScript

C'est probablement le plus facile à comprendre.

Pour

  • Très facile à mettre en œuvre - Il suffit de très peu de choses pour mettre en œuvre ce système et le comprendre.
  • Ne salit pas la source - Les variables sont envoyées directement à JavaScript, de sorte que le DOM n'est pas affecté.

Cons

  • Couplage étroit de PHP à votre logique de données - Comme PHP est utilisé dans la présentation, vous ne pouvez pas séparer les deux proprement.

Exemple de mise en œuvre

La mise en œuvre est relativement simple :

<!-- snip -->
<script>
    var data = <?php echo json_encode("42", JSON_HEX_TAG); ?>; // Don't forget the extra semicolon!
</script>
<!-- snip -->

Bonne chance !

75 votes

"PHP n'a pas de fonctions d'échappement JavaScript triviales" - Qu'est-ce qui ne va pas avec json_encode ?

36 votes

Je ne suis pas d'accord avec "Très peu sûr !" et "Les données structurées sont difficiles". Encodez les données en JSON ( JavaScript Object Notation, après tout), et voilà !

14 votes

Qu'en est-il de l'importante surcharge et de la complexité du code que l'asynchronisme introduit lors d'une requête AJAX ? Lorsque vous travaillez sur un site web léger en JavaScript, faire une requête AJAX est fastidieux et ne constitue pas une bonne pratique.

110voto

asdasd Points 381

J'utilise généralement les attributs data-* en HTML.

<div
    class="service-container"
    data-service="<?= htmlspecialchars($myService->getValue()) ?>"
>

</div>

<script>
    $(document).ready(function() {
        $('.service-container').each(function() {
            var container = $(this);
            var service = container.data('service');

            // Var "service" now contains the value of $myService->getValue();
        });
    });
</script>

Cet exemple utilise jQuery, mais il peut être adapté à une autre bibliothèque ou à du JavaScript classique.

Vous pouvez en savoir plus sur la propriété de l'ensemble de données ici : https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.dataset

3 votes

Cette réponse me semble en fait la plus simple pour les besoins de la plupart des gens. Vous avez gagné un vote positif !

4 votes

Je suis d'accord, je ne veux pas sur-analyser et mettre en place une solution fantaisiste pour un problème simple. Cette méthode sépare le PHP du Javascript, de sorte que le PHP continue à générer uniquement le HTML, tandis que le Javascript peut être externe au fichier PHP.

2 votes

Je suis d'accord pour dire que c'est la meilleure option. Elle résout tous les problèmes de sécurité, sans la latence. Vous pouvez garder JS entièrement en dehors de vos pages HTML. Le HTML doit être servi par le serveur d'application, mais pas JS (ni CSS). C'est également plus sémantique.

100voto

Benjamin Gruenbaum Points 51406

Je vais essayer une réponse plus simple :

Explication du problème

Tout d'abord, comprenons le déroulement des événements lorsqu'une page est servie par notre serveur :

  • Lorsque PHP est exécuté, il génère le HTML qui est servi au client.
  • Ensuite, le HTML est livré au client, après que PHP en ait fini avec lui. Je tiens à souligner qu'une fois que le code quitte le serveur, PHP en a fini avec lui et ne peut plus y accéder.
  • Ensuite, le HTML avec JavaScript atteint le client, qui peut exécuter JavaScript sur ce HTML.

Donc vraiment, la chose essentielle à retenir ici est que HTTP est apatride . Une fois qu'une demande a quitté le serveur, le serveur ne peut plus y toucher. Donc, cela laisse nos options à :

  1. Envoyer plus de demandes du client après la demande initiale est faite.
  2. Encodez ce que le serveur avait à dire dans la demande initiale.

Solutions

La question centrale que vous devriez vous poser est la suivante :

Suis-je en train d'écrire un site web ou une application ?

Les sites web sont principalement basés sur des pages, et les temps de chargement des pages doivent être aussi rapides que possible (par exemple - Wikipedia). Les applications Web sont davantage axées sur AJAX et effectuent de nombreux allers-retours pour fournir rapidement des informations au client (par exemple, un tableau de bord boursier).

Site web

Envoyer d'autres requêtes du client après que la requête initiale ait été effectuée est lent car elle nécessite davantage de requêtes HTTP, ce qui entraîne une surcharge importante. En outre, elle nécessite asynchronisme car la réalisation d'une requête AJAX nécessite un gestionnaire pour le moment où elle est terminée.

Je voudrais no recommander de faire une autre demande à moins que votre site soit une application pour obtenir cette information du serveur.

Vous voulez des temps de réponse rapides qui ont un énorme impact sur la conversion et les temps de chargement. Faire des requêtes Ajax est lent pour le temps de chargement initial dans ce cas et inutile.

Vous avez deux façons d'aborder le problème

  • Définir un cookie - Les cookies sont des en-têtes envoyés dans les requêtes HTTP que le serveur et le client peuvent lire.
  • Encodez la variable en JSON - JSON est très proche des objets JavaScript, et le plus Les objets JSON sont des variables JavaScript valides.

Mise en place d'un cookie n'est vraiment pas très difficile, il suffit de lui attribuer une valeur :

setcookie("MyCookie", $value); // Sets the cookie to the value, remember, do not
                               // Set it with HTTP only to true.

Ensuite, vous pouvez le lire avec JavaScript en utilisant document.cookie :

Voici un parseur roulé à la main, mais la réponse dont j'ai donné le lien juste au-dessus en propose de meilleurs :

var cookies = document.cookie.split(";").
    map(function(el){ return el.split("="); }).
    reduce(function(prev,cur){ prev[cur[0]] = cur[1]; return prev },{});
alert(cookies["MyCookie"]); // Value set with PHP.

Les cookies sont bons pour un petit nombre de données. C'est ce que font souvent les services de suivi.

Une fois que nous avons plus de données, nous pouvons les encoder avec JSON à l'intérieur d'une variable JavaScript :

<script>
    var myServerData = <?=json_encode($value)?>; // Don't forget to sanitize
                                                 //server data
</script>

En supposant que $value es json_encode capable du côté PHP (il l'est généralement). C'est ce que fait Stack Overflow avec son chat par exemple (mais en utilisant .NET au lieu de PHP).

Application

Si vous écrivez une application, le temps de chargement initial n'est pas toujours aussi important que les performances continues de l'application, et il devient intéressant de charger les données et le code séparément.

Ma réponse aquí explique comment charger des données en utilisant AJAX en JavaScript :

function callback(data){
    // What do I do with the response?
}

var httpRequest = new XMLHttpRequest;
httpRequest.onreadystatechange = function(){
    if (httpRequest.readyState === 4) { // Request is done
        if (httpRequest.status === 200) { // successfully
            callback(httpRequest.responseText); // We're calling our method
        }
    }
};
httpRequest.open('GET', "/echo/json");
httpRequest.send();

Ou avec jQuery :

$.get("/your/url").done(function(data){
    // What do I do with the data?
});

Maintenant, le serveur doit juste contenir un /your/url route/fichier qui contient le code qui saisit les données et en fait quelque chose, dans votre cas :

<?php
$val = myService->getValue(); // Makes an API and database call
header("Content-Type: application/json"); // Advise client of response type
echo json_encode($val); // Write it to the output

De cette façon, notre fichier JavaScript demande les données et les affiche plutôt que de demander du code ou de la mise en page. C'est plus propre et cela commence à porter ses fruits à mesure que l'application s'élève. C'est aussi une meilleure séparation des préoccupations et cela permet de tester le code côté client sans qu'aucune technologie côté serveur ne soit impliquée, ce qui est un autre avantage.

Post-scriptum : Vous devez être très conscient des vecteurs d'attaque XSS lorsque vous injectez n'importe quoi, du PHP au JavaScript. C'est très difficile d'échapper aux valeurs correctement et c'est sensible au contexte. Si vous n'êtes pas sûr de la façon de traiter les XSS, ou si vous n'en êtes pas conscient, lisez ce qui suit. cet article de l'OWASP , celui-ci y cette question .

0 votes

Nitpick : Il n'existe pas d'"objet JSON" (à part celui qui a l'attribut parse y stringify méthodes). JSON est par définition une séquence de caractères.

4 votes

@cHao plus généralement - les encodages sont définis comme une séquence de caractères et l'existence d'objets conceptuels est une question philosophique. Cependant, les objets JSON existent et sont définis par la grammaire JSON. {} est un objet JSON valide - voir json.org

1 votes

Si vous utilisez cette définition, alors tous Les "objets JSON" sont valables en JS.

48voto

Jessé Catrinck Points 28
<script>
  var jsvar = <?php echo json_encode($PHPVar); ?>;
</script>

json_encode() nécessite :

  • PHP 5.2.0 ou plus
  • $PHPVar codé en UTF-8, Unicode.

0 votes

Vous êtes génial ! La réponse en une ligne de code est toujours la meilleure !

8voto

andrew Points 3960
myPlugin.start($val); // Tried this, didn't work

Cela ne fonctionne pas parce que $val n'est pas défini en ce qui concerne JavaScript, c'est-à-dire que le code PHP n'a rien sorti pour l'option $val . Essayez de visualiser la source dans votre navigateur et voici ce que vous verrez :

myPlugin.start(); // I tried this, and it didn't work

Et

<?php myPlugin.start($val); ?> // This didn't work either

Cela ne fonctionne pas parce que PHP essaiera de traiter myPlugin comme une constante et si cela échoue, il essaiera de la traiter comme la chaîne de caractères 'myPlugin' qu'il essaiera de concaténer avec la sortie de la fonction PHP start() et comme c'est indéfini, cela produira une erreur fatale.

Et

 myPlugin.start(<?=$val?> // This works sometimes, but sometimes it fails

Bien que cela ait de grandes chances de fonctionner, puisque le code PHP produit du JavaScript valide avec les arguments attendus, si cela échoue, il y a de fortes chances que ce soit parce que myPlugin n'est pas encore prêt. Vérifiez votre ordre d'exécution.

Vous devez également noter que le code PHP en sortie n'est pas sécurisé et doit être filtré avec json_encode() .

EDIT

Parce que je n'ai pas remarqué la parenthèse manquante dans myPlugin.start(<?=$val?> :-\

Comme le souligne @Second Rikudo, pour que ça fonctionne correctement. $val devrait contenir la parenthèse fermante, par exemple : $val="42);"

Cela signifie que le PHP produira maintenant myPlugin.start(42); et fonctionnera comme prévu lorsqu'il sera exécuté par le code JavaScript.

0 votes

Encodez vos données en JSON : myPlugin.start(<?=json_encode($val)?>);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X