- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想从我的 opencart 网上商店重写我的产品 url。 Opencart 本身有一个非常糟糕的 seo 实现。我已经更新了 seo 实现,以便能够对多个类别使用相同的关键字,请参阅:Opencart duplicate URL keywords但这仅适用于类别。对于我认为的产品,我只需要一个 htaccess 重写规则。
原始网址如下所示:
http://domain.com/index.php?route=product/product&path=25_28_93&product_id=1759
我的网址现在看起来像这样:
http://domain.com/In-Stock/Retreaded-Tires/Agricultural?product_id=1759
如您所见,类别确实已经发生了变化。
我希望它是这样的:
http://domain.com/In-Stock/Retreaded-Tires/Agricultural/1759/1050-50R32-Mega-X-Bib
然后为了分页(在一个类别中)我有这个 url:
http://domain.com/index.php?route=product/category&path=36_70_67&page=2
我已经把它变成了:
http://domain.com/Tire-Retreading/Equalizing/&page=2
但我希望这样
http://domain.com/Tire-Retreading/Equalizing/2
我的 htaccess 文件如下所示:
Options +FollowSymlinks
Options -Indexes
<FilesMatch "(?i)((\.tpl|\.ini|\.log|(?<!robots)\.txt))">
Order deny,allow
Deny from all
</FilesMatch>
RewriteEngine On
RewriteBase /
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteRule ^download/(.*) /index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
我的 seo_url.php 文件稍作改动,如下所示:
public function index() {
$this->load->model('catalog/category');
// Add rewrite to url class
if ($this->config->get('config_seo_url')) {
$this->url->addRewrite($this);
}
// Decode URL
if (isset($this->request->get['_route_'])) {
$parts = explode('/', $this->request->get['_route_']);
// remove any empty arrays from trailing
if (utf8_strlen(end($parts)) == 0) {
array_pop($parts);
}
$categories = array();
for ($i = 0; $i < count($parts); $i++) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE keyword = '" . $this->db->escape($parts[$i]) . "'");
if ($query->num_rows) {
$url = explode('=', $query->row['query']);
if ($url[0] == 'product_id') {
$this->request->get['product_id'] = $url[1];
}
if ($url[0] == 'category_id') {
$categories[$i] = $this->model_catalog_category->getCategory($url[1]);
if (!isset($this->request->get['path'])) {
$this->request->get['path'] = $categories[$i]['category_id'];
} else {
foreach ($query->rows as $row) {
$url = explode('=', $row['query']);
$category_id = $url[1];
$category = $this->model_catalog_category->getCategory($category_id);
if ($category['parent_id'] == $categories[$i - 1]['category_id']) {
$this->request->get['path'] .= '_' . $category['category_id'];
}
}
}
}
if ($url[0] == 'manufacturer_id') {
$this->request->get['manufacturer_id'] = $url[1];
}
if ($url[0] == 'information_id') {
$this->request->get['information_id'] = $url[1];
}
if ($query->row['query'] && $url[0] != 'information_id' && $url[0] != 'manufacturer_id' && $url[0] != 'category_id' && $url[0] != 'product_id') {
$this->request->get['route'] = $query->row['query'];
}
} else {
$this->request->get['route'] = 'error/not_found';
break;
}
}
if (!isset($this->request->get['route'])) {
if (isset($this->request->get['product_id'])) {
$this->request->get['route'] = 'product/product';
} elseif (isset($this->request->get['path'])) {
$this->request->get['route'] = 'product/category';
} elseif (isset($this->request->get['manufacturer_id'])) {
$this->request->get['route'] = 'product/manufacturer/info';
} elseif (isset($this->request->get['information_id'])) {
$this->request->get['route'] = 'information/information';
}
}
if (isset($this->request->get['route'])) {
return new Action($this->request->get['route']);
}
}
}
public function rewrite($link) {
$url_info = parse_url(str_replace('&', '&', $link));
$url = '';
$data = array();
parse_str($url_info['query'], $data);
foreach ($data as $key => $value) {
if (isset($data['route'])) {
if (($data['route'] == 'product/product' && $key == 'product_id') || (($data['route'] == 'product/manufacturer/info' || $data['route'] == 'product/product') && $key == 'manufacturer_id') || ($data['route'] == 'information/information' && $key == 'information_id')) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($key . '=' . (int)$value) . "'");
if ($query->num_rows && $query->row['keyword']) {
$url .= '/' . $query->row['keyword'];
unset($data[$key]);
}
} elseif ($key == 'path') {
$categories = explode('_', $value);
foreach ($categories as $category) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = 'category_id=" . (int)$category . "'");
if ($query->num_rows && $query->row['keyword']) {
$url .= '/' . $query->row['keyword'];
} else {
$url = '';
break;
}
}
unset($data[$key]);
} else {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" .$data['route'] . "'");
if ($query->num_rows && $query->row['keyword']) {
$url .= '/' . $query->row['keyword'];
unset($data[$key]);
}
}
}
}
if ($url) {
unset($data['route']);
$query = '';
if ($data) {
foreach ($data as $key => $value) {
$query .= '&' . rawurlencode((string)$key) . '=' . rawurlencode((string)$value);
}
if ($query) {
$query = '?' . str_replace('&', '&', trim($query, '&'));
}
}
return $url_info['scheme'] . '://' . $url_info['host'] . (isset($url_info['port']) ? ':' . $url_info['port'] : '') . str_replace('/index.php', '', $url_info['path']) . $url . $query;
} else {
return $link;
}
}
分页代码是这样的:
class Pagination {
public $total = 0;
public $page = 1;
public $limit = 20;
public $num_links = 8;
public $url = '';
public $text_first = '|<';
public $text_last = '>|';
public $text_next = '>';
public $text_prev = '<';
public function render() {
$total = $this->total;
if ($this->page < 1) {
$page = 1;
} else {
$page = $this->page;
}
if (!(int)$this->limit) {
$limit = 10;
} else {
$limit = $this->limit;
}
$num_links = $this->num_links;
$num_pages = ceil($total / $limit);
$this->url = str_replace('%7Bpage%7D', '{page}', $this->url);
$output = '<ul class="pagination">';
if ($page > 1) {
$output .= '<li><a href="' . str_replace('{page}', 1, $this->url) . '">' . $this->text_first . '</a></li>';
$output .= '<li><a href="' . str_replace('{page}', $page - 1, $this->url) . '">' . $this->text_prev . '</a></li>';
}
if ($num_pages > 1) {
if ($num_pages <= $num_links) {
$start = 1;
$end = $num_pages;
} else {
$start = $page - floor($num_links / 2);
$end = $page + floor($num_links / 2);
if ($start < 1) {
$end += abs($start) + 1;
$start = 1;
}
if ($end > $num_pages) {
$start -= ($end - $num_pages);
$end = $num_pages;
}
}
for ($i = $start; $i <= $end; $i++) {
if ($page == $i) {
$output .= '<li class="active"><span>' . $i . '</span></li>';
} else {
$output .= '<li><a href="' . str_replace('{page}', $i, $this->url) . '">' . $i . '</a></li>';
}
}
}
if ($page < $num_pages) {
$output .= '<li><a href="' . str_replace('{page}', $page + 1, $this->url) . '">' . $this->text_next . '</a></li>';
$output .= '<li><a href="' . str_replace('{page}', $num_pages, $this->url) . '">' . $this->text_last . '</a></li>';
}
$output .= '</ul>';
if ($num_pages > 1) {
return $output;
} else {
return '';
}
}
}
编辑:
我的所有页面都重定向到 http://domain.com/index.php从那里它决定使用路由参数的目录/文件。所以 route=product/product
告诉我们去目录 product 中的 product.php
。目录 product 还包含 categories.php
,它通向一条路线:route=product/category
字符串中的 Path 变量表示类别的 ID。在我的示例中,25
代表 In-Stock
。而 25_28
代表 In-Stock/Retreaded-Tires
等。
product_id
变量表示产品的相应 ID。
page 变量表示分页,用于类别中的产品列表。这个列表可以有一个可变的长度,因为它计算一个类别中有多少产品以及他应该在一页上显示多少。所以如果原始 url 有 &page=2
和路由 route=product/category
它应该像这样制作一个 url:http://domain.com/轮胎翻新/均衡/2
最佳答案
我仍然觉得添加的解释令人困惑,而且在我看来您不太了解 URL 重写的工作原理,所以我将尝试解释一些 URL 重写基础知识。
您可以通过 URL 重写将(向用户显示的 URL 的)翻译“漂亮”URL 段成您的实际的、长的段、“不漂亮”的 URL(使用变量来提供某些内容)。为此,您可以使用正则表达式来匹配漂亮的片段,然后将预定义值或那些匹配的值提供给您的 php 变量。
因此,您首先要做的是弄清楚您漂亮的 URL 应该是什么样子,以及它们的各个部分如何转化为您的变量。 (尽管您当然也可以使用任意数量的新变量,然后您可以转换这些变量的值并将其分配给 php 脚本中已经存在或预定义的变量。)
你举了这个例子: http://example.com/Tire-Retreading/Equalizing/2
此 URL 似乎由您要转换为变量的三个部分组成:
轮胎翻新
(可变路线
)均衡
(可变路径
)2
(变量页面
)您必须构建您的 RegEx 以根据各个段的所有可能拼写方式匹配您的段,包括允许的任何特殊字符等。完成后,您可以将匹配的值传递给您的变量使用反向引用(或者您可以定义您自己的值以供您的变量使用)。
使用反向引用,你可以这样使用:
RewriteRule ^([A-Za-z-]+)/([A-Za-z-]+)/([0-9]+)$ index.php?route=$1&path=$2&page=$3 [NC,L]
您必须将用于段匹配的单个 RegEx(如 [A-Za-z-]+
)放在圆括号中,以便能够将结果分配给您的 php 变量$1
, $2
等形式
根据是否还应允许用户浏览您的产品/类别或路径的“概览”页面,您可能必须从可能的最小“漂亮”URL 开始重写到最长的 URL。
例如
RewriteRule ^([A-Za-z-]+)$ $1/ [NC,R]
RewriteRule ^([A-Za-z-]+)/$ index.php?route=$1 [NC,L]
RewriteRule ^([A-Za-z-]+)/([A-Za-z-]+)$ $1/$2/ [NC,R]
RewriteRule ^([A-Za-z-]+)/([A-Za-z-]+)/$ index.php?route=$1&path=$2 [NC,L]
RewriteRule ^([A-Za-z-]+)/([A-Za-z-]+)/([0-9]+)$ $1/$2/$3/ [NC,R]
RewriteRule ^([A-Za-z-]+)/([A-Za-z-]+)/([0-9]+)/$ index.php?route=$1&path=$2&page=$3 [NC,L]
域本身的重写在所有“路径”重写之前进行。
您还必须弄清楚需要使用哪些标志(末尾方括号中的部分),这意味着您必须继续阅读 URL rewriting更详细。在上面的示例中,用户键入的所有不以斜杠结尾的 URL 都会自动重定向(这就是方括号中的 R
所代表的含义)到相同的 URL,但添加了斜杠。因此,http://example.com/blah
将重定向到 http://example.com/blah/
等
根据您提供的信息,您的 URL 将以两个可能的部分之一开头:
http://example.com/In-Stock/...
对比
http://example.com/Product-or-Category/....
因此,您必须格外小心,不要混淆这两者。如果 In-Stock
被汇集到它自己的变量中并且总是拼写完全一样,您可能希望让您的第一个规则处理它并仅在以后使用 RegEx 来匹配产品/类别(所有重写规则都按时间顺序处理,一个接一个)。
希望对您有所帮助。
关于php - URL 重写 OpenCart 产品 SEO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33278642/
我需要按不同类别过滤我网站上的产品。例如,如果您选择“DRINKS”类别,它将向我显示属于该类别的产品。 为了更好地解释自己。 我需要按类别过滤我网站的出版物 [产品],例如,在选择一个类别时说“饮料
我有 orders 集合,其中包含 products 集合。我将一些产品 ID 作为列表传递给该方法。我需要返回与任何匹配的产品列表input 列表中的 id。 我需要像这样使用 foreach 循环
我已经为临时分发进行存档好几个月了,但今天突然我无法这样做,因为“存档”菜单项已被禁用。我没有改变任何东西。我完成了该项目的配置设置,看起来没问题。 我的临时个人资料即将在 14 天后过期。这可能是问
我正在尝试找出产品和产品属性之间的关系。我有一个 product 表和一个 product_attributes 表。产品可以具有多种属性。我需要查询来查找具有一个特定属性和另一个属性之一的所有产品。
我正在使用 MySQL Workbench 创建 EER 图。 实现产品、类别和公司表之间关系的最佳方式是什么? 我正在考虑这种关系,但考虑到我想让公司的客户管理自己的产品/类别,这是最好的方式吗?如
我正在使用 itertools 包,并尝试在具有 900 个值的数组中创建 1、2 和 3 的所有可能组合,然后将其转换为 30 x 30 矩阵。我必须执行此操作的代码在下面并且工作正常。 for d
我有几个关于 Cartridge 启动器的问题: 我的产品不需要评级或发布日期。他们永远不会出售。一些产品是可下载的,因此“num_in_stock”不相关或本质上是无限制的。没有颜色选项,只有尺寸。
在 MySQL 中,存储产品价格(或一般货币)的首选列类型是什么?谷歌知道我经常使用 DECIMAL of FLOAT,但我想知道哪个更好。 我存储的价格范围是 0.01 到 25.00。当然更高的值
在软件开发过程中,尤其是在准备将新功能或修复后的版本上线之前,进行详尽的自测和上线前检查是至关重要的。以下是一个从多个维度综合考量的上线升级检查清单(Checklist),旨在帮助团队确保软件质量、稳
我正在创建一个闪购网站,并且我已经在主页和商店页面上根据日期范围显示产品。但我也想根据其他地方的日期范围显示产品,因此使用简码。 这是我的代码: function testt($meta_query)
可以在 WooCommerce 上批量创建产品吗?我正在使用 wp-cli Product 命令,但似乎我必须一个一个地创建。 'My product 1'), array('title'
我有一个带有数量和价格列的 excel 文件,我用它来为插件 WooCommerce Dynamic Pricing 创建必要的输出的定价规则。 我几乎想通了,但是 WooCommerce 进口商正在
我刚刚继承了一个woocommerce项目,我需要将主页更改为仅显示特定品牌。他们设置了 Product-Data => Attribute => pa_brand。 如果我打印 pa_brand 数
在插件中如何使用 wc_get_products() 获取产品。或者有其他方法可以做到吗? if ( in_array( 'woocommerce/woocommerce.php', apply_fi
我正在做一个无法从公司网络外部访问的内部网,他们希望在 Plone 中显示一些关于文件下载和最常查看的页面的不错的统计数据。 由于网络限制,我无法使用谷歌分析或任何类型的外部服务,那么是否有任何产品可
我正在就以下问题寻求建议: 保留哪些产品 key 属于哪个客户端的列表。例如,如果我的产品 key 为 8456-7894-4567-7894,则应该这样设计,以便将列表写入数据库而不是文件。 如何将
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
尝试将产品搜索栏添加到 Wordpress 管理栏后端,以进行 Woocommerce 产品搜索。它将位于后端管理菜单栏的顶部,这样无论您在后端的哪个位置,都可以搜索 woo 的产品。我很接近但在小绊
这让我抓狂.. 我正在尝试根据特定属性查询和输出 WooCommerce 产品。例如,我设置了一个名为 on 的属性,可能的值为 yes或 no . 我使用以下查询: $args = array(
我正在尝试从 Shopify 商店获取所有产品的 JSON。我一直在向 {STORE URL}/products.json 端点。但这最终只显示了商店提供的部分产品(很多,但不是全部)。当我将参数更改
我是一名优秀的程序员,十分优秀!