使用皮肤创建网站 - 从我的视角提供正确图像的最佳方式是什么?

时间:2010-08-02 17:47:39

标签: php image dynamic skinning readfile

我正在重新编写一个支持多个皮肤的网站。目前,我只是计划允许修改图像和CSS,但底层HTML不会改变。如果皮肤不修改图像或CSS文件,它将从基础皮肤继承该文件。

考虑到这一点,以下是我迄今为止考虑提供依赖皮肤的文件的三种方法:

  1. 使用查找功能在视图中包装所有特定于皮肤的请求请求,即:
  2.     <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" />

    3. 我想做的就是2号,但我只关心让PHP基本上为每个图像文件提供服务的性能影响。

      我的用户群足够小(约3万用户),我认为这不是一个问题,但我也想了解其他人在这种情况下做了什么。

      感谢。

      编辑:我不知道为什么我的代码格式不正确。我点击代码按钮并检查它是4个空格,但它仍然很难看。对不起。

4 个答案:

答案 0 :(得分:1)

所有这三个都是完全有效的选择。我个人更喜欢第一个,虽然使用图像名称而不是图像路径。如果你的主题控制位足够强大,这可以让主题定义他们自己的额外用户可控图像。

考虑第四个选项:不要使用img标签实际插入图像。相反,使用div与背景图像。这可以适用于大多数情况,并将图像完全定义到样式表。不幸的是,这也是一个更复杂的选择。

答案 1 :(得分:1)

我会尝试构建它,以便它是模块化的,并且很容易适应未来的变化。我会避免在代码中尽可能多地放入硬盘位置,或者至少将它最小化到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>

答案 2 :(得分:0)

我最后选择了变量2.我正在寻找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捕获它并将其发送到我的处理程序脚本。

感谢您的帮助。其他两个建议都提供了很多,Charles也可以使用,但这对我来说是理想的解决方案。作为这样做的额外奖励,我还可以替换css中的图像以及没有自定义css文件的动态内容。我的应用程序主要包括替换主要背景,因此我的主题所需的一切都只是创建一个新的皮肤文件夹并上传一个背景图像。

答案 3 :(得分:0)

你能否命名皮肤的资产?例如,我构建的大多数应用程序都有一个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
        }
    }
}