Déclaration et accès variable globale

Bonjour,

J’ai beaucoup de mal avec le langage de spip, je n’arrive pas à me faire à la « logique » syntaxique et structurelle de ce système.
Donc j’ai un problème pour récupérer un variable globale, voici le contexte :

J’ai besoin de récupérer dans une bdd externe des rôles spécifiques pour les utilisateurs enregistrés.
J’ai créé dans mes_options une balise dynamique #USER_INFO. Dans cette balise j’initialise un tableau avec les différents rôles des utilisateurs qui est placé dans une variable globale (ok en sortie de routine). La balise en elle-même ne renvoie que le statut de la récupération. Je récupère bien ce statut en plaçant la balise dans une page, mais pas moyen de récupérer les données du tableau.
Dans la routine de la balise j’ai essayé de déclarer le tableau avec :

$GLOBALS['userinfo'][…]
$_SESSION['userinfo'][…]
$GLOBALS['visiteur_session']['userinfo'][…]  

Pour récupérer les données j’ai essayé selon le cas avec les codes suivants :

<span style='display: none;'>
   get_user_info: #USER_INFO   ← recup ok
   data: [(#GET{$GLOBALS[userinfo]}|table_valeur{item})]   ← selon déclaration
   data: [(#GET{#SESSION{userinfo}}|table_valeur{item})]   ← selon déclaration
</span>

Est-ce que la syntaxe du #GET est incorrecte ?
Faut-il déclarer la variable globale quelque part avant de l’utiliser dans mes_options ?
Est-ce qu’il existe un moyen plus simple pour déclarer une variable global et l’utiliser dans un squelette / une page ?

Autre souci avec ma balise, dans la déclaration de la balise statique, si j’utilise un tableau vide comme suggéré dans certains exemples, pour l’appel de la balise dynamique :

return calculer_balise_dynamique($p, 'USER_INFO', array());

Je récupère cette erreur :

get_user_info: 
Fatal error: Uncaught ArgumentCountError: Too few arguments to function balise_USER_INFO_dyn(),
0 passed in /volume1/web/istresrando.fr_/spip/ecrire/public/evaluer_page.php(51) : 
eval()'d code on line 6 and exactly 1 expected in /volume1/web/istresrando.fr_/spip/config/mes_options.php on line 33

Pour l’instant, j’ai contourné le problème en passant un tableau de paramètres bidons…

Merci d’avance pour tout aide, cordialement.

TG

Alors déjà les variables globales c’est le mal. :stuck_out_tongue:

Ensuite #GET ne sert QUE à récupérer des variables définies par #SET avant. Sinon il faut faire plutôt #EVAL :
https://www.spip.net/fr_article4587.html

Mais surtout je pense qu’il faut comprendre comment marche le langage de template, car à mon avis l’ordre de tes appels n’est jamais le bon. Le principe du langage c’est que c’est pas PHP justement, il est compilé pour être mis en double cache.
Template => compilé en PHP dynamique (var_mode=recalcul)
PHP compilé => compilé en HTML (var_mode=calcul)

Si tu as une balise dynamique, alors le « travail » qu’elle fait, n’est PAS fait au moment de la compilation, mais c’est bien son PHP final qui est appelé à la toute fin en permanence (comme les formulaires, qui doivent toujours être à jour).

Or ensuite dans ton GET (qui n’est pas bon de toute façon, mais si c’était #EVAL pareil), tu tentes d’y récupérer une valeur à la compilation, donc forcément à ce moment là, le PHP de ta balise dynamique n’a encore jamais exécuté, peu importe que ta récup soit dans des lignes après.

Enfin, comme tu travailles spécifiquement pour des utilisateurs, je pense que tu devrais plutôt utiliser les API qui existe au lieu d’une globale :

  • include_spip(‹ inc/session ›)
  • session_set(‹ tesinfos ›, valeurs)
  • dans les templates, tu peux alors
    • soit utiliser #SESSION #SESSION - SPIP mais attention : cela va créer un cache spécifique à chaque utilisateur pour ce template
    • soit (et c’est en gros le seul cas qui le justifie), mettre du PHP dans le template, pour qu’il soit exécuté qu’à la toute fin : <?php if (session_get('tesinfos')) { ?> etc <?php } ?>


RastaPopoulos

Bon, je croyais avoir tout compris avec avec ces belles explications exhaustives, mais … non !
C’est un peu ça, qui me hérisse avec Spip, c’est que même quand on pense avoir avancé un peu et bien on s’aperçoit qu’on est toujours dans le mur … :wink:
Donc j’ai modifié le code de la balise comme suit :

include_spip('inc/session');
$userinfo = array();
../.. (initialisation des items du tableau)
session_set('userinfo', $userinfo);

Pour la récupération, j’ai essayé tout ce qui me passait par l’esprit … nada :

 <span style="display: none;">
    get_user_info: #USER_INFO isadmin: 
    <?php 
       include_spip('inc/session');
       if ($userinfo = session_get('userinfo'))
          echo $userinfo['admin']; 
    ?>
    <br>
    <?=$GLOBALS['visiteur_session']['userinfo']['admin'] ?>
    <br>
    #EVAL{$GLOBALS['visiteur_session']['userinfo']['admin']}
    <br>
    #SET{userinfo,#SESSION{userinfo}}
    [(#GET{userinfo}|table_valeur{admin})]
    <br>
    [(#SESSION{userinfo}|table_valeur{admin})]
    <br>
 </span>

Dans le fichier du cache, on a ça :

$page = (
'
' .
vide($Pile['vars'][$_zzz=(string)'userinfo'] = interdire_scripts(invalideur_session($Cache, table_valeur($GLOBALS["visiteur_session"], (string)'userinfo', null)))) .
'<span style="display: none;">
	get_user_info: ' .
executer_balise_dynamique('USER_INFO',
	array(@$Pile[0][''],@$Pile[0]['']),
	array('squelettes/header/dist.html','html_081ee3389d73583cdae4ab3e010f8112','',3,$GLOBALS['spip_lang'])) .
' isadmin:
	<?php
		include_spip(\'inc/session\');
		if ($userinfo = session_get(\'userinfo\'))
	 		echo $userinfo[\'admin\'];
	?>
	<br>
	<?=$GLOBALS[\'visiteur_session\'][\'userinfo\'][\'admin\'] ?>
	<br>
	' .
interdire_scripts(eval('return '.'$GLOBALS[\'visiteur_session\'][\'userinfo\'][\'admin\']'.';')) .
'<br>
	' .
vide($Pile['vars'][$_zzz=(string)'userinfo'] = interdire_scripts(invalideur_session($Cache, table_valeur($GLOBALS["visiteur_session"], (string)'userinfo', null)))) .
table_valeur(table_valeur($Pile["vars"], (string)'userinfo', null),'admin') .
'
	<br>
	' .
interdire_scripts(invalideur_session($Cache, table_valeur(table_valeur($GLOBALS["visiteur_session"], (string)'userinfo', null),'admin'))) .
'
	<br>
</span>
'

J’ai mis un point d’arrêt dans le fichier du cache et dans le fichier mes_options, et j’appelle la page sans l’option var_mode=calcul/recalcul.
Au point d’arrêt du code de la page du cache la variable $GLOBALS[‹ visiteur_session ›] contient bien le tableau [‹ userinfo ›] avec tous les items renseignés, pourtant rien n’est affiché :frowning:

J’ai encore besoin des lumières d’un expert !

TG

Est-ce que tu as lu : SPIP, PHP et Javascript sont dans un bateau - SPIP-Contrib ?

Bon, j’ai compris le problème, ce matin j’affiche le site (sans avoir rien modifié depuis hier) et je me connecte avec un compte admin et miracle tout fonctionne. Je me reconnecte avec un compte non admin et … rien ne s’affiche ! Donc mon code est bon, mais spip affiche les valeurs ‹ true › en ‹ 1 › et les valeurs ‹ false › en … rien. Je m’attendais à voir des ‹ 0 ›, voilà ce qui m’a induit en erreur !
Du coup comme les 5 différentes syntaxes utilisées fonctionnent, et sachant que le php et la balise #SESSION sont déconseillés, la syntaxe suivante est-elle bien la plus pertinente ?

#EVAL{$GLOBALS['visiteur_session']['userinfo']['admin']}

ou est-ce que cela ne change rien en terme d’optimisation du cache par rapport à l’utilisation de #SESSION ?
Ou comme conseillé dans l’article Du php dans le squelette à la place de #SESSION ou #CACHE 0 vaut-il mieux utiliser le php ?
Si j’utilise l’API session_get(), faut-il systématiquement ajouter include_spip(‹ inc/session ›) dans le squelette ? ou le fait d’avoir déjà fait l’include dans le fichier mes_options suffit-il ?

Merci d’avance pour ces petites précisions.

TG

Le 28/08/2021 à 11:20, geth44 via Discuter de SPIP a écrit :

et sachant que le php et la balise #SESSION sont déconseillés, la syntaxe suivante est-elle bien la plus pertinente ?
|#EVAL{$GLOBALS[‹ visiteur_session ›][‹ userinfo ›][‹ admin ›]} |

Où as-tu vu ça ? C’est le contraire : c’est bien #SESSION (si squelette autonome circonscrit) ou du PHP exceptionnel dans le squelette, qui sont le plus propre à priori, pas un #EVAL.

Si j’utilise l’API session_get(), faut-il systématiquement ajouter include_spip(‹ inc/session ›) dans le squelette ? ou le fait d’avoir déjà fait l’include dans le fichier mes_options suffit-il ?

C’est inclus en permanence à la racine (pas dans une fonction) ? Moi je préfère toujours inclure les bons fichiers à l’endroit où on l’utilise, pour être certain d’avoir accès tant qu’on utilise pas les loaders automatiques.


RastaPopoulos

Où as-tu vu ça ? C’est le contraire : c’est bien #SESSION (si squelette autonome circonscrit) ou du PHP exceptionnel dans le squelette, qui sont le plus propre à priori, pas un #EVAL.

Ben justement dans l’article Du php dans le squelette à la place de #SESSION ou #CACHE 0 :

…/…
Utiliser les balises #SESSION ou #AUTORISER à bon escient car ces balises créent un cache par utilisateur logué (et un autre pour tous les utilisateurs non logués). Le cache pour un utilisateur d’un squelette qui utilise une de ces balises ne bénéficie donc pas à un autre utilisateur et il faut 1) recalculer le cache pour chaque utilisateur (consommation CPU) et 2) stocker d’innombrables versions du cache (consommation d’espace disque).
…/…

Voici bien un exemple de l’aide parfois contre-intuitive de spip …
Et aussi d’un vocabulaire très spipien complètement abscont pour un néophyte :

(si squelette autonome circonscrit)

Là je suis encore plus largué qu’avant …
pourrais-tu stp, développer en des termes compréhensibles pour un non-initié :wink:. Merci d’avance.

Cordialement

TG

Le 29/08/2021 à 12:07, geth44 via Discuter de SPIP a écrit :

Et aussi d’un vocabulaire très spipien complètement abscont pour un néophyte :

(si squelette autonome circonscrit)

Là je suis encore plus largué qu’avant …

circonscrit n’a rien de propre à SPIP… un template propre à un morceau précis de ta page quoi

si tu mets une balise #SESSION dans un gros squelette complet qui génère tout ta page (dans un article.html à la racine par ex), alors c’est la page entière qui va avoir un cache par utilisateur

si en revanche tu utilises #SESSION uniquement dans une petite inclusion propre à un besoin précis dans les pages (afficher des infos dédiées à l’utilisateur uniquement dans un petit bloc précis des pages par ex), et bien le cache propre à chaque utilisateur sera circonscrit seulement à ce morceau (s’il est bien inclus avec <INCLURE>)

mais sinon du PHP marche très bien quand c’est pour afficher des choses simples en rapport avec la session de la personne (afficher son nom, ou son statut par ex), ou tester et n’afficher que dans un certain cas (n’afficher tel morceau que si la personne est une admin par ex). Mais faut pas avoir à faire des choses complexes comme utiliser l’id de l’utilisateur ou tout autre de ses infos dans un critère de boucle par ex, dans ce cas il est obligatoire d’utiliser #SESSION puisque c’est pour utiliser une valeur session dans le langage de template, et non à la toute fin dans le PHP compilé


RastaPopoulos