Intereting Posts
Как проверить, пусто ли пользовательское поле профиля пользователя Codex: Database Описание: значение кардинальности Показывать будущие события на основе настраиваемого поля И порядок по дате Alert Email при изменении любой почты или страницы У Drupal идет Symfony. Поможет ли WordPress делать то же самое? Перемещенный сайт и домен сайта wordpress обновления к содержимому страницы wp возвращают меня на главную страницу и не будут сохранять Должен ли я использовать spl_autoload_register () в моем плагине? Фильтрация пользовательского типа post post в раскрывающемся меню администратора? Как WordPress отслеживает, что определенный Пользователь зарегистрирован? download_url () отображается серым значком Создание продукта woocommerce с использованием WordPress REST API Санизировать или обрабатывать строку в редакторе с помощью короткого кода Невозможно изменить wp_title с помощью add_filter Пользовательский запрос не находит страницы

Создание файлов CSS с помощью PHP-скриптов?

В рамках моих усилий по ускорению моих тем для моих клиентов я доставляю свой CSS через динамический PHP-файл. В конце вызванного, например, my_theme_css.php :

Это позволяет мне добавлять заголовки Expiry к моим CSS и JavaScript следующим образом:

 <?php header("Expires: Thu, 31 Dec 2020 20:00:00 GMT"); header('Content-type: text/css'); ?> 

Затем я хочу разрешить пользователю добавлять собственный пользовательский CSS, поэтому я установил следующее:

 <?php header("Expires: Thu, 31 Dec 2020 20:00:00 GMT"); header('Content-type: text/css'); ?> p{color:blue;} /** Custom CSS **/ <?php if(get_theme_mod('my_custom_css') != '') { $my_custom_css = get_theme_mod('my_custom_css'); echo $my_custom_css; } ?> 

Затем я добавил соответствующие параметры темы. Но то, что я нахожу, заключается в том, что get_theme_mod() не работает из-за проблемы с областью (я думаю.) Любые предложения о том, как обойти это?

Я мог бы добавить следующий код:

 <?php if(get_theme_mod('my_custom_css') != '') { $my_custom_css = get_theme_mod('my_custom_css'); echo $my_custom_css; } ?> 

В тегах <style></style> в заголовке, и это будет работать нормально, ожидайте, что я не хочу встроить CSS, я хочу, чтобы он был в основном файле CSS с заголовком истечения срока действия.

Привет @Ash G:

Я не следил за 100%, когда у вас были проблемы, поэтому я не уверен, что действительно могу ответить на ваши вопросы по пунктам, но я могу объяснить, как это сделать с нуля . И если вы не делаете то, что вам нравится, то вы упомянули, что это немного больше работы, чем я думаю, вы ожидали, но это все еще вполне выполнимо. И даже если я расскажу о многих местах, о которых вы уже знаете, есть хороший шанс, что другие люди с меньшими знаниями или опытом найдут это через Google и им тоже будет помогать.

/wp-load.php WordPress с /wp-load.php

Первое, что нам нужно сделать в файле my_theme_css.php – это функции основной библиотеки WordPress. Следующая строка кода загружает /wp-load.php . Он использует $_SERVER['DOCUMENT_ROOT'] чтобы найти корень веб-сайта, поэтому вам не нужно беспокоиться о том, где вы храните этот файл на своем сервере; предполагая, что DOCUMENT_ROOT установлен правильно, поскольку он всегда должен быть для WordPress, тогда это будет загружать WordPress:

 <?php include_once("{$_SERVER['DOCUMENT_ROOT']}/wp-load.php"); 

Так что это легкая часть. Далее идет сложная часть …

Сценарии PHP должны обрабатывать всю логику кэширования

Вот где я могу поспорить, вы, возможно, споткнулись, потому что я уверен, что я пытался выяснить, как ответить на ваш вопрос. Мы так привыкли к тому, что кеширование обрабатывается веб-сервером Apache, что мы забываем или даже не понимаем, что нам нужно делать все тяжелое поднятие, когда мы загружаем CSS или JS с PHP.

Конечно, заголовок expiry может быть всем, что нам нужно, когда у нас есть прокси в середине, но если запрос делает его на веб-сервере, а скрипт PHP просто волей-неволей возвращает содержимое и код состояния «ОК», в сущности, вы будете не имеют кеширования.

Возврат «200 Ok» или «304 Not Modified»

Более конкретно, наш PHP-файл, который возвращает CSS, должен правильно отвечать на заголовки запросов, отправленные браузером. Наш PHP-скрипт должен вернуть правильный код состояния на основе того, что содержат эти заголовки. Если контент нужно обслуживать, потому что это запрос в первый раз или из-за истечения срока действия, сценарий PHP должен генерировать все содержимое CSS и возвращаться с «200 Ok» .

С другой стороны, если мы определим на основе заголовков запросов, связанных с кешем, что у браузера клиента уже есть последний CSS, мы не должны возвращать какой-либо CSS и вместо этого возвращаться с «304 Not Modified» . Слишком строчные коды для этого, соответственно, (конечно, вы никогда не будете использовать их как одну строку за другой, я просто показываю этот путь здесь для удобства) :

 <?php header('HTTP/1.1 200 Ok'); header('HTTP/1.1 304 Not Modified'); 

Четыре варианта HTTP-кэширования

Далее нам нужно посмотреть на различные способы HTTP-кэширования. Первое – это то, что вы упоминаете; Expires :

  • Истекает : этот заголовок Expires ожидает дату в формате ( PHP gmdate() ) в формате 'D, d MYH:i:s' с добавлением ' GMT' ( GMT означает среднее время по Гринвичу ). Теоретически, если этот заголовок обслуживается браузер и нисходящие прокси будут кэшироваться до истечения указанного времени, после чего он снова начнет запрашивать страницу. Это, вероятно, самый известный из кэширующих заголовков, но, по-видимому, он не является предпочтительным; Cache-Control – лучший . Интересно, что в моем тестировании на localhost с Safari 5.0 на Mac OS XI никогда не было возможности заставить браузер уважать заголовок Expires ; он всегда запрашивал файл снова (если кто-то может это объяснить, я был бы благодарен.) Вот пример, который вы дали выше:

header("Expires: Thu, 31 Dec 2020 20:00:00 GMT");

  • Cache-Control : заголовок Cache-Control легче работать, чем заголовок Expires потому что вам нужно указывать только количество секунд в секундах как max-age означающее, что вам не нужно указывать точный формат даты в строке которая легко ошибается. Кроме того, Cache-Control позволяет несколько других параметров, таких как возможность сообщить клиенту, что он всегда повторно проверял кеш, используя параметр mustrevalidate и public если вы хотите принудительно кэшировать обычные запросы без кэширования (т. Е. Запросы через HTTPS ) и даже не кеш, если это то, что вам нужно (т. е. вы можете заставить отслеживать рекламные объявления размером 1×1 пикселей .GIF не кэшироваться.) Как и Expires мне также не удалось заставить это работать при тестировании ( любая помощь? ) Следующий пример кэширует 24-часовой период (60 секунд на 60 минут на 24 часа):

header("Cache-Control: max-age=".60*60*24.", public, must-revalidate");

  • Last-Modified / If-Modified-Since : Тогда есть заголовок Last-Modified response и пара заголовка запроса If-Modified-Since . Они также используют тот же формат даты GMT, что и заголовок Expires но они поддерживают рукопожатие между клиентом и сервером. PHP-скрипту необходимо отправить заголовок Last-Modified (который, кстати, вам следует обновлять только тогда, когда ваш пользователь обновляет свой собственный CSS), после чего браузер будет продолжать отправлять такое же значение обратно, как и If-Modified-Since и это обязанность скрипта PHP сравнить сохраненное значение с тем, которое было отправлено браузером. Здесь PHP-скрипт должен принять решение об обслуживании 200 Ok или 304 Not Modified . Вот пример обслуживания Last-Modified заголовка с использованием текущего времени (что не то, что мы хотим сделать, см. Более поздний пример того, что нам действительно нужно):

header("Last-Modified: " . gmdate('D, d MYH:i:s', time()).'GMT');

И вот как вы читали Last-Modified возвращаемый браузером через заголовок If-Modified-Since :

$last_modified_to_compare = $_SERVER['HTTP_IF_MODIFIED_SINCE'];

  • ETag / If-None-Match : И, наконец, есть ETag ответа ETag и пара заголовка запроса If-None-Match . ETag который на самом деле является лишь маркером, который наш PHP устанавливает на уникальное значение (обычно на основе текущей даты) и отправляет браузер, и браузер возвращает его. Это текущее значение отличается от того, что браузер возвращает ваш PHP-скрипт, должен регенерировать содержимое сервера 200 Ok иначе ничего не генерировать и обслуживать 304 Not Modified . Вот пример установки ETag с использованием текущего времени:

header("ETag: " . md5(gmdate('D, d MYH:i:s', time()).'GMT'));

И вот как вы прочитали бы ETag возвращенный браузером через заголовок If-None-Match :

$etag_to_match = $_SERVER['HTTP_IF_NONE_MATCH'];

Теперь, когда мы рассмотрели все, давайте посмотрим на фактический код, который нам нужен:

Обслуживание файла CSS через init и wp_enqueue_style()

Вы не показали этого, но я решил, что я покажу его на благо других. Вот вызов функции, который сообщает WordPress использовать my_theme_css.php для его CSS. Это может быть сохранено в файле functions.php темы или даже в плагине, если это необходимо:

 <?php add_action('init','add_php_powered_css'); function add_php_powered_css() { if (!is_admin()) { $version = get_theme_mod('my_custom_css_version',"1.00"); $ss_dir = get_stylesheet_directory_uri(); wp_enqueue_style('php-powered-css', "{$ss_dir}/my_theme_css.php",array(),$version); } } 

Следует отметить несколько моментов:

  • Использование is_admin() чтобы избежать загрузки CSS в админ (если вы этого не хотите),
  • Использование get_theme_mod() для загрузки CSS с версией по умолчанию 1.00 (более того, это немного),
  • Использование get_stylesheet_directory_uri() для захвата правильного каталога для текущей темы, даже если текущая тема является дочерней темой,
  • Использование wp_enqueue_style() для очереди CSS, чтобы позволить WordPress загружать его в надлежащее время, когда 'php-powered-css' – это произвольное имя для ссылки в качестве зависимости позже ( если необходимо ), а пустой array() означает это CSS не имеет зависимостей ( хотя в реальном мире он часто имеет один или несколько ), и
  • Использование $version ; Вероятно, самый важный, мы wp_enqueue_style() добавить параметр ?ver=1.00 в URL-адрес /my_theme_css.php чтобы при изменении версии браузер просмотрел его как совершенно другой URL-адрес (гораздо больше того, что в немного.)

Установка $version и Last-Modified при обновлении пользователем CSS

Итак, вот трюк. Каждый раз, когда пользователь обновляет свой CSS, вы хотите обслуживать контент и не дожидаться до 2020 для тайм-аута браузера каждого пользователя, верно? Вот функция, которая в сочетании с моим другим кодом выполнит это. Каждый раз, когда вы сохраняете CSS, обновляемый пользователем, используйте эту функцию или функциональные возможности, подобные тому, что содержится внутри:

 <?php function set_my_custom_css($custom_css) { $new_version = round(get_theme_mod('my_custom_css_version','1.00',2))+0.01; set_theme_mod('my_custom_css_version',$new_version); set_theme_mod('my_custom_css_last_modified',gmdate('D, d MYH:i:s',time()).' GMT'); set_theme_mod('my_custom_css',$custom_css); } 

Функция set_my_custom_css() автоматически увеличивает текущую версию на 0,01 (это было просто произвольное значение приращения, которое я выбрал), а также устанавливает последнюю измененную дату прямо сейчас и, наконец, сохраняет новый пользовательский CSS. Для вызова этой функции это может быть так же просто, как это (где new_custom_css , скорее всего, будет назначен через пользователя, отправленного $_POST а не с помощью new_custom_css как вы видите здесь) :

 <?php $new_custom_css = 'body {background-color:orange;}'; set_my_custom_css($new_custom_css); 

Это подводит нас к заключительному, хотя и значительному этапу:

Создание CSS из скрипта PHP

Наконец, мы увидим мясо, фактический файл my_theme_css.php . На высоком уровне он тестирует как « Last-Modified If-Modifed-Since сравнению с сохраненным Last-Modified значением, так и If-None-Match против ETag который был получен из сохраненного значения Last-Modified и если ни один из них не изменился, он просто устанавливает заголовок в 304 Not Modifed и не завершен до конца.

Если, однако, любой из них изменил, он генерирует Expires , Cache-Control . Заголовки Last-Modified и Etag а также 200 Ok и указывающие, что тип содержимого – text/css . Нам, вероятно, не нужны все те, но, учитывая то, как аккуратное кэширование может быть с разными браузерами и прокси-серверами, я полагаю, что это не повредит для покрытия всех баз. (И любой, у кого больше опыта с кешированием HTTP и WordPress, пожалуйста, сделайте перезвон, если у меня возникнут какие-либо нюансы.)

В следующем коде есть несколько деталей, но я думаю, что вы, вероятно, можете сами их решить:

 <?php $s = $_SERVER; include_once("{$s['DOCUMENT_ROOT']}/wp-load.php"); $max_age = 60*60*24; // 24 hours $now = gmdate('D, d MYH:i:s', time()).'GMT'; $last_modified = get_theme_mod('my_custom_css_last_modified',$now); $etag = md5($last_modified); if (strtotime($s['HTTP_IF_MODIFIED_SINCE']) >= strtotime($last_modified) || $s['HTTP_IF_NONE_MATCH']==$etag) { header('HTTP/1.1 304 Not Modified'); } else { header('HTTP/1.1 200 Ok'); header("Expires: " . gmdate('D, d MYH:i:s', time()+$max_age.'GMT')); header("Cache-Control: max-age={$mag_age}, public, must-revalidate"); header("Last-Modified: {$last_modified}"); header("ETag: {$etag}"); header('Content-type: text/css'); echo_default_css(); echo_custom_css(); } exit; function echo_custom_css() { $custom_css = get_theme_mod('my_custom_css'); if (!empty($custom_css)) echo "\n{$custom_css}"; } function echo_default_css() { $default_css =<<<CSS body {background-color:yellow;} CSS; echo $default_css; } 

Итак, эти три основных бита кода; 1.) add_php_powered_css() вызываемая крючком init , 2.) set_my_custom_css() вызываемая любым кодом, позволяет пользователю обновлять свой собственный CSS и, наконец, 3.) my_theme_css.php вы должны в значительной степени иметь это лизнул.

Дальнейшее чтение

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

  • Кэшируйте это! Решение проблем производительности PHP – типичная SitePoint Uber-Article; пять (5) длинных страниц кеширования всех вещей и PHP, охватывающих HTTP и другие формы кеширования.

  • CSS Caching Hack – это то, что я сделал с $version но он объясняет более глубокие, чем я.

  • php: howto управление кэшированием страниц – хорошая информация об использовании HTTP-заголовков с PHP.

Эпилог:

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

Истекает в 2020 ? Наверное, слишком экстремально.

Во-первых, я действительно не думаю, что вы хотите установить Expires до 2020 года. Любые браузеры или прокси, уважающие Expires , не будут повторно запрашиваться даже после того, как вы внесете много изменений CSS. Лучше установить что-то разумное, как 24 часа (например, я сделал в своем коде), но даже это нарушит пользователей в течение дня, в течение которого вы вносите изменения в hardcoded CSS, но забываете, но номер обслуживаемой версии. Модерация во всем?

Это все может быть излишним!

Поскольку я читал различные статьи, чтобы помочь мне ответить на ваш вопрос, я наткнулся на следующее из урока г-на Кэша , Марк Ноттингем :

Лучший способ сделать кеш-дружественный сценарий (а также работать лучше) – это сбрасывать его содержимое на простой файл всякий раз, когда он изменяется. Затем веб-сервер может рассматривать его как любую другую веб-страницу, генерировать и использовать валидаторы, что облегчает вашу жизнь. Не забывайте записывать только те файлы, которые были изменены, поэтому сохраняются Last-Modified.

В то время как весь этот код я написал это круто и было весело писать (да, я действительно признал это), может быть, лучше просто создать статический CSS-файл каждый раз, когда пользователь обновит свой собственный CSS вместо этого, и пусть Apache сделает все тяжелое поднятие как это родилось? Я просто говорю …

Надеюсь это поможет!

Попробуйте его кодировать так:

 <?php $my_custom_css = get_theme_mod('my_custom_css'); if(!empty($my_custom_css)) { echo $my_custom_css; } ?> 

Это должно помочь вам решить любые проблемы с помощью функции get_theme_mod() .