如何使用 slug 查找在 CakePHP 2.x 中将旧的 URL 301 重定向到新的 URL?
How to 301 redirect old URL to new URL in CakePHP 2.x with slug lookup?
我需要像这样重定向 (301) 网址:
https://website.com/products/view/id
至:
https://website.com/products/product-name-slug
我知道如何使 slug 版本的 url 工作,但我不想完全禁用旧版本,而是希望它们 301 重定向到它的 slug 版本。
我不希望它们同时工作,因为它被 Google SEO 视为重复内容。
我也不想像这样为 routes.php 中的每个产品编写重定向:
Router::redirect( '/product/view/1001', [ 'controller' => 'products', 'action' => 'view', 'product-1001-name-slug' ] );
相反,我宁愿有动态查找功能来为我做这件事。
如何在 CakePHP 中实现 2.x?
- Create a custom route class 处理这个案例
- 检查新的 slug 字段中是否存在 slug
- 如果是,那就太好了,没什么可做的
- 如果没有尝试在旧的 slug 字段中查找 slug
- 如果它存在重定向到新的 slug 并设置 HTTP 状态
- 如果不存在return false
这是@burzum 回答的示例实现:
在routes.php中:
Router::connect(
'/product/view/:slug',
array( 'controller' => 'base_products', 'action' => 'view' ),
array( 'pass' => array( 'slug' ) )
);
Router::connect(
'/base_products/view/:id',
[ 'controller' => 'product', 'action' => 'view', 'model' => 'BaseProduct' ],
[ 'routeClass' => 'IdToSlugRoute' ]
);
在 app/Routing/Route/IdToSlugRoute.php:
public function parse($url) {
$params = parent::parse($url);
if (!$params) {
return false;
}
if (!$this->response) {
$this->response = new CakeResponse();
}
App::import('Model', $params['model']);
$Model = new $params['model']();
$instance = $Model->find('first', array(
'conditions' => array($params['model'] . '.id' => $params['id']),
'recursive' => 0
));
$slug = getSlug( $instance[$params['model']]['id'], $instance[$params['model']]['name'] );
$redirect = ['controller' => $params['controller'], 'action' => $params['action'], $slug];
$status = 301;
$this->response->header(array('Location' => Router::url($redirect, true)));
$this->response->statusCode($status);
$this->response->send();
$this->_stop();
}
在 app/Controller/BaseProductsController.php:
function view($slug)
{
$id = getIdFromSlug($slug);
$product = $this->BaseProduct->find('first', array(
'conditions' => array('BaseProduct.id' => $id),
'recursive' => 2
));
...
}
附加性:
function getIdFromSlug( $slug ) {
$pieces = explode( "-", $slug );
return $pieces[0];
}
function getSlug( $id, $name ) {
return $id . '-' . Inflector::slug($name, '-');
}
我需要像这样重定向 (301) 网址:
https://website.com/products/view/id
至:
https://website.com/products/product-name-slug
我知道如何使 slug 版本的 url 工作,但我不想完全禁用旧版本,而是希望它们 301 重定向到它的 slug 版本。 我不希望它们同时工作,因为它被 Google SEO 视为重复内容。
我也不想像这样为 routes.php 中的每个产品编写重定向:
Router::redirect( '/product/view/1001', [ 'controller' => 'products', 'action' => 'view', 'product-1001-name-slug' ] );
相反,我宁愿有动态查找功能来为我做这件事。
如何在 CakePHP 中实现 2.x?
- Create a custom route class 处理这个案例
- 检查新的 slug 字段中是否存在 slug
- 如果是,那就太好了,没什么可做的
- 如果没有尝试在旧的 slug 字段中查找 slug
- 如果它存在重定向到新的 slug 并设置 HTTP 状态
- 如果不存在return false
这是@burzum 回答的示例实现:
在routes.php中:
Router::connect(
'/product/view/:slug',
array( 'controller' => 'base_products', 'action' => 'view' ),
array( 'pass' => array( 'slug' ) )
);
Router::connect(
'/base_products/view/:id',
[ 'controller' => 'product', 'action' => 'view', 'model' => 'BaseProduct' ],
[ 'routeClass' => 'IdToSlugRoute' ]
);
在 app/Routing/Route/IdToSlugRoute.php:
public function parse($url) {
$params = parent::parse($url);
if (!$params) {
return false;
}
if (!$this->response) {
$this->response = new CakeResponse();
}
App::import('Model', $params['model']);
$Model = new $params['model']();
$instance = $Model->find('first', array(
'conditions' => array($params['model'] . '.id' => $params['id']),
'recursive' => 0
));
$slug = getSlug( $instance[$params['model']]['id'], $instance[$params['model']]['name'] );
$redirect = ['controller' => $params['controller'], 'action' => $params['action'], $slug];
$status = 301;
$this->response->header(array('Location' => Router::url($redirect, true)));
$this->response->statusCode($status);
$this->response->send();
$this->_stop();
}
在 app/Controller/BaseProductsController.php:
function view($slug)
{
$id = getIdFromSlug($slug);
$product = $this->BaseProduct->find('first', array(
'conditions' => array('BaseProduct.id' => $id),
'recursive' => 2
));
...
}
附加性:
function getIdFromSlug( $slug ) {
$pieces = explode( "-", $slug );
return $pieces[0];
}
function getSlug( $id, $name ) {
return $id . '-' . Inflector::slug($name, '-');
}