8

我正在尝试创建自己的 xml 站点地图。一切都完成了,除了我认为最简单的部分。您如何获得网站上所有页面的列表?我在 /site 文件夹和其他一些文件夹中有一堆视图。有没有办法明确地请求他们的 URL 或者通过控制器?

我不想使用扩展程序

4

5 回答 5

9

您可以使用反射来遍历所有控制器的所有方法:

Yii::import('application.controllers.*');
$urls = array();

$directory = Yii::getPathOfAlias('application.controllers');
$iterator = new DirectoryIterator($directory);
foreach ($iterator as $fileinfo)
{
    if ($fileinfo->isFile() and $fileinfo->getExtension() == 'php')
    {
        $className = substr($fileinfo->getFilename(), 0, -4); //strip extension
        $class = new ReflectionClass($className);

        foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
        {
            $methodName = $method->getName();
            //only take methods that begin with 'action', but skip actions() method
            if (strpos($methodName, 'action') === 0 and $methodName != 'actions')
            {   
                $controller = lcfirst(substr($className, 0, strrpos($className, 'Controller')));
                $action = lcfirst(substr($methodName, 6));
                $urls[] = Yii::app()->createAbsoluteUrl("$controller/$action");
            }
        }
    }
}
于 2013-03-04T13:32:29.320 回答
1

您需要知道要在 sitemap.xml 中包含哪些内容,我真的不认为您想在 sitemap.xml 中包含所有页面,或者您真的想要包含类似 site.com/article/edit 的内容/1 ?

也就是说,您可能只想要view控制器中操作的结果。事实是,您需要知道要索引的内容。

不要考虑控制器/操作/视图,而是考虑系统中您想要索引的资源,无论是文章还是页面,它们都在您的数据库中或以某种方式存储,因此您可以列出它们,并且它们有一个标识它们的 URI,获取 URI 是调用几个函数的问题。

于 2013-01-14T15:06:02.097 回答
1

有两种可能——

情况1:

您正在运行一个静态网站,然后您可以在 1 个文件夹中找到所有 HTML - protected/views/site/pages http://www.yiiframework.com/wiki/22/how-to-display-static-pages-in- yii/

案例二:

网站是动态的。生成和重新生成站点地图等任务可以归类为后台任务。

运行后台任务可以通过在 linux 中使用 - WGETGETlynx命令模拟浏览器来实现

或者,您可以将 CronController 创建为CConsoleCommand。如何在 YII 中使用命令显示在下面的链接中 - http://tariffstreet.com/yii/2012/04/implementing-cron-jobs-with-yii-and-cconsolecommand/

站点地图是一种 XML,它列出了您网站的 URL。但它的作用不止于此。它可以帮助您可视化网站的结构,您可能有

  • 类别
  • 子类别。

在进行有用的扩展时,可以在设计之前考虑以上几点。

像Wordpress这样的框架提供了生成分类站点地图的方法。因此,每个页面的元数据都是从之前存储的,并使用它发现和分组页面的元数据。

@Pavle建议的反射解决方案很好,应该是要走的路。考虑可能存在部分视图,您可能希望也可能不希望将它们列为单独的链接。

因此,您想为创建扩展付出多少努力也取决于其中一些。

您可以要求用户列出 config fie 中的所有变量并从那里开始,这还不错,或者您必须使用反射解析页面等技术对页面和列表进行分组并查找regex

例如 - 基于模块名称,您可以先将它们分组,模块内的控制器可以形成子组。

于 2013-03-04T14:49:55.250 回答
1

第一种方法可能是遍历视图文件,但是您必须考虑到在某些情况下,视图不是页面目标,而是通过 usingCController::renderPartial()方法包含在另一个页面中的页面部分。通过探索 CController 的 Class Reference,我发现了这个CController::actions()方法。

所以,我还没有找到任何Yii 方法来迭代 CController 的所有操作,但我使用 php 在我的一个项目中迭代 SiteController 的所有方法,并使用前缀“action”将它们过滤到这些方法,这是我的动作前缀,这是示例

class SiteController extends Controller{
    public function actionTest(){
        echo '<h1>Test Page!</h1></p>';
        $methods = get_class_methods(get_class($this));
        // The action prefix is strlen('action') = 6
        $actionPrefix = 'action';
        $reversedActionPrefix = strrev($actionPrefix);
        $actionPrefixLength = strlen($actionPrefix);
        foreach ($methods as $index=>$methodName){
            //Always unset actions(), since it is not a controller action itself and it has the prefix 'action'
            if ($methodName==='actions') {
                unset($methods[$index]);
                continue;
            }
            $reversedMethod = strrev($methodName);
            /* if the last 6 characters of the reversed substring === 'noitca', 
             * it means that $method Name corresponds to a Controller Action,
             * otherwise it is an inherited method and must be unset.
             */
            if (substr($reversedMethod, -$actionPrefixLength)!==$reversedActionPrefix){
                unset($methods[$index]);
            } else $methods[$index] = strrev(str_replace($reversedActionPrefix, '', $reversedMethod,$replace=1));
        }
        echo 'Actions '.CHtml::listBox('methods', NULL, $methods);
    }
    ...
}

我得到的输出是..

ListBox 中的所有动作!

我确信它可以进一步完善,但这种方法应该适用于你拥有的任何控制器......

所以你要做的是:

对于每个Controller:过滤掉该类的所有非动作方法,使用上述方法。您可以构建一个关联数组,例如

array(
    'controllerName1'=>array(
        'action1_1',
        'action1_2'),
    'controllerName2'=>array(
        'action2_1',
        'action2_2'),
);

为此,我会在我的 SiteController 中添加一个静态方法 getAllActions()。

get_class_methodsget_classstrrevstrlen都是 PHP 函数。

于 2013-03-04T16:14:27.667 回答
1

根据您的问题: 1. 您如何获得网站上所有页面的列表?

基于 Yii 的 module/controller/action/action_params 的方式,你需要为 SEO 构建一个站点地图。

  1. 由于您的操作参数无限变化,因此很难自动解析以获取所有网址。虽然您可以简单地获得由 Pavle Predic 构建的控制器/动作。当您为 SEO 定制 (SERF) URL 规则时,复杂性就会出现。

下一个最佳解决方案是拥有一个内容数据库,并且您知道如何通过 url 规则获取每个内容,然后是一个 cron 控制台作业来创建所有要保存为 sitemap.xml 的 url。

希望这可以帮助!

于 2013-03-08T07:44:22.860 回答