PHP中ASP.Net的web.sitemap的最佳替代品

时间:2011-05-04 14:14:47

标签: php asp.net

在ASP.Net中,我通常使用标准web.sitemap文件驱动我的主导航,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
    <siteMapNode url="~/index.html" title="My Awesome Site">
        <siteMapNode url="~/About/index.html" title="About">
            <siteMapNode url="~/About/Board.html" title="Board"/>
            <siteMapNode url="~/About/Vision.html" title="Vision"/>
            <siteMapNode url="~/About/Mission.html" title="Mission"/>
            <siteMapNode url="~/About/Support.html" title="Support"/>
            <siteMapNode url="~/About/Locations.html" title="Locations"/>
            <siteMapNode url="~/About/Funding-Sources.html" title="Funding Sources"/>
            <siteMapNode url="~/About/Volunteer.html" title="Volunteer"/>
            <siteMapNode url="~/About/Staff.html" title="Staff"/>
        </siteMapNode>
        <siteMapNode url="~/Parents/index.html" title="Parents">
            <siteMapNode url="~/Parents/Child-Development.html" title="Child Development"/>
            <siteMapNode url="~/Parents/Referrals.html" title="Referrals"/>
        </siteMapNode>
        <siteMapNode url="~/Resources/index.html" title="Resources">
            <siteMapNode url="~/Resources/Resource-Library.html" title="Resource Library"/>
            <siteMapNode url="~/Resources/Links.html" title="Links"/>
        </siteMapNode>
    </siteMapNode>
</siteMap>

然后我通常会为导航创建一个用户控件,我可以使用SiteMap.CurrentNode和/或SiteMap.CurrentNode.IsDescendantOf将当前页面标记为“已选中”或其他任何内容。我正在寻找类似PHP的东西。在ASP经典中,我们几乎不得不使用一个包含和一堆if语句,但是一旦你获得了几个级别,你最终会得到一堆代码。我可以在每个页面的顶部创建变量,指定我们所在的“部分”,“子部分”和“页面”,但如果可能的话,我想避免这样做。

我发现this link通过查询字符串反弹,但这不是一个选项。

如果有人不熟悉web.sitemap文件,我可以在需要时更详细地解释它。

编辑 - @BrandonS的评论

我正在寻找的核心是能够定义一个代表我网站页面的文件。 ASP.Net使用XML文件,方便捕获一些潜在的错误,但不是必需的。理想情况下,我实际上喜欢使用ASP.Net使用的完全相同的文件格式,以便我可以共享代码,但仍然不是绝对必需的。

在ASP.Net中,使用上面的站点地图,我将拥有一个用户控件(基本上是一个美化的包含文件),在每个页面上输出<title>标记。在主页页面上,它只输出My Awesome Site,在关于 L2页面上输出My Awesome Site - About主板上 L3页面,它将输出My Awesome Site - About - Board。同样的想法可能用于子页面上的面包屑。 (除此之外,对于我的所有网站,网页只存在一次,因此页面上不能有两个父母。)

在每个页面请求的ASP.Net中,自动创建一个SiteMap对象。 (实际上我认为它的延迟加载意味着它实际上不会被创建,除非你尝试访问但透明地发生。)所以在任何给定的时刻我都可以在站点地图文件中存在的任何页面上使用SiteMap.CurrentNode对象。 (如果站点地图文件中不存在页面null,则返回。)从那里我可以要求SiteMap.CurrentNode.ParentNode或者我可以走SiteMap.CurrentNode.ChildNodes。我还可以获得代表站点地图文件根目录的SiteMap.RootNode。从那里我可以走SiteMap.RootNode.ChildNodes知道这些直接孩子代表我网站的2级页面。然后,我可以单独告诉这些孩子,知道每个“孙子”代表L3等等。

因此,使用上面的递归,我可以通过走根节点的子节点来定义我的网站的主要导航,如果我的导航中有下拉菜单,那么我可以走子子。在走路的孩子或孙子时,我可以根据SiteMap.CurrentNode是等于还是来自孩子或孙子的后代来设置课程。下面是VB.Net中关于如何使用站点地图构建L2导航的示例:

    ''//An array that we append potential CSS class names to such as "first" or "active"
    Dim Classes As List(Of String)

    ''//A StringBuild is just an efficient way to work with Strings
    ''//if you are not familiar with it just now that Append() is basically "&=" and AppenLine() is basically "&= ...\n"
    Dim Buf As New StringBuilder()
    Buf.AppendLine("     <ul>")

    ''//Walk the root child nodes, the N variable will be the current ChildNode of the SiteMap.RootNote
    For Each N As SiteMapNode In SiteMap.RootNode.ChildNodes

        ''//For the first and last child we want to add extra classes in case we need to adjust borders, padding, etc
        Classes = New List(Of String)
        If N.PreviousSibling Is Nothing Then
            Classes.Add("first")
        ElseIf N.NextSibling Is Nothing Then
            Classes.Add("last")
        End If

        ''//See if the page being requested is the current child or if the current page is descended from it so that we can mark it as active
        If SiteMap.CurrentNode IsNot Nothing Then
            If SiteMap.CurrentNode.Equals(N) OrElse SiteMap.CurrentNode.IsDescendantOf(N) Then
                Classes.Add("active")
            End If
        End If

        ''//This code below is just for outputting the <li class="..."><a href="...">...</a></li> code

        ''//Write the opening list tag
        Buf.Append("      <li")
        ''//If the above code created any CSS classes append the class attribute and the space-delimited list of classes
        If Classes.Count > 0 Then
            Buf.Append(" class=""" & Join(Classes.ToArray(), " ") & """")
        End If
        ''//Close the list tag
        Buf.Append(">")

        ''//Append the hyperlink. The "N" object is the current child of the SiteMap.RootNode.ChildNodes
        ''//All SiteMapNode objects have a Url property and a Title property which is defined in the XML file
        Buf.AppendFormat("<a href=""{0}"">{1}</a></li>", N.Url.Replace("/index.html", "/"), HttpUtility.HtmlEncode(N.Title))

        ''//Append a blank line, I like to keep my code formatted nicely
        Buf.AppendLine()
    Next

    ''//Append the closing list tag
    Buf.AppendLine("     </ul>")

附加说明

有些人可能会认为这有点过分,但这都是.Net的内容,这就是为什么我要问PHP是否存在某些东西。我可以自己滚动,但显然我想尽可能避免它。

2 个答案:

答案 0 :(得分:2)

嗯......据我所知,PHP中没有内置的解决方案。他们有很多框架。

例如在Zend中我们有navigation containers,它可以以您选择的任何格式存储所有数据 - 例如xml-config。然后在zend view navigation helpers的帮助下,我们可以在布局或具体页面中输出它。

作为示例,您可以看到有关它的自动翻译帖子here

答案 1 :(得分:0)

澄清我是否正确理解您的目标:您是否希望单个文件处理所有网页的标题和父母?

当然! htaccess:)

RewriteEngine on
# ROOT
RewriteRule ^me.html$           me.php?title=Home+Page [L,QSA]
# ABOUT
RewriteRule ^about/index.html$  about/index.php?parent=About&title=About [L,QSA]
RewriteRule ^about/staff.html$  about/staff.php?parent=About&title=The+Staff [L,QSA]

但是,您不能在文件系统结构中使用.html文件,因为它是静态的。文件需要在.php中,但是使用该htaccess的配置,URL将保留为.html。

网址about/index.html将查找about/index.php并将两个变量传递给它:parent和title。还需要根据您的URL目录(如index.php文件夹中的staff.php/about来组织php文件。

about/index.php文件中,您可以输出:

<?php
echo $_GET['parent'];
echo "<br />";
echo $_GET['title'];

如果我的答案不充分,请研究htaccess的更多信息,但我认为这正是您所寻找的。