Рішення для створення динамічного javascript / CSS


15

Скажімо, вам потрібно генерувати код JavaScript або CSS, який залежить від поточного контексту.

Наприклад, у вас є домашня сторінка форма, яка запускає запит ajax під час подання, та інша форма на одній сторінці. Або у випадку з CSS ви хочете створити тему, яка дозволяє його користувачам створювати власну компоновку, змінювати кольори тощо.

Досі я бачу рішення:

  1. Включіть код у головний розділ документа (або наприкінці для JS)

  2. Зробіть спеціальний запит, який виводить код, наприклад site.com?get_assets . Це повільно, оскільки WP завантажується двічі.

  3. Зберігайте його у тимчасових файлах протягом певного часу та завантажуйте звідти. Не дуже надійний для публічних тем або плагінів.

  4. Тільки Javascript - зробіть його статичним, вводячи його у звичайний файл, який завантажується щоразу. У цьому випадку вам доведеться змусити ваш код впоратися з будь-якою ситуацією

Чи знаєте ви інших? Яким шляхом ви б пішли?


Одне питання, з яким я стикався з рішенням 1, - кешування браузером, код не оновлюється при перезавантаженні сторінки.
Авроврата

Відповіді:


9

Ще один варіант, залежно від типу параметрів, які потрібно ввести. Назвемо це (2а). Ви також можете створювати PHP-скрипти, які виводять динамічно генеровані text/cssабо, text/javascriptа не text/html, і надають їм ті дані, які їм потрібні, використовуючи параметри GET, а не завантажуючи WordPress. Звичайно, це працює лише в тому випадку, якщо вам потрібно передати порівняно невелику кількість відносно компактних параметрів. Наприклад, скажімо, що вам потрібно ввести лише 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>

У фантазії-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, які, можливо, вам знадобляться, без того, щоб двічі вдалося завантажити WordPress. Це майже напевно, що ви повинні зробити, якщо у вас немає вагомих причин цього не робити (наприклад, через розмір таблиці стилів або сценарій, який вам потрібно використовувати).

Якщо розмір стає досить великим, щоб викликати неполадки щодо ваги вашої однієї сторінки, ви можете спробувати (2) або (2a).

Інакше - це, мабуть, краща ідея - ви можете спробувати відокремити частини сценарію чи таблицю стилів, які фактично використовують динамічні дані від частин, які можуть бути визначені статично. Скажімо, у вас є таблиця стилів, якій потрібно передати каталог з WordPress, щоб встановити фоновий параметр для елемента # my-fancy. Ви можете помістити все це в головний елемент:

 <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. Краще розділити лише рядки, які залежать від 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>

Замість цього покладіть щось подібне до головного елемента:

 <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), або глобально доступний змінні (глобальні елементи, елементи DOM або будь-який інший кубічний отвір для JS).


Блискуча відповідь!
scribu

2
Лише невелике доповнення: у випадку JS ми можемо використовувати wp_localize_sciprt для додавання динамічних змінних.
Anh Tran

6

Динамічний випадок CSS досить простий.

Просто створіть функцію, яка виводить динамічні визначення CSS всередині <style type="text/css"></style>тегів, а потім підключіть цю функцію до 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_scripts, оскільки WordPress не має wp_enqueue_stylesгачка дій.


1
те саме, що 1). Це я зараз роблю, але якщо вам сподобалося 40K CSS, ви отримуєте об'ємний html-документ
onetrickpony

1
Але ці 40K CSS повинні бути десь виведені , правда? І, безумовно, те саме, що №1, але це правильний спосіб ввести динамічний CSS в WordPress. :)
Чіп Беннетт

2

Я певний час думав про це. Ваше запитання змушує мене повернутися до цього. Не впевнений, це гарна ідея чи ні, тому я хотів би коментарі експертів з цього приводу.

Що робити, якщо я записую файл javascript / css через php, коли адміністратор зберігає дані. Це буде одноразовим записом, поки користувач знову не змінить макет (що користувач може робити не надто часто). Таким чином ми отримуємо доступ до бази даних щодо налаштувань користувача лише один раз, коли користувач зберігає дані.

Після написання файлу це буде звичайний файл JavaScript / css, тому нам не доведеться дзвонити в базу даних кожного разу, коли тема завантажується.

Одне питання, на який потрібно відповісти: Що станеться, коли відвідувач спробує отримати доступ до сайту в ту мить, коли php пише файл?

Дайте мені знати, що ви думаєте.


Якщо ви генеруєте ці файли в wp-content/uploads(єдиний каталог, який гарантується для запису з коду WP), це може бути життєздатним підходом. Я думаю, що навіть WP Core використовує цю техніку для одного js-файлу.
scribu

Недолік у тому, що він насправді не динамічний, тобто однаковий для всіх на всіх сторінках. Для кожної варіації вам доведеться генерувати новий файл. Як ви вже згадували, це все ще хороший підхід для варіантів теми / плагінів.
scribu

@scribu: так це правда. це може бути безлад для чогось подібного. якщо ми надаємо користувачам користувальницьку сторінку профілю та доводимо писати файли кожен із них. Але це може бути хорошим підходом для чогось подібного, якщо ми робимо візуальний виробник веб-сайтів (перетягування), коли користувач змінює кольори та додає різні ефекти (станом на це питання) тощо. І може поєднуватися з WPMU;)
Sisir

1

Що стосується невеликих фрагментів сценаріїв, які ви, можливо, не хочете включати в окремий файл, наприклад, оскільки вони генеруються динамічно, WordPress 4.5 та інші пропозиції wp_add_inline_script. Ця функція в основному прив'язує сценарій до іншого сценарію. Скажімо, наприклад, що ви розробляєте тему і хочете, щоб ваш клієнт міг вставити власні сценарії (наприклад, Google Analytics або AddThis) на сторінку параметрів. Приклад .

Для стилів є wp_add_inline_style, що в основному працює так само. Ви використовуєте його, наприклад, для перегляду всіх ваших модифікаторів налаштування та збирайте їх у рядок під назвою $all_mods, який потім ви додасте так у свій основний таблицю стилів:

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

-2

Створіть динамічний файл JS.php і подайте до нього важливі запити_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, батьківські плагіни можуть обмінюватися інформацією з безпосередньо доступними файлами. Батько плагін , який поставляється з динамічною PHP файлом , який робить CSS / JS може написати в файл realpath()з wp-load.phpі файлу автономного можна використовувати. Це буде проблемою для 0,1% користувачів WP. Я думаю, що ті, хто переміщує папки і не дотримуються нормальної структури, знають, що вони роблять, і, ймовірно, можуть плагіни PIMP, які потрібно завантажувати wp-load.phpбезпосередньо.


Симпатичний! Ненависть, будь ласка, додайте пояснення. Просвіти мене. Спасибі;) xoxo
EarnestoDev

Неправильна практика включати wp-load.phpз теми чи файлів плагінів, оскільки wp-contentта / або plugins каталоги можуть бути де завгодно відносно кореневого редактора WP. Запам’ятайте WP_CONTENT_DIR та WP_PLUGINS_DIR.
scribu

1
@scribu І окремий файл може співпрацювати з батьківським плагіном. Батьківський плагін може зберігати wp-load.php у папці, де він знаходиться, і динамічний js-генератор може зчитувати його звідти. Просте ...
EarnestoDev

1
Так, підхід батьківського плагіна може працювати. Напишіть це у своїй відповіді, і я зніму свій короткий запис. PS: Цей сайт англійською мовою; у вас можуть виникнути проблеми, якщо ви продовжуєте залишати зауваження румунською мовою.
scribu

5
Виріжте ставлення. Ручне навантаження на серцевину - це життєздатна техніка, але далеко не хороший перший вибір для більшості речей. Ніхто не сумнівається, що ви можете змусити його працювати. Голоси - це якість вашої відповіді, а не ваш мозок.
Рарст
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.