Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Passer une valeur quelconque de PHP a JavaScript

37 réponses
Avatar
Olivier Miakinen
[ diapublication entre fcl.php et fcl.javascript, suivi sur fcl.php(¹) ]

Bonjour,

La question que je me pose, je suis étonné de ne pas l'avoir encore vue
passer. Je n'ai rien trouvé non plus dans la FAQ, même si j'ai trouvé
la question inverse (avec une réponse lapidaire assez logique :
<http://faqfclphp.free.fr/#rub2.8>).


Je voudrais transmettre le contenu d'une variable de type chaîne de
caractères de PHP à JavaScript. À priori, rien de plus simple :
var str = '<?php echo $str; ?>';

Mais le problème, c'est que la chaîne en PHP $str peut contenir à peu
près n'importe quoi, par exemple des caractères chinois ou japonais,
mais aussi des apostrophes simples (') ou doubles ("), des sauts de
ligne, des barres obliques dans un sens et dans l'autre (/ et \) et
ainsi de suite.

Je précise que le codage de $str est de l'UTF-8, et celui du fichier
HTML aussi. Il ne peut pas y avoir de caractère invalide (genre une
valeur CP1252 entre 128 et 159 transformée en UTF-8 comme si c'était
du Latin-1) mais à peu près tout point de code valide entre U+0001 et
U+FFFF est susceptible de s'y retrouver.

Comment puis-je faire pour assurer que ça marche dans tous les cas ?

Cordialement,
--
Olivier Miakinen

(¹) Si votre réponse utilise plus de JavaScript que de PHP, n'hésitez
pas à changer de groupe pour la suite de la discussion.

10 réponses

1 2 3 4
Avatar
Cenekemoi
Bonjour à Olivier Miakinen <om+ qui nous a écrit :
(...)
- les quatre « LineTerminator » qui sont Line Feed (n, U+000A),
Carriage Return (r, U+000D), Line separator (U+2028) et Paragraph
separator (U+2029).

Du coup, le code suivant fait ce que je veux :

<?php
function php2js($str)
{
$from > array("", "'", '"', "r", "n", "xE2x80xA8", "xE2x80xA9");
$to > array('\', ''', '"', 'r', 'n', 'u2028', 'u2029');
return str_replace($from, $to, $str);
}



Désolé, mais je connais mal PHP (je suis plutôt Java), mais je comprend
mal ce que va donner les changement de "r" et "n" en 'r' et 'n'.
Peux-tu m'éclairer, STP ?

--
Cordialement, Thierry ;-)
Avatar
Olivier Miakinen
Le 08/12/2008 13:56, Alex Marandon a écrit :

À mon avis utiliser PHP pour générer des chaines littérales JavaScript
n'est pas une bonne idée, justement à cause du problème que tu évoques.



Eh, il ne faudrait quand même pas jeter le bébé avec l'eau du bain ! Le
problème n'est pas insurmontable, j'ai d'ailleurs trouvé une solution
moi-même après avoir lu le standard ECMA-262 (3e éd.).

<news:
------------------------------------------------------------------------
<?php
function php2js($str)
{
$from array("", "'", '"', "r", "n", "xE2x80xA8", "xE2x80xA9");
$to array('\', ''', '"', 'r', 'n', 'u2028', 'u2029');
return str_replace($from, $to, $str);
}
?>

...

var str = '<?php echo php2js($str) ?>';

ou

var str = "<?php echo php2js($str) ?>";
------------------------------------------------------------------------

En revanche ce qui me surprend c'est d'être apparemment le seul à me
poser la question. Est-ce qu'il n'arrive jamais à personne d'avoir
en base de données une valeur contenant un saut de ligne, valeur à
transmettre fidèlement à l'utilisateur ?

[...] Pour ne pas faire de requêtes HTTP
supplémentaires, tu peux inclure tes données dans le DOM:
<div id="data" style="display:none"><?php echo $str; ?></div>
Tu n'as plus alors qu'à gérer les problèmes d'échapement habituels liés
à HTML.



Non, ça n'est pas une bonne solution car alors les séries de caractères
blancs (retours chariot, sauts de ligne, espaces, tabulations...) sont
remplacées par une unique espace. La chaîne n'est donc plus la même.
Avatar
Olivier Miakinen
Le 08/12/2008 14:40, Pierre Goiffon a écrit :

Je génère sur le serveur une page HTML incluant du code JavaScript.
Dans ce code, il y a des initialisations de variables du style
« var truc = 3; » ou « var machin = 'chaîne'; », et je voudrais
m'assurer que ce que je mets à la place de « chaîne » sera toujours
correct, même si au départ c'est dans une variable PHP et que cette
variable peut contenir n'importe quels caractères unicode valides.



Que signifie "toujours correct" ?



1) Que ça ne fasse pas planter le script. ;-)
2) Que les caractères écrits soient bien compris par JavaScript.

A première vue du moment que la chaine ne contient pas de ' et vu ce qui
a été dis (page en UTF-8 et tous les caractères sont corrects) alors
qu'est-ce qui ne pourrait pas aller ?



J'avais posé la question avant d'aller relire attentivement la norme,
mais je savais déjà qu'un saut de ligne ne pouvait pas être transmis
tel quel. Après relecture, je sais maintenant que les seuls caractères
à protéger sont l'apostrophe, la barre oblique , LF (U+000A), CR
(U+000D), LS (U+2028) et PS (U+2029).
Avatar
Olivier Miakinen
Le 08/12/2008 16:31, Cenekemoi a écrit :

<?php
function php2js($str)
{
$from >> array("", "'", '"', "r", "n", "xE2x80xA8", "xE2x80xA9");
$to >> array('\', ''', '"', 'r', 'n', 'u2028', 'u2029');
return str_replace($from, $to, $str);
}



Désolé, mais je connais mal PHP (je suis plutôt Java), mais je comprend
mal ce que va donner les changement de "r" et "n" en 'r' et 'n'.
Peux-tu m'éclairer, STP ?



Oui, bien sûr. "n" représente l'unique caractère dont le code ASCII ou
Unicode est 10, tandis que 'n' est une chaîne de deux caractères, de
codes respectifs 92 () et 110 (n). Pour info, 'n' signifie la même
chose que "n". Idem avec "r" (code 13) et 'r' (égal à "r").

Cordialement,
--
Olivier Miakinen
Avatar
Cenekemoi
Bonjour à Olivier Miakinen <om+ qui nous a écrit :
(...)
Pour info, 'n' signifie la
même chose que "n". Idem avec "r" (code 13) et 'r' (égal à "r").



Ok, compris ! Merci pour l'explication...

...et c'est vrai que dans nos applications Java, nous n'avons pas a
priori de CRLF dans les données avec lesquelles nous travaillons.

Mais je vais quand même vérifier tout cela et peut-être blinder la bête
!...

--
Cordialement, Thierry ;-)
Avatar
Alex Marandon
Olivier Miakinen wrote:
En revanche ce qui me surprend c'est d'être apparemment le seul à me
poser la question. Est-ce qu'il n'arrive jamais à personne d'avoir
en base de données une valeur contenant un saut de ligne, valeur à
transmettre fidèlement à l'utilisateur ?



Non c'est simplement que, comme signalé précédemment, on évite en
général de génerer du JavaScript dynamiquement.

[...] Pour ne pas faire de requêtes HTTP
supplémentaires, tu peux inclure tes données dans le DOM:
<div id="data" style="display:none"><?php echo $str; ?></div>
Tu n'as plus alors qu'à gérer les problèmes d'échapement habituels liés
à HTML.



Non, ça n'est pas une bonne solution car alors les séries de caractères
blancs (retours chariot, sauts de ligne, espaces, tabulations...) sont
remplacées par une unique espace. La chaîne n'est donc plus la même.



Heu tu es sûr de ça ? Je ne suis pas suffisament motivé pour tester dans
différents browsers mais je viens de faire quelques essaus avec Firefox
et les espaces sont bien conservés tels quels. Peut-être confonds-tu
avec la manière dont les browsers *affichent* les séries de caractères
blancs à l'écran ?
Avatar
Olivier Miakinen
Le 08/12/2008 18:08, Alex Marandon a écrit :

En revanche ce qui me surprend c'est d'être apparemment le seul à me
poser la question. Est-ce qu'il n'arrive jamais à personne d'avoir
en base de données une valeur contenant un saut de ligne, valeur à
transmettre fidèlement à l'utilisateur ?



Non c'est simplement que, comme signalé précédemment, on évite en
général de génerer du JavaScript dynamiquement.



D'accord. Et en effet, comme tu le signales, on peut toujours créer une
valeur dans un élément du DOM puis la relire en JavaScript. Cela dit,
ma méthode marche aussi et je ne vois pas trop ce qu'on pourrait lui
reprocher.

[...] ça n'est pas une bonne solution car alors les séries de caractères
blancs (retours chariot, sauts de ligne, espaces, tabulations...) sont
remplacées par une unique espace. La chaîne n'est donc plus la même.



Heu tu es sûr de ça ? Je ne suis pas suffisament motivé pour tester dans
différents browsers mais je viens de faire quelques essais avec Firefox
et les espaces sont bien conservés tels quels. Peut-être confonds-tu
avec la manière dont les browsers *affichent* les séries de caractères
blancs à l'écran ?



Tu as raison, je confondais avec le rendu d'affichage. Dont acte.
Avatar
Alex Marandon
Olivier Miakinen wrote:
Le 08/12/2008 18:08, Alex Marandon a écrit :
En revanche ce qui me surprend c'est d'être apparemment le seul à me
poser la question. Est-ce qu'il n'arrive jamais à personne d'avoir
en base de données une valeur contenant un saut de ligne, valeur à
transmettre fidèlement à l'utilisateur ?


Non c'est simplement que, comme signalé précédemment, on évite en
général de génerer du JavaScript dynamiquement.



D'accord. Et en effet, comme tu le signales, on peut toujours créer une
valeur dans un élément du DOM puis la relire en JavaScript. Cela dit,
ma méthode marche aussi et je ne vois pas trop ce qu'on pourrait lui
reprocher.



Il y a d'abord le problème inhérent à la génération de code en général,
on se retrouve avec deux niveaux de code à débugguer, écrits dans deux
langages différents.

Il y a aussi les problèmes liés à l'optimisation du temps de chargement
des pages. Générer du JavaScript dynamiquement rends difficile et/ou
inefficace la concaténation et la minification du code ainsi que
l'exploitation des caches. Si ton projet ne fait pas grand chose côté
client, ce n'est pas un problème, mais à mesure que la quantité de code
JavaScript grossit, ça peut en devenir un.

Il y a enfin un problème de séparation des préocupations. Comme tu l'as
dit, tes données proviennent côté serveur d'une base de données. Il ne
te viendrait pas à l'esprit de générer côté serveur du PHP contenant tes
données dans des chaines littérales, avant d'éxcuter ce code (remarque y
en a bien qui ont du le faire ;) De même que, côté serveur, les données
ont leur place dans une base de données, côté client, dans les browsers,
la représentation des données se fait en principe soit en mémoire dans
des structures de données JavaScript, soit de manière sérialisée avec
HTML (et en pratique généralement avec une combinaison des deux).
Mélanger données et code ne contribue pas à une conception claire et
modulaire. Après, si tu es de ceux qui pensent que mélanger HTML, CSS,
SQL, JavaScript et PHP dans un même fichier ne pose pas de problèmes
particuliers, ce dernier argument ne te parles probablement pas :)
Personnellement il m'arrive de générer des chaines littérales JavaScript
en phase d'expérimentation/prototypage mais je m'assure toujours que ça
n'aille pas en production.
Avatar
Olivier Miakinen
Le 08/12/2008 19:15, Alex Marandon a écrit :

[ plein de choses très justes ]



Je me rends à tes arguments.

Histoire de te rassurer sur mes pratiques douteuses, il faut savoir que
je suis en train de découvrir les bases de données (j'ai commencé jeudi
dernier à lire une doc de référence) et que je fais juste des petites
pages de test pour voir ce que ça donne. Pour l'une d'elles, j'ai fait
un formulaire dans lequel on est invité à saisir un texte, et mon
programme PHP vérifie que le texte saisi est le même que celui qu'on
avait déjà saisi précédemment. L'endroit où j'ai généré du JavaScript
directement à partir de PHP, c'est la fonction optionnelle qui vérifie
la même chose en JavaScript avant de faire la requête au serveur.

Cela dit, je n'ai pas su trouver (mais j'ai sans doute mal cherché) des
tutoriels donnant quelques méthodes standard du style « page de login »,
« changement de mot de passe », etc. Cela m'aurait sans doute évité
cette erreur de newbie.

Cordialement,
--
Olivier Miakinen
Avatar
Mickael Wolff
Olivier Miakinen a écrit :
Et bien sûr il faudra faire le json_decode dans la partie
JavaScript.



C'est un eval de la chaîne qu'il faut faire en fait.


Mais c'est intéressant à connaître pour des structures de données
complexes (des tableaux de tableaux par exemple). Encore merci !



JSON a le vent en poupe pour shunter XML dans les cas où il est
certain que la cible est un navigateur Web comprenant ecmascript.

var datas = eval(xhr.responseText) ;

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
1 2 3 4