Php 用皮肤创建网站-从我的观点来看,提供合适形象的最佳方式是什么?

Php 用皮肤创建网站-从我的观点来看,提供合适形象的最佳方式是什么?,php,image,dynamic,skinning,readfile,Php,Image,Dynamic,Skinning,Readfile,我正在写一个网站,将支持多种皮肤。目前,我正计划允许修改图像和CSS,但底层HTML不会改变。如果皮肤不修改图像或CSS文件,它将从基础皮肤继承该文件 考虑到这一点,到目前为止,我考虑了3种提供皮肤相关文件的方法: 使用查找功能在视图中包装所有特定于皮肤的请求,即: 让php为图像服务 始终尝试加载皮肤文件,如果皮肤文件不存在,请使用ModRewrite将结果发送到php处理程序脚本: 第二点是我想做的,但我只关心让PHP提供基本上每个图像文件的性能影响 我的用户群很小,大约有3万用户,我不认为

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

考虑到这一点,到目前为止,我考虑了3种提供皮肤相关文件的方法:

使用查找功能在视图中包装所有特定于皮肤的请求,即: 让php为图像服务

始终尝试加载皮肤文件,如果皮肤文件不存在,请使用ModRewrite将结果发送到php处理程序脚本:

第二点是我想做的,但我只关心让PHP提供基本上每个图像文件的性能影响

我的用户群很小,大约有3万用户,我不认为这是一个问题,但我也想了解其他人在这种情况下会做什么

谢谢


编辑:我不知道为什么我的代码格式不正确。我按了“代码”按钮,检查是否有4个空格,但还是很难看。对此很抱歉。

这三个选项都是完全有效的。我个人更喜欢第一种,尽管使用图像名称而不是图像路径。如果您的主题控制位足够强大,这将允许主题定义自己额外的用户可控制图像


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

我会尝试构建它,使其模块化,并且易于适应未来的变化。我会尽量避免在代码中放置硬位置,或者至少将其最小化为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页面保存为notDefault.xml

<notDefault>
    <header>locationToHeader/header.png</header>
    <footer>locationToFooter/footer.png</footer>
</notDefault>

我最后选择了选项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捕获它并将其发送到我的处理程序脚本


谢谢你在这方面的帮助。stmpy和Charles提供的另外两个建议也会起作用,但这对我来说是理想的解决方案。这样做的一个好处是,我还可以替换css中的图像以及没有自定义css文件而无法动态替换的图像。我的应用程序将主要包括替换主背景,因此我的主题所需的全部内容,大部分内容将只是创建一个新的皮肤文件夹并上载一个背景图像。

您不能为皮肤的资产命名名称吗?例如,我构建的大多数应用程序都有一个包含编程逻辑的inc目录和一个tpl目录,然后将该目录分解为单独的目录,用于单独的皮肤。如果站点只有一个皮肤,那么它们将只有一个目录

例如:

inc/
    ...
tpl/
    default/
        assets/
            css/
            images/
            js/
    alternative/
        assets/
            css/
            images/
            js/
if (!isset($_SESSION['tpl'])) {
    $tpl = "default";
}
if (isset($_GET['tpl']) && is_dir('tpl/'.$_GET['tpl'])) {
    $_SESSION['tpl'] = $_GET['tpl'];
}
$tpl = $_SESSION['tpl'];
在我的控制器脚本index.php中,我可以监听通过$\u GET数组传递的tpl变量。例如:

inc/
    ...
tpl/
    default/
        assets/
            css/
            images/
            js/
    alternative/
        assets/
            css/
            images/
            js/
if (!isset($_SESSION['tpl'])) {
    $tpl = "default";
}
if (isset($_GET['tpl']) && is_dir('tpl/'.$_GET['tpl'])) {
    $_SESSION['tpl'] = $_GET['tpl'];
}
$tpl = $_SESSION['tpl'];
现在,当前的tpl值在我的$\u会话数组中可用。如果我希望该值在会话和$tpl变量之间保持不变,我可以轻松地将其更改为使用cookies。然后我可以获得如下图像和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" />

修正了你的格式。我不知道为什么会这样。此外,您不需要在问题标题中包含关键字或前缀,这就是标记的用途:谢谢你的建议。我已经考虑过这个想法,但我正在尽量避免配置文件。如果我的替换逻辑更复杂,或者我无法控制皮肤的创建,那么像这样的XML文件会很有意义,但是由于我的替换逻辑非常简单,我可以控制皮肤,因此检查文件系统似乎更适合我的应用程序。
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
        }
    }
}