動的なJavaScript / CSSを生成するためのソリューション


15

現在のコンテキストに依存するjavascriptまたはCSSコードを生成する必要があるとしましょう。

たとえば、送信時にajaxリクエストを発行するフォームがホームページにあり、単一のページに別のフォームがあります。または、CSSの場合、ユーザーが独自のレイアウトを構築したり、色を変更したりできるテーマを作成する必要があります。

これまでに見たソリューション:

  1. ドキュメントのheadセクション(またはJSの場合は末尾)にコードを含めます

  2. site.com?get_assetsのようなコードを出力する特別なリクエストを行います。WPが2回ロードされるため、これは遅くなります。

  3. 一時ファイルに一定時間保存し、そこからロードします。公開テーマまたはプラグインについてはあまり信頼できません。

  4. Javascriptのみ-毎回ロードされる通常のファイルに入れて、静的にします。この場合、コードにあらゆる状況を処理させる必要があります。

他の人を知っていますか?どちらに行きますか?


ソリューション1で発生した問題の1つは、ブラウザによるキャッシュです。ページの再読み込み時にコードが更新されません。
-Aurovrata

回答:


9

渡す必要のあるパラメーターの種類に応じて、1つの追加オプション。これを呼び出しましょう(2a)。また、動的に生成されるtext/cssまたはtext/javascriptではなく、を出力するPHPスクリプトを作成text/htmlし、WordPressをロードするのではなく、GETパラメーターを使用して必要なデータを提供することもできます。もちろん、これは、比較的少数の比較的コンパクトなパラメーターを渡す必要がある場合にのみ機能します。したがって、たとえば、投稿のURLまたはファイルまたは類似のディレクトリのみを渡す必要がある場合、次のようなことができます。

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>

fancy-js.phpで:

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

ただし、これにより、GETパラメーターで直接渡されたデータにのみアクセスできます。渡す必要のあるものの数が比較的少なく、それらの表現が比較的コンパクトな場合にのみ機能します。(基本的に一握りの文字列または数値-ユーザー名、ユーザー名、またはディレクトリ。ユーザーの最近の投稿すべてなどのリストではありません。)

これらのオプションのどれが最適かについてはわかりません。それはユースケースに依存します。オプション(1)にはシンプルであるというメリットがあり、WordPressを2回ロードすることによるパフォーマンスの低下を招くことなく、明らかに必要なWordPressデータへのアクセスを許可します。使用する必要のない強力な理由がない限り(スタイルシートやスクリプトのサイズが原因など)、ほとんど間違いなくあなたがすべきことです。

サイズが1ページの重量の点で問題を引き起こすほど大きくなった場合は、(2)または(2a)を試すことができます。

または、これはおそらくより良いアイデアです-静的に指定できる部分から動的データを実際に使用するスクリプトまたはスタイルシートの部分を分離しようとすることができます。#my-fancy要素の背景パラメータを設定するために、WordPressからディレクトリを渡す必要があるスタイルシートがあるとします。これらすべてを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>

しかし、なぜそうする必要があるのでしょうか?ここには、WordPressのデータに依存する1行しかありません。WordPressに依存する行のみを分割することをお勧めします。

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

標準のリンク要素(style.cssなど)を使用してロードする静的スタイルシートに他のすべてを配置します。

 #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 ... */

そして、カスケードに仕事をさせてください。

JavaScriptについても同じことが言えます:これを行うのではなく:

 <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>

代わりに、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>

そして、残りを静的JavaScriptファイルにドロップし、my_huge_function()およびmy_other_function()を書き換えて、グローバルWordPressPostData.urlおよびWordPressPostData.authorを使用します。

40KのCSSまたは40KのJSは、ほとんど常に動的データに実際に依存する<1Kに分割でき、残りは静的外部ファイルで指定し、カスケード(CSSの場合)またはグローバルにアクセス可能ないずれかを使用して再結合できます変数(JS、グローバル、DOM要素、または他の任意のキュービックホール)。


素晴らしい答えです!
スクライブ

2
ほんの少しの追加:JSの場合、wp_localize_sciprtを使用して動的変数を追加できます。
アントラン

6

動的なCSSのケースはかなり単純です。

<style type="text/css"></style>タグ内で動的なCSS定義を出力する関数を作成し、その関数をにフックするだけwp_print_stylesです。例えば

<?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' );
?>

または、事前に設定されたカラースキームがあるとします。現在のユーザー設定に従って、適切なスタイルシートをキューに入れることができます。

<?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' );
?>

この場合、wp_enqueue_scriptsWordPressにはwp_enqueue_stylesアクションフックがないため、関数はにフックすることに注意してください。


1
1)と同じ。これは私が今やっていることですが、40KのCSSがあれば、かさばるhtmlドキュメントが得られます
onetrickpony

1
しかし、これらの40KのCSSはどこかに出力する必要がありますよね?そして、間違いなく#1と同じですが、WordPressで動的CSSを注入する正しい方法です。:)
チップベネット

2

私はしばらくそれを考えていました。あなたの質問に私はそれに戻ります。良いアイデアかどうかわからないので、専門家のコメントをお願いします。

どのような場合私は、PHP経由でのjavascript / cssファイルを書き込み、管理データを保存するとき。ユーザーがレイアウトを再度変更するまで、1回の書き込みになります(ユーザーはあまり頻繁に変更しないことがあります)。この方法では、ユーザーがデータを保存するときに、ユーザー設定のためにデータベースに1回だけアクセスします。

ファイルを書き込んだ後は、通常のjavascript / cssファイルになりますので、テーマがロードされるたびにデータベースを呼び出す必要はありません。

回答が必要な質問:訪問者がphpがファイルを書き込む瞬間にサイトにアクセスしようとするとどうなりますか?

どう考えているか教えてください。


これらのファイルをwp-content/uploads(WPコードから書き込み可能なことが保証されている唯一のディレクトリ)で生成する場合、実行可能なアプローチになる可能性があります。WP Coreでさえ、この手法を1つのjsファイルに使用していると思います。
スクライブ

欠点は、動的ではないことです。つまり、すべてのページのすべてのユーザーで同じです。バリエーションごとに、新しいファイルを生成する必要があります。あなたが言ったように、それはまだテーマ/プラグインオプションのための良いアプローチです。
スクライブ

@scribu:はい、本当です。それは次のようなものの混乱になる可能性があります。ユーザーにカスタマイズされたプロファイルページを提供し、各ユーザーにファイルを書き込む必要がある場合。しかし、それは、我々は視覚的なウェブサイトメーカー(ドラッグ&ドロップ)を行う場合は、ユーザーが色を変更し、様々な効果(この質問のような)などを追加...とWPMUと組み合わせることができる場所のようなもののために良いアプローチかもしれません。)
Sisir

1

たとえば、動的に生成されるため、別のファイルに含めたくない小さなスクリプトの場合は、WordPress 4.5以降で提供されますwp_add_inline_script。この関数は、基本的にスクリプトを別のスクリプトにラッチします。たとえば、テーマを開発していて、顧客がオプションページから独自のスクリプト(Google AnalyticsやAddThisなど)を挿入できるようにしたいとします。

スタイルについてはwp_add_inline_style、基本的に同じように機能します。たとえば、それを使用して、すべてのカスタマイザmodをループし、それらをストリングという名前$all_modsで収集して、メインスタイルシートに次のように追加します。

if (!empty($all_mods)) wp_add_inline_style ('main-style', $all_mods);

-2

動的なJS.phpファイルを作成し、重要なquery_varsをフィードします。これらの変数は$_GET、ファイルがコンテキストを決定するのに役立ち、その中でキャッシュしreadfile()て将来のリクエストに使用できます...何でもできます。

ファイルがwp-load.php他のものより先にロードされることを確認してください。そうすれば、WP関数にアクセスできます。現在のフォルダーへの相対パスを使用する(dirname(__FILE__))か、フォルダー構造内で下向きに移動してwp-load.php、プラグインの配置に関係なく検索します。

どこからでもwp-load.phpを探すコード

// 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

乾杯、スクリブ!

PS:フォルダが通常のWPデクリメンタル構造に従っていない複雑な構造の場合、親プラグインは直接アクセス可能なファイルと情報を共有できます。CSS / JSファイルに書き込むことができますレンダリングする動的なPHPファイルが付属して親プラグインrealpath()wp-load.phpスタンドアロンファイルがそれを使用することができます。これは、WPユーザーの0.1%にとって問題になります。フォルダを移動し、通常の構造に従っていない人は、自分が何をしているかを知っており、おそらくwp-load.php直接ロードする必要のあるPIMPプラグインを知っていると思います。


可愛い!嫌い、説明を追加してください。私を啓発します。ありがとう;)xoxo
EarnestoDev

wp-load.phpテーマやプラグインファイルからインクルードするのは悪い習慣です。これは、wp-contentおよび/またはplugins ディレクトリがルートWPディレクトリに関連する任意の場所にある可能性があるためです。WP_CONTENT_DIRとWP_PLUGINS_DIRを覚えておいてください。
スクライブ

1
@scribuまた、スタンドアロンファイルは親プラグインと共同作業できます。親プラグインは、それが置かれているフォルダーにwp-load.phpを保存でき、動的jsジェネレーターはそこからそれを読み取ることができます。シンプル
...-EarnestoDev

1
はい、親プラグインアプローチが機能します。あなたの答えにそれを書き留めてください、そして、私は私の下票を取り除きます。PS:このサイトは英語です。ルーマニア語で発言を続けると問題が発生する可能性があります。
スクライブ

5
態度をカットします。手動のコアロードは実行可能な手法ですが、ほとんどの場合、最初の適切な選択にはほど遠い状態です。あなたがそれを機能させることができることを誰も疑いません。投票は、あなたの脳ではなく、あなたの答えの質に関するものです。
ラースト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.