SilverStripe 3.1+使用PHP动态更改重定向器的URL段


SilverStripe 3.1+ Using PHP to dynamically change the URL slug of a Redirector

这是我最初的问题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部分也可以做到这一点,但这会让你的生活变得更加艰难,因为你必须经历很多麻烦才能访问AdminDev
如果你想要最短的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。

这个答案并不是非常充实,但希望能为您自己的用例提供一些关于调查方向的想法。