我正在尝试创建自己的 xml 站点地图。一切都完成了,除了我认为最简单的部分。您如何获得网站上所有页面的列表?我在 /site 文件夹和其他一些文件夹中有一堆视图。有没有办法明确地请求他们的 URL 或者通过控制器?
我不想使用扩展程序
您可以使用反射来遍历所有控制器的所有方法:
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");
}
}
}
}
您需要知道要在 sitemap.xml 中包含哪些内容,我真的不认为您想在 sitemap.xml 中包含所有页面,或者您真的想要包含类似 site.com/article/edit 的内容/1 ?
也就是说,您可能只想要view
控制器中操作的结果。事实是,您需要知道要索引的内容。
不要考虑控制器/操作/视图,而是考虑系统中您想要索引的资源,无论是文章还是页面,它们都在您的数据库中或以某种方式存储,因此您可以列出它们,并且它们有一个标识它们的 URI,获取 URI 是调用几个函数的问题。
有两种可能——
您正在运行一个静态网站,然后您可以在 1 个文件夹中找到所有 HTML - protected/views/site/pages http://www.yiiframework.com/wiki/22/how-to-display-static-pages-in- yii/
网站是动态的。生成和重新生成站点地图等任务可以归类为后台任务。
运行后台任务可以通过在 linux 中使用 - WGET、GET或lynx命令模拟浏览器来实现
或者,您可以将 CronController 创建为CConsoleCommand。如何在 YII 中使用命令显示在下面的链接中 - http://tariffstreet.com/yii/2012/04/implementing-cron-jobs-with-yii-and-cconsolecommand/
站点地图是一种 XML,它列出了您网站的 URL。但它的作用不止于此。它可以帮助您可视化网站的结构,您可能有
在进行有用的扩展时,可以在设计之前考虑以上几点。
像Wordpress这样的框架提供了生成分类站点地图的方法。因此,每个页面的元数据都是从之前存储的,并使用它发现和分组页面的元数据。
@Pavle建议的反射解决方案很好,应该是要走的路。考虑可能存在部分视图,您可能希望也可能不希望将它们列为单独的链接。
因此,您想为创建扩展付出多少努力也取决于其中一些。
您可以要求用户列出 config fie 中的所有变量并从那里开始,这还不错,或者您必须使用反射和解析页面等技术对页面和列表进行分组并查找regex。
例如 - 基于模块名称,您可以先将它们分组,模块内的控制器可以形成子组。
第一种方法可能是遍历视图文件,但是您必须考虑到在某些情况下,视图不是页面目标,而是通过 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);
}
...
}
我得到的输出是..
我确信它可以进一步完善,但这种方法应该适用于你拥有的任何控制器......
所以你要做的是:
对于每个Controller:过滤掉该类的所有非动作方法,使用上述方法。您可以构建一个关联数组,例如
array(
'controllerName1'=>array(
'action1_1',
'action1_2'),
'controllerName2'=>array(
'action2_1',
'action2_2'),
);
为此,我会在我的 SiteController 中添加一个静态方法 getAllActions()。
get_class_methods、get_class、strrev和strlen都是 PHP 函数。
根据您的问题: 1. 您如何获得网站上所有页面的列表?
基于 Yii 的 module/controller/action/action_params 的方式,你需要为 SEO 构建一个站点地图。
下一个最佳解决方案是拥有一个内容数据库,并且您知道如何通过 url 规则获取每个内容,然后是一个 cron 控制台作业来创建所有要保存为 sitemap.xml 的 url。
希望这可以帮助!