多域名共享登录及独立 Header/Footer 加载方案 (PHP+Twig)
2025-03-09 13:33:31
不同域名,咋用同一个登录注册,还能加载各自的 Header?
多个域名(domain.com, domain.org, domain.africa, domain.net)共享数据库和部分内容,但每个域名都有自己独立的注册登录表单,更新起来很麻烦。现在把注册登录表单统一了,可咋根据用户当前访问的域名,加载对应的 header 和 footer 呢?
我用的是 PHP + Twig (无框架),在网上找了些方法,但都不太灵光。下面我来捋一捋问题,并给出解决方案。
问题根源:区分域名,条件加载
问题的核心在于:如何准确判断用户当前访问的是哪个域名,然后根据域名,有条件地加载对应的 header 和 footer 文件 。 之前尝试的方法,要么判断不准确(比如 JavaScript 的方法,总是加载第一个匹配项),要么 Twig 模板引擎获取不到正确的 URL 信息。
解决方案:服务器端才是王道!
由于需要准确获取域名信息,并在服务器端处理模板渲染,客户端(Javascript)方案并不可靠。应该直接在 PHP 中获取当前 URL,然后将域名信息传递给 Twig 模板。
方案一:PHP 传递域名信息给 Twig
-
原理: 在 PHP 中使用
$_SERVER['HTTP_HOST']
获取当前请求的主机名(即域名),然后将这个值传递给 Twig 模板。在 Twig 模板中,根据这个值来决定加载哪个 header 文件。 -
代码示例 (PHP 部分):
<?php // 获取当前域名 $currentDomain = $_SERVER['HTTP_HOST']; // 假设你的 Twig 环境设置好了,名为 $twig echo $twig->render('your_template.html', [ 'currentDomain' => $currentDomain ]); ?>
-
代码示例 (Twig 部分):
{% if currentDomain == 'domain.com' %} {% include 'domains/domaincom/includes/header.html' %} {% elseif currentDomain == 'domain.org' %} {% include 'domains/domainorg/includes/header.html' %} {% elseif currentDomain == 'domain.africa' %} {% include 'domains/domainafrica/includes/header.html' %} {% elseif currentDomain == 'domain.net' %} {% include 'domains/domainnet/includes/header.html' %} {% else %} {# 默认的 header,或者啥也不加载 #} {% endif %} {# ... 页面的其他内容 ... #} {% if currentDomain == 'domain.com' %} {% include 'domains/domaincom/includes/footer.html' %} {% elseif currentDomain == 'domain.org' %} {% include 'domains/domainorg/includes/footer.html' %} {% elseif currentDomain == 'domain.africa' %} {% include 'domains/domainafrica/includes/footer.html' %} {% elseif currentDomain == 'domain.net' %} {% include 'domains/domainnet/includes/footer.html' %} {% else %} {# 默认的 footer,或者啥也不加载 #} {% endif %}
-
解释:
- PHP 代码中,
$_SERVER['HTTP_HOST']
能可靠地获取当前域名。 - 然后,把获取到的域名通过
$twig->render
传递给 Twig 模板。 - Twig 模板里, 用
{% if currentDomain == '...' %}
这样的条件判断语句, 来决定包含哪个 header/footer 文件。
- PHP 代码中,
方案二:创建域名映射,简化 Twig 逻辑
如果域名和 header/footer 文件的路径有规律,可以创建一个映射关系,让 Twig 模板更简洁。
-
原理: 在 PHP 中创建一个数组,将域名映射到对应的 header/footer 文件夹。将这个映射数组传递给 Twig 模板。在 Twig 模板中,通过域名从映射数组中取出对应的文件夹,然后拼接出完整的 header/footer 文件路径。
-
代码示例 (PHP 部分):
<?php $currentDomain = $_SERVER['HTTP_HOST']; // 创建域名到文件夹的映射 $domainMap = [ 'domain.com' => 'domaincom', 'domain.org' => 'domainorg', 'domain.africa' => 'domainafrica', 'domain.net' => 'domainnet', ]; // 获取对应的文件夹名称,如果域名不存在映射,则为空 $domainFolder = $domainMap[$currentDomain] ?? ''; echo $twig->render('your_template.html', [ 'domainFolder' => $domainFolder, ]); ?>
-
代码示例 (Twig 部分):
{% if domainFolder %} {% include 'domains/' ~ domainFolder ~ '/includes/header.html' %} {% endif %} {# ... 页面的其他内容 ... #} {% if domainFolder %} {% include 'domains/' ~ domainFolder ~ '/includes/footer.html' %} {% endif %}
-
解释:
- PHP 代码中创建了一个
$domainMap
数组。 $domainMap[$currentDomain] ?? ''
尝试根据当前域名获取对应的文件夹名称。如果$currentDomain
不在$domainMap
中,则返回空字符串。- Twig 模板中, 使用
~
连接字符串, 拼出完整的 header/footer 文件路径.
- PHP 代码中创建了一个
方案三: 更进一步,把 header/footer 文件名也放到映射里 (可选)
如果 header/footer 文件名在不同域名下也不一样,还可以把文件名也放到映射数组里。
-
原理: 在 PHP 中创建的映射数组,不仅包含文件夹名,还包含 header 和 footer 的文件名。
-
代码示例 (PHP 部分):
<?php $currentDomain = $_SERVER['HTTP_HOST']; $domainMap = [ 'domain.com' => ['folder' => 'domaincom', 'header' => 'header.html', 'footer' => 'footer.html'], 'domain.org' => ['folder' => 'domainorg', 'header' => 'header_org.html', 'footer' => 'footer_org.html'], 'domain.africa' => ['folder' => 'domainafrica', 'header' => 'header_africa.html', 'footer' => 'footer_africa.html'], 'domain.net' => ['folder' => 'domainnet', 'header' => 'header.html', 'footer' => 'special_footer.html'], ]; $domainData = $domainMap[$currentDomain] ?? null; echo $twig->render('your_template.html', [ 'domainData' => $domainData, ]); ?>
-
代码示例 (Twig 部分):
{% if domainData %} {% include 'domains/' ~ domainData.folder ~ '/includes/' ~ domainData.header %} {% endif %} {# ... 页面的其他内容 ... #} {% if domainData %} {% include 'domains/' ~ domainData.folder ~ '/includes/' ~ domainData.footer %} {% endif %}
-
解释:
$domainMap
数组现在每个域名对应一个包含folder
、header
、footer
键的数组。- 在Twig中使用
domainData.folder
,domainData.header
,domainData.footer
来拼接路径
安全建议
- 验证输入: 尽管
$_SERVER['HTTP_HOST']
相对可靠, 但理论上仍然可以被伪造。如果你需要更高的安全性,可以考虑对$currentDomain
的值进行白名单验证,只允许已知的域名。 - 路径安全: 在拼接文件路径时,要确保
$domainFolder
、domainData.header`, `domainData.footer`这些变量的值不会导致路径遍历漏洞。一般来说,使用白名单控制这些变量的值是最安全的。避免直接使用用户可控的输入来拼接文件路径。
进阶技巧:封装成 Twig 扩展(可选)
如果你想让代码更优雅,可以将获取域名和选择 header/footer 的逻辑封装成一个 Twig 扩展。这样,在 Twig 模板中就可以使用自定义的函数或过滤器,让模板更简洁。由于这部分内容较为复杂,这里只提供思路,不展开具体代码。主要步骤如下:
- 创建一个 PHP 类,实现 Twig 的扩展接口(
Twig\Extension\ExtensionInterface
或继承Twig\Extension\AbstractExtension
)。 - 在这个类中,定义一个或多个自定义函数或过滤器。这些函数/过滤器负责获取当前域名,并根据域名返回对应的 header/footer 文件路径。
- 将这个扩展注册到你的 Twig 环境中。
- 在 Twig 模板中,使用你定义的自定义函数或过滤器。
希望以上方案能帮你解决多域名 header/footer 的问题!