Page 1 sur 1

Array Php (Smarty) vers Javascript

Posté : 03 oct. 2008, 19:37
par lux
Hello tout le monde.

Bon, ça fait 2 heures que je sèche, ça me dépasse.

Alors, j'ai un array en php tel que :
Array
(
    [0] => Array
        (
            [id] => 81
            [url_data] => 0.jpg
        )

    [1] => Array
        (
            [id] => 82
            [url_data] => 1.jpg
        )

    [2] => Array
        (
            [id] => 83
            [url_data] => 2.jpg
        )

    [3] => Array
        (
            [id] => 84
            [url_data] => 3.jpg
        )
)
Je l'envoye dans mon template smarty avec
$smarty->assign('array',$array);
La, je l'envoye dans une fonction javascript comme ça :

Code : Tout sélectionner

<body onload="liste('{$array}');">
Cette fonction liste listera le contenu de l'array. (C'est pour pouvoir déplacer les éléments de la liste dynamiquement avec les Sortables de Mootools, but final.)
Bon, et dans la fonction javascript, pour l'instant, j'ai ça :

Code : Tout sélectionner

function liste(array) { alert(array[0]['id']); }
Et ça me renvoye comme valeur : "undefined".

Bon, j'ai creusé un peu, j'ai tenté de faire un "json_encode" dans php avant l'envoie vers smarty, c'est encore pire car ça désactive complètement la fonction javascript.

Donc la je cale, comment je fais passer cet array proprement à travers le bazar ?

Merci d'avance pour toute idée, pendant ce temps je vais continuer de chercher de mon côté aussi. :wink:

Posté : 03 oct. 2008, 20:47
par sadeq
Le json_encode() tu dois le mettre pour la fonction javascript et non smarty. Car smarty est un framework côté php et donc la méthode :
$smarty->assign('array',$array);
attend bien une variable php qui est dans notre cas $array.

Mais javascript s'exécute côté navigateur (après la fin de php) donc la formule :
<body onload="liste('{$array}');">
est incorrecte car il faut passer le contenu linéaire de $array et non $array lui même (php étant incapable de sérialiser automatiquement un array) Il faut donc le sérialiser avant de le passer à la fonction javascript. Et la meilleur façon est d'utiliser Json (intégré à PHP5 désormais) qui permet une passerelle d'objets entre php et javascript.

Tu dois écrire alors:
echo '<body onload="liste(' . json_encode($array) . ')">'; 

Posté : 03 oct. 2008, 21:06
par lux
Tu dois écrire alors:
echo '<body onload="liste(' . json_encode($array) . ')">'; 
Oui mais ça ça me fait mettre du php dans le fichier .tpl. C'est pas top.

J'ai essayé ça :
$smarty->assign('array',json_encode($array));
Dans le .tpl, si j'affiche l'array comme ça, ça me donne ça :

Code : Tout sélectionner

[{"id":"81","url_data":"0.jpg"},{"id":"82","url_data":"1.jpg"},{"id":"83","url_data":"2.jpg"},{"id":"84","url_data":"3.jpg"},{"id":"85","url_data":"4.png"}]
Donc c'est sérialisé comme chaîne de caractère non, au format json ?

Et donc je fais :

Code : Tout sélectionner

<body onload="liste('{$test}');>
, et un "alert('test');" dans la fonction liste, il m'affiche rien du tout, comme si la fonction refusait de se faire appeler.

Posté : 03 oct. 2008, 21:49
par sadeq
Ok, je comprends. Tu écris ton html dans un template. Dans ce cas c'est bon ce que tu fais.

Dans php :
$smarty->assign('array',json_encode($array));
Ce qui crée une variable smarty nommée "array".

Et dans le template :

Code : Tout sélectionner

{literal}<body onload="liste('{/literal}{$array}{literal}');>{/literal}
Ici, on intègre la variable smarty "array" dans le code du template.

Posté : 03 oct. 2008, 22:05
par lux
Hmm c'est pas encore ça. Pourquoi avec mis les litéral autour du html ?

Ce que vois en sortie en affichant l'array tout simplement dans la page :

(Dans le fichier .tpl)

Code : Tout sélectionner

<div>{$array}</div>
Sur la page s'affichera :

Code : Tout sélectionner

[{"id":"81","url_data":"0.jpg"},{"id":"82","url_data":"1.jpg"},{"id":"83","url_data":"2.jpg"},{"id":"84","url_data":"3.jpg"},{"id":"85","url_data":"4.png"}]
Bon, maintenant si je fais :

(Dans le fichier .tpl)
<body onload="liste('{$test}');">
Et ça m'affiche dans la source de la page:

Code : Tout sélectionner

<body onload="liste('[{"id":"81","url_data":"0.jpg"},{"id":"82","url_data":"1.jpg"},{"id":"83","url_data":"2.jpg"},{"id":"84","url_data":"3.jpg"},{"id":"85","url_data":"4.png"}]');">
Et la, la fonction ne semble rien recevoir en entrée.

Un idée, ce ne serait pas du aux "" qui perturberaient le truc ? mais vu que c'est entre simple quotes ' ' comme une chaine, ça ne doit pas influer.

Posté : 03 oct. 2008, 22:17
par sadeq
si si. Ce sont les " qui se trouvent dans le tableau sérialisé qui gênent les " du onload. Tu peux utiliser les ' (apostrophes) à la place :

Code : Tout sélectionner

<body onload='liste({$test});'>
Remarque: $test n'est pas considéré comme une chaine mais comme un objet tableau sérialisé. Donc, pas de délimiteurs de texte ''.

ps: pour le {literal} tu peux oublier c'est une façon d'écrire.

Posté : 03 oct. 2008, 22:34
par lux
Bon, les données semblent passer dans le javascript.

Reste la récupération de ses données. Je dois décoder le json maintenant ?

De plus si je fais un

Code : Tout sélectionner

alert(array);
dans ma fonction liste, il m'affiche "undefined".

Y aurait pas un print_r sous javascript pour que je puisse voir le contenu ?

Posté : 03 oct. 2008, 23:03
par sadeq
Il faut maintenant corriger au niveau de la fonction javascript:
function liste(array)
{
alert(array[0]['id']);
}
Le champ "id" n'est plus considéré comme index de tableau comme sous php mais comme propriété de l'objet créé par json. Il doit être noté : array[0].id

Explication : Quand on a fait un json_encode($array) en php, json a créer un tableau javascript où chaque case est elle même un objet contenant les dimensions nommées du array php en tant que propriétés.

Correction:

Code : Tout sélectionner

function liste(array) { alert(array[0].id); alert(array[0].url_data); }
Bon, voici un exemple pour comparer:

programme smarty : index.php
<?php

// put full path to Smarty.class.php
require('C:/wamp/bin/php/php5.2.6/Smarty/Smarty.class.php');
$smarty = new Smarty();

$smarty->template_dir = 'smarty/templates';
$smarty->compile_dir = 'smarty/templates_c';
$smarty->cache_dir = 'smarty/cache';
$smarty->config_dir = 'smarty/configs';

//

$test = array(
    0 => array(
            'id' => 81,
            'url_data' => '0.jpg'
        ),

    1 => array(
            'id' => 82,
            'url_data' => '1.jpg'
        ),

    2 => array(
            'id' => 83,
            'url_data' => '2.jpg'
        ),

    3 => array(
            'id' => 84,
            'url_data' => '3.jpg'
        )
);
//
$smarty->assign('test',json_encode($test)); 

//
$smarty->display('index.tpl');

?>
Le template smarty : index.tpl

Code : Tout sélectionner

<html> <head> <title>Smarty</title> {literal} <script type="text/javascript"> function liste(tableau) { var msg = ''; for(i=0; i<tableau.length; i++){ msg += 'id = ' + tableau[i].id + ' - url_data = ' + tableau[i].url_data + '\n'; } alert(msg); } </script> {/literal} </head> <body onload='liste({$test});'> Hello! </body> </html>

Posté : 03 oct. 2008, 23:07
par lux
Nickel ça marche. Merci beaucoup, je n'aurai pas trouvé tout seul.

Heureusement on a trouvé l'erreur sur les "", sinon on aurait encore cherché longtemps :P

Ça marche maintenant, un peu fastidieux, je mets donc en résolu. Un grand merci pour ta patience ! :wink:

Posté : 04 oct. 2008, 00:15
par sadeq
Attention: cette sérialisation avec json sert simplement dans les cas où l'on veut passer un tableau php à javascript. donc cette technique n'a rien à voir avec smarty.

Par contre, en sérialisant le tableau php par json_encode() dans une variable smarty il n'est plus considéré comme tableau php. Il est donc inexploitable par les fonctions smarty orientée tableau comme "foreach".

Voici donc un complément à l'exemple précédent qui illustre cette différence :
<?php

// put full path to Smarty.class.php
require('C:/wamp/bin/php/php5.2.6/Smarty/Smarty.class.php');
$smarty = new Smarty();

$smarty->template_dir = 'smarty/templates';
$smarty->compile_dir = 'smarty/templates_c';
$smarty->cache_dir = 'smarty/cache';
$smarty->config_dir = 'smarty/configs';

//

$test = array(
    0 => array(
            'id' => 81,
            'url_data' => '0.jpg'
        ),

    1 => array(
            'id' => 82,
            'url_data' => '1.jpg'
        ),

    2 => array(
            'id' => 83,
            'url_data' => '2.jpg'
        ),

    3 => array(
            'id' => 84,
            'url_data' => '3.jpg'
        )
);
//
$smarty->assign('test1',json_encode($test)); //pour sérialiser et passer le tableau à javascript
$smarty->assign('test2',$test); //le tableau reste au niveau smarty (php)

//
$smarty->display('index.tpl');

?>
Ici, on a créé 2 variables smarty:
  • 1. $test1 qui contient le code json du tableau php et qui est donc exportable à javascript en tant que tableau JS mais que smarty ne peut pas utiliser dans le template comme tableau php normal (car il ne l'est plus)
    2. $test2 qui contient directement le tableau au format php qu'on peut donc exploiter dans le template par les fonctions smarty comme un tableau php normal (car il n'est pas encodé par json)
Et voici le template :

Code : Tout sélectionner

<html> <head> <title>Smarty</title> {literal} <script type="text/javascript"> function liste(tableau) { var msg = ''; for(i=0; i<tableau.length; i++){ msg += 'id = ' + tableau[i].id + ' - url_data = ' + tableau[i].url_data + '\n'; } alert(msg); } </script> {/literal} </head> <body onload='liste({$test1});'> Hello! <p>Voici une liste par smarty : </p> <p><select id="liste"> <option></option> {foreach from=$test2 item=row} <option value="{$row.id}">{$row.url_data}</option> {/foreach} </select></p> </body> </html>
Ici, le tableau json $test1 est passé à une fonction javascript qui le considère comme un tableau JS.
Par contre, $test2 reste un tableau pur php/smarty il est donc exploité par la boucle smarty "foreach" pour construire les options d'une liste déroulante selon cet exemple.

Posté : 04 oct. 2008, 00:26
par lux
He bé, même tard dans la nuit, on à le droit à la rédaction d'un complément, respect. 8-)

Perso pour moi, j'avais compris la différence, mais c'est vrai que c'est bien de préciser, si un jour quelqu'un tombe sur ce topic, il aura toutes les explications nécessaires. Surtout que c'est subtil, y a même pas 4 heures je savais même pas que Json existait :P

Posté : 04 oct. 2008, 00:53
par sadeq
Merci, Lux et bonne nuit. :wink:

Posté : 04 oct. 2008, 00:57
par lux
Merci à toi surtout !

Bonne nuit ! :wink: