这是我最初的问题SilverStripe 3.1+动态创建页面重定向的扩展
我有一个产品页面URLa) www.mysite.com/category/subcat/productid您可以通过单独的重定向器页面访问此页面b) www.mysite.com/production
页面"a"有选项卡,可以通过c) www.mysite.com/category/subcat/productid/tabid
我想使用PHP为创建的每个产品页面动态创建链接/重定向程序,这样它就可以被访问:
1) 一个只使用"b"中显示的"预测"的短URL(我可以通过创建页面重定向器来做到这一点,但对于大量产品来说,这是冗长的。2) 为每个选项卡链接创建一个简短的URL,因此"c"将从以下位置重定向:d)www.mysite.com/production/tabid
"tabid"可以是硬编码的,在我的情况下是:音频、视频、图片、固件
当前正在使用我的ProductPage.php 中的代码
class ProductPage_Controller extends Page_Controller {
private static $allowed_actions = array(
'audio',
'pictures',
'firmware',
'videos',
);
public function audio() {
$this->redirect($this->Link().'?tab=audio');
}
public function pictures() {
$this->redirect($this->Link().'?tab=pictures');
}
public function firmware() {
$this->redirect($this->Link().'?tab=firmware');
}
public function videos() {
$this->redirect($this->Link().'?tab=videos');
}
允许我从/视频转到/?tab=视频,但这当然不会缩短URL,这是我想要的最终结果。这可能是在RedirectorPage.php的扩展中完成的吗?
实现这一点的一种方法是在调用404错误时使用onBeforeHTTPError404
挂接,并重定向找到的任何产品。
我们创建了一个带有onBeforeHTTPError404
函数的ProductRedirectExtension
。当找不到页面时,但在系统返回404错误之前,将调用此函数。这里的代码将检查是否存在ProductPage
和带有用户URL字符串第一部分的URLSegment
。如果找到了ProductPage
,那么我们检查用户URL字符串的第二部分是否是选项卡关键字之一。之后,用户被重定向到该页面。
ProductRedirectExtension.php
class ProductRedirectExtension extends Extension {
public function onBeforeHTTPError404( $request ) {
$urlSegment = $request->param('URLSegment');
$action = strtolower($request->param('Action'));
$page = ProductPage::get()->filter('URLSegment', $urlSegment)->first();
if ($page) {
$link = $page->Link();
if ($action == 'audio' || $action == 'pictures' || $action == 'firmware' || $action == 'videos') {
$link .= '?tab=' . $action;
}
$response = new SS_HTTPResponse();
$response->redirect($link, 301);
throw new SS_HTTPResponse_Exception($response);
}
}
}
我们使用以下配置设置启用此扩展。
config.yml
RequestHandler:
extensions:
- ProductRedirectExtension
ContentController:
extensions:
- ProductRedirectExtension
ModelAsController:
extensions:
- ProductRedirectExtension
你能走的最短的是www.mysite.com/product/productid/tabid
。没有product
部分也可以做到这一点,但这会让你的生活变得更加艰难,因为你必须经历很多麻烦才能访问Admin
和Dev
如果你想要最短的URL,你应该制作一个新的页面,因为你当前的ProductPage
是另一个页面的子页面,从你的URL告诉:
www.mysite.com/category/subcat/productid
您可以使用以下代码实现最佳场景:
class ProductRedirectPage_Controller extends Page_Controller
{
private static $allowed_actions = [
'Product'
];
private static $url_handlers = [
'$ID/$TabID' => 'Product'
];
public function Product()
{
// Get your ProductPage, this should work if there is only one ProductPage
$page = ProductPage::get()->first();
if(! $productId = $this->request->param('ID'))
return $this->redirect($page->Link()); // or send them somewhere else
$tabId = $this->request->param('TabID');
$link = $page->Link('yourAction/' . $productId . '/' . $tabId);
return $this->redirect($link);
}
}
编辑
有了这个代码,当访问
www.mysite.com/product/productid/tabid
时,它会将您重定向到ProductPage
所在的位置。也许您希望将/$tabId
更改为?tabId=' . $tabId
,但这完全取决于您。所以,如果我要总结,你希望newpage/video打开正确的页面选项卡,而不是呈现不同页面的操作?
您可以用private static $url_handlers
做一些奇怪的事情,设置一个可以通过$request->param("ing")查询的参数。
或者,您可以设置handleAction来测试$action是否是列表中的内容之一(并设置标志以供稍后在例如模板中使用),或者是否为parent::handleAction。
这个答案并不是非常充实,但希望能为您自己的用例提供一些关于调查方向的想法。