Решения для генерации динамического javascript / CSS

Предположим, вам нужно создать javascript или CSS-код, который зависит от текущего контекста.

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

Решения, которые я вижу до сих пор:

  1. Включите код в раздел главы документа (или в конце в случае JS)

  2. Сделайте специальный запрос, который выводит код, например site.com?get_assets . Это медленно, потому что WP загружается дважды.

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

  4. Только Javascript – статируйте его, помещая его в обычный файл, который загружается каждый раз. В этом случае вам придется сделать код в любой ситуации

Вы знаете других? В каком направлении вы пойдете?

Еще один вариант, в зависимости от того, какие параметры вам нужно передать. Назовем его (2a). Вы также можете создавать 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> 

В 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, которые вам могут понадобиться, без снижения производительности при загрузке WordPress дважды. Это почти наверняка, что вы должны делать, если у вас нет сильной причины (например, из-за размера таблицы стилей или скрипта, который вам нужно использовать).

Если размер становится достаточно большим, чтобы вызвать проблему с точки зрения веса вашей одной страницы, вы можете попробовать (2) или (2a).

Или еще – это, вероятно, лучшая идея – вы можете попытаться выделить части скрипта или таблицу стилей, которые фактически используют динамические данные из частей, которые могут быть указаны статически. Ssay у вас есть таблица стилей, которая должна быть передана из каталога 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> 

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

Динамический случай 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 действия wp_enqueue_styles .

Я думал об этом сейчас. Ваш вопрос заставляет меня вернуться к этому. Не уверен, что это хорошая идея или нет, поэтому я бы хотел, чтобы эксперты комментировали это.

Что делать, если я пишу файл javascript / css через php, когда администратор сохраняет данные. Он будет писать один раз, пока пользователь не изменит макет снова (какой пользователь может не делать слишком часто). Таким образом, мы получаем доступ к базе данных для пользовательских настроек только один раз, когда пользователь сохраняет данные.

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

Ответ на один вопрос: что произойдет, когда посетитель попытается получить доступ к сайту в тот момент, когда php записывает файл?

Дайте мне знать, что вы думаете.

Для небольших фрагментов скриптов, которые вы не хотите включать в отдельный файл, например, потому что они генерируются динамически, 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); 

Создайте динамический файл JS.php и загрузите в него важные query_vars. Эти переменные в $_GET помогут файлу определить контекст, и в нем вы можете кэшировать и использовать readfile() для будущих запросов … делать что угодно.

Просто убедитесь, что файл загружает wp-load.php раньше всего, поэтому у вас есть доступ к функциям WP. Используйте относительный путь к текущей папке (dirname(__FILE__)) или просто digg, спускающийся в структуре папок, чтобы найти 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 .