Solusi untuk menghasilkan javascript / CSS dinamis

15

Katakanlah Anda perlu membuat kode javascript atau CSS yang tergantung pada konteks saat ini.

Misalnya Anda memiliki formulir di beranda yang mengirimkan permintaan ajax saat mengirim, dan formulir lain di satu halaman. Atau dalam hal CSS, Anda ingin membuat tema yang memungkinkan penggunanya untuk membangun tata letak mereka sendiri, mengubah warna dll.

Solusi yang saya lihat sejauh ini:

  1. Sertakan kode di bagian kepala dokumen (atau di akhir dalam kasus JS)

  2. Lakukan permintaan khusus yang menampilkan kode, seperti site.com?get_assets . Ini lambat karena WP dimuat dua kali.

  3. Simpan dalam file sementara untuk jangka waktu tertentu, dan muat dari sana. Tidak terlalu andal untuk tema atau plugin publik.

  4. Hanya Javascript - membuatnya statis dengan memasukkannya ke dalam file normal yang dimuat setiap waktu. Dalam hal ini Anda harus membuat kode Anda menangani situasi apa pun

Apakah kamu kenal orang lain? Kemana Anda akan pergi?

onetrickpony
sumber
satu masalah yang saya temui dengan solusi 1 adalah caching oleh browser, kode tidak bisa di-refresh pada halaman yang dimuat ulang.
Aurovrata

Jawaban:

9

Satu opsi tambahan, tergantung pada jenis parameter yang perlu Anda lewati. Sebut saja (2a). Anda juga dapat membuat skrip PHP yang menghasilkan text/cssatau menghasilkan secara dinamistext/javascript bukan text/html, dan memberikan mereka data yang mereka butuhkan menggunakan parameter GET bukan oleh loading WordPress. Tentu saja ini hanya berfungsi jika Anda perlu memasukkan sejumlah kecil parameter yang relatif kompak. Jadi, misalnya, Anda hanya perlu memasukkan URL kiriman atau direktori file atau sejenisnya, Anda dapat melakukan sesuatu seperti ini:

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

Dalam fancy-js.php:

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

dll.

Tetapi ini hanya memungkinkan Anda mengakses data yang secara langsung diteruskan dalam parameter GET; dan itu hanya akan berfungsi jika jumlah hal yang perlu Anda lewati relatif kecil, dan representasi dari hal-hal itu relatif kompak. (Pada dasarnya beberapa string atau nilai numerik - nama pengguna, katakanlah, atau direktori; bukan daftar semua posting terbaru pengguna atau sesuatu seperti itu.)

Adapun yang salah satu dari opsi ini adalah yang terbaik - saya tidak tahu; itu tergantung pada kasus penggunaan Anda. Opsi (1) memiliki kelebihan yaitu sederhana, dan jelas memungkinkan Anda mengakses data WordPress apa pun yang mungkin Anda perlukan, tanpa kinerja menekan memuat WordPress dua kali. Ini hampir pasti apa yang harus Anda lakukan kecuali Anda memiliki alasan kuat untuk tidak melakukannya (misalnya karena ukuran stylesheet atau skrip yang perlu Anda gunakan).

Jika ukurannya menjadi cukup besar untuk menyebabkan masalah dalam hal berat satu halaman Anda, maka Anda dapat mencoba (2) atau (2a).

Atau yang lain - ini mungkin ide yang lebih baik - Anda dapat mencoba memisahkan bagian-bagian dari skrip atau stylesheet yang benar-benar memanfaatkan data dinamis dari bagian-bagian yang dapat ditentukan secara statis. Katakanlah Anda memiliki stylesheet yang perlu melewati direktori dari WordPress untuk menetapkan parameter latar belakang untuk elemen # my-fancy. Anda bisa memasukkan semua ini ke elemen kepala:

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

Tetapi mengapa Anda perlu melakukan itu? Hanya ada satu baris di sini yang bergantung pada data dari WordPress. Lebih baik membagi hanya garis-garis yang bergantung pada WordPress:

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

Tempatkan semua yang lain di stylesheet statis yang Anda muat dengan elemen tautan standar (style.css atau apa pun):

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

Dan biarkan kaskade melakukan pekerjaan.

Hal yang sama berlaku untuk JavaScript: daripada melakukan ini:

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

Alih-alih meletakkan sesuatu seperti ini di elemen kepala:

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

Dan kemudian masukkan sisanya ke file JavaScript statis, menulis ulang my_huge_function () dan my_other_function () untuk memanfaatkan global WordPressPostData.url dan WordPressPostData.author.

40K CSS atau 40K JS hampir selalu dapat dibagi menjadi <1K yang sebenarnya tergantung pada data dinamis, dan sisanya, yang dapat ditentukan dalam file eksternal statis dan kemudian dikombinasi ulang menggunakan kaskade (untuk CSS) atau dapat diakses secara global variabel (global, elemen DOM, atau lubang cubby apa pun yang Anda inginkan, untuk JS).

radgeek
sumber
Jawaban yang brilian!
scribu
2
Hanya tambahan kecil: dalam kasus JS, kita dapat menggunakan wp_localize_sciprt untuk menambahkan variabel dinamis.
Anh Tran
6

Kasing CSS dinamis cukup sederhana.

Cukup buat fungsi yang menampilkan definisi CSS dinamis di dalam <style type="text/css"></style>tag, lalu kaitkan fungsi itu wp_print_styles. misalnya

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

Atau, katakanlah Anda memiliki skema warna yang sudah dikonfigurasi sebelumnya; Anda dapat menentukan lembar gaya yang sesuai sesuai dengan pengaturan pengguna saat ini:

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

Perhatikan bahwa, dalam hal ini, fungsi kait ke wp_enqueue_scripts, karena WordPress tidak memiliki wp_enqueue_styleskait tindakan.

Chip Bennett
sumber
1
sama dengan 1). Inilah yang saya lakukan sekarang, tetapi jika Anda memiliki 40K CSS, Anda akan mendapatkan dokumen html besar
onetrickpony
1
Tetapi 40K CSS itu harus berupa output di suatu tempat , bukan? Dan, pasti sama dengan # 1, tetapi merupakan cara yang tepat untuk menyuntikkan CSS dinamis di WordPress. :)
Chip Bennett
2

Aku memikirkan itu untuk sementara waktu sekarang. Pertanyaan Anda membuat saya kembali ke sana. Tidak yakin itu ide yang bagus atau tidak, jadi saya ingin komentar pakar tentang itu.

Bagaimana jika saya menulis file javascript / css melalui php ketika admin menyimpan data. Ini akan menjadi penulisan satu kali sampai pengguna mengubah tata letak lagi (yang pengguna mungkin tidak melakukannya terlalu sering). Dengan begitu kita mengakses basis data untuk pengaturan pengguna hanya sekali ketika pengguna menyimpan data.

Setelah menulis file itu akan menjadi file javascript / css biasa sehingga kita tidak perlu memanggil database setiap kali memuat tema.

Satu pertanyaan yang perlu dijawab: Apa yang akan terjadi ketika pengunjung mencoba mengakses situs secara instan ketika php menulis file?

Biarkan aku tahu apa yang kamu pikirkan.

Sisir
sumber
Jika Anda menghasilkan file-file itu di wp-content/uploads(satu-satunya direktori dijamin dapat ditulis dari kode WP), itu bisa menjadi pendekatan yang layak. Saya pikir bahkan WP Core menggunakan teknik ini untuk satu file js.
scribu
Kekurangannya adalah itu tidak benar-benar dinamis, yaitu sama untuk semua orang di semua halaman. Untuk setiap variasi, Anda harus membuat file baru. Itu masih merupakan pendekatan yang baik untuk opsi tema / plugin, seperti yang Anda sebutkan.
scribu
@scribu: ya itu benar. itu bisa menjadi berantakan untuk sesuatu seperti. jika kami memberikan pengguna halaman profil khusus dan harus menulis file masing-masing. Tapi itu mungkin pendekatan yang bagus untuk sesuatu seperti jika kita membuat pembuat situs web visual (drag and drop) di mana pengguna mengubah warna dan menambahkan berbagai efek (pada pertanyaan ini) dll. Dan dapat dikombinasikan dengan WPMU;)
Sisir
1

Untuk skrip kecil, yang mungkin tidak ingin Anda sertakan dalam file terpisah, misalnya karena dihasilkan secara dinamis, WordPress 4.5 dan penawaran lebih lanjut wp_add_inline_script. Fungsi ini pada dasarnya mengaitkan skrip ke skrip lain. Katakanlah, misalnya, bahwa Anda sedang mengembangkan tema dan ingin pelanggan Anda dapat menyisipkan skripnya sendiri (seperti Google Analytics atau AddThis) melalui halaman opsi. Contoh .

Untuk gaya ada wp_add_inline_style, yang pada dasarnya berfungsi sama. Anda akan menggunakannya, misalnya, untuk mengulang-ulang semua mod penyesuai Anda, dan mengumpulkan mereka dalam string yang disebut $all_mods, yang kemudian Anda tambahkan seperti ini ke stylesheet utama Anda:

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

Buat file JS.php dinamis dan beri makan query_vars penting untuk itu. Variabel-variabel di dalam $_GETakan membantu file menentukan konteks dan di dalamnya Anda dapat menyimpan dan menggunakannyareadfile() untuk permintaan di masa depan ... lakukan apa saja.

Pastikan saja file tersebut memuat wp-load.phpsebelum apa pun, sehingga Anda memiliki akses ke fungsi WP. Gunakan jalur relatif ke folder saat ini (dirname(__FILE__))atau cukup digg turun dalam struktur folder untuk mencariwp-load.php terlepas dari penempatan plugin.

Kode untuk mencari wp-load.php dari mana saja

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

Cheers, Scribu!

PS : Untuk struktur yang rumit di mana folder tidak mengikuti struktur dekremental WP normal, plugin induk dapat berbagi informasi dengan file yang dapat diakses langsung. Sebuah plugin orang tua yang datang dengan file PHP yang dinamis yang membuat CSS / JS dapat menulis ke dalam file realpath()dari wp-load.phpdan file standalone bisa menggunakan itu. Ini akan menjadi masalah bagi 0,1% pengguna WP. Saya pikir mereka yang memindahkan folder dan tidak mengikuti struktur normal tahu apa yang mereka lakukan dan mungkin dapat plugin PIMP yang perlu dimuatwp-load.php secara langsung.

EarnestoDev
sumber
Imut! Pembenci, harap tambahkan penjelasan. Cerahkan saya. Terima kasih;) xoxo
EarnestoDev
Merupakan praktik yang buruk untuk disertakan wp-load.phpdari file tema atau plugin, karena direktori wp-contentdan / atau pluginsdirektori bisa berada di mana saja relatif terhadap direktori WP root. Ingat WP_CONTENT_DIR dan WP_PLUGINS_DIR.
scribu
1
@scribu Dan file mandiri dapat berkolaborasi dengan plugin induk. Plugin induk dapat menyimpan wp-load.php di folder di mana ia berada dan generator js dinamis dapat membacanya dari sana. Sederhana ...
EarnestoDev
1
Ya, pendekatan plugin induk bisa berfungsi. Tuliskan jawaban Anda dan saya akan menghapus downvote saya. PS: Situs ini dalam bahasa Inggris; Anda mungkin memiliki masalah jika Anda terus meninggalkan komentar dalam bahasa Rumania.
scribu
5
Potong sikap. Beban inti manual adalah teknik yang layak, tetapi jauh dari pilihan pertama yang baik untuk kebanyakan hal. Tidak ada yang meragukan bahwa Anda dapat membuatnya bekerja. Suara adalah tentang kualitas jawaban Anda, bukan otak Anda.
Rarst