Des solutions pour générer du javascript / CSS dynamique

13

Supposons que vous deviez générer du code javascript ou CSS qui dépend du contexte actuel.

Par exemple, vous avez un formulaire sur la page d'accueil qui déclenche une demande ajax lors de l'envoi, et un formulaire différent sur la page unique. Ou, dans le cas de CSS, vous voulez créer un thème qui permette à ses utilisateurs de créer leur propre mise en page, de changer de couleur, etc.

Les solutions que je vois jusqu'à présent:

  1. Incluez le code dans la section d'en-tête du document (ou à la fin dans le cas de JS)

  2. Faites une demande spéciale qui génère le code, comme site.com?get_assets . Ceci est lent car WP est chargé deux fois.

  3. Stockez-le dans des fichiers temporaires pendant un certain temps et chargez-le à partir de là. Pas très fiable pour les thèmes publics ou les plugins.

  4. Javascript uniquement - rendez-le statique en le plaçant dans un fichier normal chargé à chaque fois. Dans ce cas, vous devrez obliger votre code à gérer n'importe quelle situation.

Connaissez-vous les autres? Où iriez-vous?

    
posée onetrickpony 29.10.2011 - 16:56

5 réponses

8

Une option supplémentaire, en fonction du type de paramètres à transmettre. Appelons-le (2a). Vous pouvez également créer des scripts PHP générant dynamiquement text/css ou text/javascript plutôt que text/html , et leur fournir les données dont ils ont besoin à l'aide de paramètres GET plutôt que de charger WordPress. Bien entendu, cela ne fonctionne que si vous devez transmettre un nombre relativement petit de paramètres relativement compacts. Ainsi, par exemple, supposons que vous n’ayez besoin de transmettre que l’URL d’une publication ou le répertoire d’un fichier ou un fichier similaire, vous pouvez procéder de la manière suivante:

Dans header.php:

 <script type="text/javascript" src="<?php print get_stylesheet_directory_uri(); 
 ?>/fancy-js.php?foo=bar&amp;url=<?php print urlencode(get_permalink($post->ID)); ?>"></script>

Dans fancy-js.php:

 <?php
 header("Content-type: text/javascript");
 ?>
 foo = <?php print json_encode($_GET['foo']); ?>;
 url = <?php print json_encode($_GET['url']); ?>;

etc.

Mais cela ne vous permet que d'accéder aux données directement passées dans les paramètres GET; et cela ne fonctionnera que si le nombre d'éléments à transmettre est relativement petit et si la représentation de ces éléments est relativement compacte. (En gros, une poignée de valeurs de chaîne ou numériques - un nom d'utilisateur, par exemple, ou un répertoire; pas une liste de toutes les publications récentes d'un utilisateur ou quelque chose comme ça.)

En ce qui concerne laquelle de ces options est la meilleure - je ne sais pas; cela dépend de votre cas d'utilisation. L’option (1) a le mérite d’être simple et de vous permettre clairement d’accéder à toutes les données WordPress dont vous pourriez avoir besoin, sans avoir à charger deux fois WordPress. C’est presque certainement ce que vous devriez faire sauf si vous avez une raison strong de ne pas le faire (par exemple, en raison de la taille de la feuille de style ou du script que vous devez utiliser).

Si la taille devient suffisamment grande pour poser un problème de poids d'une page, vous pouvez essayer (2) ou (2a).

Sinon - c’est probablement la meilleure idée - vous pouvez essayer de séparer les parties du script ou de la feuille de style qui utilisent réellement les données dynamiques des parties pouvant être spécifiées de manière statique. Ssay, vous avez une feuille de style qui doit recevoir un répertoire de WordPress afin de définir un paramètre d’arrière-plan pour l’élément # my-fancy. Vous pouvez mettre tout cela dans l'élément head:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */
 </style>

Mais pourquoi auriez-vous besoin de faire ça? Il n'y a qu'une seule ligne ici qui dépend des données de WordPress. Mieux vaut ne séparer que les lignes qui dépendent de WordPress:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
 }
 </style>

Placez tout le reste dans une feuille de style statique que vous chargez avec un élément de lien standard (style.css ou autre):

 #my-fancy-element {
      /* background-image provided dynamically */
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */

Et laissez la cascade faire le travail.

Même chose pour JavaScript: plutôt que de faire ceci:

 <script type="text/javascript">
 // Here comes a huge function that uses WordPress data:
 function my_huge_function () {
     // Do a million things ...

     jQuery('#my-fancy').append('<a href="'+<?php json_encode(get_permalink($GLOBALS['post']->ID)); ?>+'">foo</a>);

     // Do a million more things ...

     my_other_function(<?php print json_encode(get_userdata($GLOBALS['post']->post_author); ?>);
 }

 function my_other_function (user) {
     // Do a million things ...
 }
 </script>

Placez plutôt quelque chose comme ceci dans l'élément head:

 <script type="text/javascript">
 var WordPressPostData = {
 url: <?php print json_encode(get_permalink($GLOBALS['post']->ID)); ?>,
 author: <?php print json_encode(get_userdata($GLOBALS['post']->post_author)); ?>
 }
 </script>

Ensuite, déposez le reste dans un fichier JavaScript statique en réécrivant my_huge_function () et my_other_function () pour utiliser les fonctions globales WordPressPostData.url et WordPressPostData.author.

40K de CSS ou 40K de JS peuvent presque toujours être divisés en < 1K qui dépendent en fait de données dynamiques, et le reste, qui peut être spécifié dans un fichier externe statique, puis recombiné à l'aide de la cascade (pour CSS) ou des variables globalement accessibles (globals, éléments DOM ou tout autre cube de votre choix pour JS).

    
réponse donnée radgeek 30.10.2011 - 16:05
5

Le cas CSS dynamique est assez simple.

Créez simplement une fonction qui affiche les définitions CSS dynamiques à l'intérieur des balises <style type="text/css"></style> , puis raccordez cette fonction à wp_print_styles . par exemple

<?php
function mytheme_dynamic_css() {
    $options = get_option( 'mytheme_options' );
    ?>
    <style type="text/css">
    /* Dynamic H1 font family */
    h1 { font-family: <?php echo $options['h1_font_family']; ?>;
    </style>
    <?php
}
add_action( 'wp_print_styles', 'mytheme_dynamic_css' );
?>

Ou, supposons que vous ayez des schémas de couleurs préconfigurés; vous pouvez mettre en file d'attente la feuille de style appropriée en fonction du paramètre utilisateur actuel:

<?php
function mytheme_enqueue_colorscheme_stylesheet() {
    $options = get_option( 'mytheme_options' );
    $color_scheme = $options['color_scheme'];
    wp_enqueue_style( $colorscheme, get_template_directory_uri() . '/css/' . $color_scheme . '.css' );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_colorscheme_stylesheet' );
?>

Notez que, dans ce cas, la fonction s'accroche à wp_enqueue_scripts , étant donné que WordPress n'a pas de crochet d'action wp_enqueue_styles .

    
réponse donnée Chip Bennett 29.10.2011 - 18:44
2

J'y pensais depuis un moment. Votre question me fait y revenir. Je ne suis pas sûr que ce soit une bonne idée ou non. Je souhaiterais donc que les experts nous commentent.

Et si je rédige le fichier javascript / css via php lors de la sauvegarde des données par l'administrateur. Ce sera une écriture unique jusqu'à ce que l'utilisateur modifie à nouveau la présentation (ce que l'utilisateur ne peut pas faire trop souvent). De cette manière, nous n’accédons à la base de données pour les paramètres utilisateur qu’une seule fois lors de la sauvegarde des données.

Après avoir écrit le fichier, il s'agira d'un fichier javascript / css standard, ce qui évite d'appeler la base de données à chaque chargement du thème.

Il faut répondre à une question: Que se passera-t-il lorsqu'un visiteur tente d'accéder au site à l'instant où php écrit le fichier?

Faites-moi savoir ce que vous pensez.

    
réponse donnée Sisir 31.10.2011 - 12:27
1

Pour les petits morceaux de script, que vous ne souhaitez peut-être pas inclure dans un fichier séparé, par exemple parce qu'ils sont générés de manière dynamique, WordPress 4.5 et d'autres offres wp_add_inline_script . Cette fonction verrouille le script sur un autre script. Supposons, par exemple, que vous développiez un thème et que vous souhaitiez que votre client puisse insérer ses propres scripts (tels que Google Analytics ou AddThis) via la page des options. Exemple .

Pour les styles, il existe wp_add_inline_style le même principe. Vous l'utiliserez, par exemple, pour parcourir tous vos mods de personnalisation et les rassembler dans une chaîne appelée $all_mods , que vous ajouteriez ensuite à votre feuille de style principale:

if (!empty($all_mods)) wp_add_inline_style ('main-style', $all_mods);
    
réponse donnée cjbj 31.10.2016 - 10:09
-2

Créez un fichier JS.php dynamique et envoyez-lui d'importants query_vars. Ces variables dans $_GET aideront le fichier à déterminer le contexte. Dans ce fichier, vous pouvez mettre en cache et utiliser readfile() pour les requêtes futures. ... fais n'importe quoi.

Assurez-vous simplement que ce fichier charge le wp-load.php avant toute autre chose, afin que vous ayez accès aux fonctions WP. Utilisez le chemin relatif vers le dossier actuel (dirname(__FILE__)) ou tout simplement en descendant dans la structure du dossier pour localiser wp-load.php quel que soit l'emplacement du plug-in.

Code pour rechercher wp-load.php à partir de n’importe où

// Ensure single declaration of function!
if(!function_exists('wp_locate_loader')):
    /**
     * Locates wp-load.php looking backwards on the directory structure.
     * It start from this file's folder.
     * Returns NULL on failure or wp-load.php path if found.
     * 
     * @author EarnestoDev
     * @return string|null
     */
    function wp_locate_loader(){
        $increments = preg_split('~[\\/]+~', dirname(__FILE__));
        $increments_paths = array();
        foreach($increments as $increments_offset => $increments_slice){
            $increments_chunk = array_slice($increments, 0, $increments_offset + 1);
            $increments_paths[] = implode(DIRECTORY_SEPARATOR, $increments_chunk);
        }
        $increments_paths = array_reverse($increments_paths);
        foreach($increments_paths as $increments_path){
            if(is_file($wp_load = $increments_path.DIRECTORY_SEPARATOR.'wp-load.php')){
                return $wp_load;
            }
        }
        return null;
    }
endif;
// Now try to load wp-load.php and pull it in
$mt = microtime(true);
if(!is_file($wp_loader = wp_locate_loader())){
    header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
    header("Status: 403 Forbidden");
    echo 'Access denied!'; // Or whatever
    die;
}
require_once($wp_loader); // Pull it in
unset($wp_loader); // Cleanup variables

Salut, Scribu!

PS : pour les structures complexes où les dossiers ne suivent pas la structure décrémentielle normale de WP, les plug-ins parents peuvent partager des informations avec des fichiers directement accessibles. Un plugin parent fourni avec un fichier PHP dynamique qui rend CSS / JS peut écrire dans un fichier le realpath() du wp-load.php et le fichier autonome peut l'utiliser. Ce serait un problème pour 0,1% des utilisateurs de WP. Je pense que ceux qui déplacent des dossiers et ne suivent pas la structure normale savent ce qu’ils font et peuvent probablement utiliser des plugins PIMP qui doivent charger wp-load.php directement.

    
réponse donnée EarnestoDev 29.10.2011 - 17:51

Lire d'autres questions sur les étiquettes