Создание веб-сайта со скинами. Как, на мой взгляд, лучше всего подать правильное изображение?

Я переписываю веб-сайт, который будет поддерживать несколько скинов. В настоящее время я просто планирую разрешить изменение изображений и CSS, но базовый HTML не изменится. И если скин не изменяет изображение или файл CSS, он наследует этот файл от базового скина.

Имея это в виду, вот 3 способа, которые я рассмотрел до сих пор для обслуживания файлов, зависящих от скина:

  1. Оберните все запросы, специфичные для скина, в представлении с помощью функции поиска, т.е.:
    <img src="<?php get_skin_file('/images/header.png', 'skin1'); ?>" />

    function get_skin_file($file, $skin) {
        $skin_file = '/' . $skin . '/' . $file;
        if(is_readable($skin_file)) return $skin_file;
        return '/default/' . $file;
    }
  1. Пусть php обслуживает изображение

    <img src="/header.png.php?skin=skin1" />

  2. Всегда пытайтесь загрузить файл скина, и если он не существует, используйте ModRewrite, чтобы отправить результат в скрипт обработчика php:

    <img src="/skin1/header.png" />

Номер 2 - это то, что я хотел бы сделать, но меня просто беспокоит влияние на производительность того, что PHP обслуживает практически каждый файл изображения.

Моя пользовательская база достаточно мала (около 30 тысяч пользователей), поэтому я не думаю, что это действительно будет проблемой, но я также хотел бы узнать, что другие люди делают в этой ситуации.

Спасибо.

РЕДАКТИРОВАТЬ: я понятия не имею, почему мой код не отформатирован должным образом. Я нажал кнопку кода и проверил, что это 4 пробела, но это все еще уродливо. Извини за это.


person user126715    schedule 02.08.2010    source источник
comment
Исправлено ваше форматирование. Не знаю, почему он так ломался. Кроме того, вам не нужно включать ключевые слова или префиксы в названия вопросов, для чего нужны теги. :)   -  person Charles    schedule 02.08.2010


Ответы (4)


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

Рассмотрим четвертый вариант: на самом деле не вставляйте изображения с помощью тегов img. Вместо этого используйте div с фоновыми изображениями. Это может работать в большинстве случаев и оставляет определение изображений полностью на усмотрение таблицы стилей. К сожалению, это также гораздо более сложный вариант.

person Charles    schedule 02.08.2010

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

Одна вещь, на которую, возможно, стоит обратить внимание, — это какой-то файл ini или файл xml, который содержит информацию о ваших изображениях для определенных скинов. Таким образом, жесткие местоположения находятся не в вашем php или html, а просто в файле ресурсов, который легко изменить.

Мне нравится использовать xml, поэтому вот пример того, что вы можете сделать.

Вот html.

<?php $skin = "notDefault"; ?>
<img src="<?php get_skin_image("header",$skin) ?>" />
<img src="<?php get_skin_image("footer",$skin) ?>" />

Тогда вот ваша функция, если образ скина не найден, он извлечет его из XML-файла по умолчанию.

function get_skin_image($type,$skin){
    $skin_xml_data = xml2array("skinFolderLocation/ " . $type . ".xml"); 
    $default_xml_data = xml2array("defaultFolderLocation/default.xml");
    // here is a link to the xml2array function for you to download 
    // http://www.php.net/manual/en/function.xml-parse.php#87920
    if(isset($skin_xml_data[$skin][$type])){
        return $skin_xml_dat[$skin][$type];
    } else {
        return $default_xml_data["default"][$type];
    }
}

И, наконец, страница xml сохранена как notDefault.xml.

<notDefault>
    <header>locationToHeader/header.png</header>
    <footer>locationToFooter/footer.png</footer>
</notDefault>
person stmpy    schedule 02.08.2010
comment
Спасибо за предложение. Я обдумывал эту идею, но стараюсь максимально избегать конфигурационных файлов. Если бы моя логика подстановки была более сложной и/или у меня не было контроля над созданием скинов, XML-файл, подобный этому, имел бы большой смысл, но, поскольку моя логика подстановки настолько проста, и я контролирую скины, проверка файловая система кажется более подходящей для моего приложения. - person user126715; 02.08.2010

Я остановился на варианте варианта 2. У меня есть apache, который ищет шаблоны URL-адресов, и если присутствует URL-адрес, заменяемый скином, запрос направляется в мой сценарий выбора изображения скина.

Вот соответствующая конфигурация Apache:

<Directory /var/www/website>
  RewriteEngine on
  RewriteBase /

  RewriteCond %{REQUEST_URI} \.select.(png|jpg|gif|txt|css)$ [NC]
  RewriteRule ^(.*)$ index.php?mode=select&q=$1 [L,QSA]
</Directory>

Вот код PHP из файла, который отображает изображение:

<?php
preg_match("%^(?P<path>.+)\.select\.(?P<ext>(jpg|gif|png|txt|css))$%", $_REQUEST['q'], $matches);

$base = '/' . $matches['path'] . '.' . $matches['ext'];

$file = '/skins/' . App::get('skin') . '/' . $base;

if(is_readable($file)) {
  header('Content-type: image/' . $matches['ext']);
  header('Content-Transfer-Encoding: binary');
  header('Content-Length: ' . filesize($file)+1);
  readfile($file);
  exit();
}
//custom file isn't available, so load the default
$file = '/skins/default/' . $base;
header('Content-type: image/' . $matches['ext']);
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file)+1);
readfile($file);
exit();
?>

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

<img src="/images/header.select.png" />

и apache ловит его и отправляет в мой скрипт-обработчик.

Спасибо за вашу помощь. Оба других 2 предложения, предоставленные stmpy и Charles, также будут работать, но это было идеальным решением для меня. В качестве бонуса за то, что я делаю это таким образом, я также могу заменять изображения в css и то, что не динамически без пользовательских файлов css. Мое приложение в значительной степени будет состоять только из замены основного фона, поэтому все, что будет необходимо для моих тем, по большей части будет просто создание новой папки скина и загрузка одного фонового изображения.

person user126715    schedule 03.08.2010

Не могли бы вы не использовать имена активов вашего скина? Например, большинство приложений, которые я создаю, имеют каталог inc (содержащий программную логику) и каталог tpl, который затем разбивается на отдельные каталоги для отдельных скинов. Если на сайте есть только один скин, то они будут только в одном каталоге.

Например:

inc/
    ...
tpl/
    default/
        assets/
            css/
            images/
            js/
    alternative/
        assets/
            css/
            images/
            js/

В моем скрипте контроллера index.php я могу прослушивать переменную tpl, которая будет передана через массив $_GET. Например:

if (!isset($_SESSION['tpl'])) {
    $tpl = "default";
}
if (isset($_GET['tpl']) && is_dir('tpl/'.$_GET['tpl'])) {
    $_SESSION['tpl'] = $_GET['tpl'];
}
$tpl = $_SESSION['tpl'];

Теперь текущее значение tpl доступно в моем массиве $_SESSION (я мог бы легко изменить это, чтобы вместо этого использовать файлы cookie, если бы я хотел, чтобы значение сохранялось между сеансами) и переменной $tpl. Затем я могу получить изображения и пути CSS следующим образом:

<img src="tpl/<?php echo $tpl; ?>/assets/images/heading.jpg" alt="Heading image" />

<link rel="stylesheet" href="tpl/<?php echo $tpl; ?>/assets/css/screen.css" type="text/css" />

Запросы активов (CSS, изображения, JavaScript) затем можно было бы обернуть в пользовательскую функцию. Это также может обрабатывать случаи, когда, скажем, все ваши файлы JavaScript содержатся в скине default, и вы не хотите дублировать их в скине alternative.

function get_template_file($filename, $tpl)
{
    // if we're requesting a JavaScript file, serve from 'default' regardless
    if (substr($filename, -3) == ".js") {
        return "tpl/default/".$filename;
    }
    else {
        $file = "tpl/{$tpl}/{$filename}";
        if (is_file($file) && is_readable($file)) {
            return $file;
        }
        else {
            $tpl = "default";
            return $file; // try return 'default' filepath
        }
    }
}
person Martin Bean    schedule 03.08.2010