Rewrite condition to remove specific parameter in Prestashop - .htaccess

I have around 1000 categories created in prestashop and I have SPSEARCHPRO module installed. This module enables me to live search though my products.
Live search doesn't work due to the high number of categories but if I search normally it doesn't work either because the cat_id are included in the link and the link is too long. I suppose that's why the live search doesn't work either.
Here is what I'm trying to do:
I have this link:
https://example.com/en/module/spsearchpro/catesearch?fc=module&module=spsearchpro&controller=catesearch&orderby=name&orderway=desc&cat_id=2%2C4%2C(etc etc etc etc etc)
how can I remove the cat_id parameter from the link because the value is too long, it includes all the category id's.
I'm on prestashop 1.6.1.9 with multistore enabled (I don't know if that matters).

Putting this early in your .htaccess should cut out the unwanted parameter when the path ends with the category search slug, you may need to add other slugs to that if there are more affected pages.
RewriteCond %{QUERY_STRING} ^(.*?&)?cat_id=(?>[^&]*)(?:&(.*))?$
RewriteRule ^.*/catesearch$ /$0?%1%2 [NS,DPI,PT]
You may have to use L,R instead of DPI,PT flags if PrestaShop doesn't trust the $_GET it starts with (which comes from the rewritten URL). I'm unsure because it looks like it re-parses the URL from $_SERVER['REQUEST_URI'] which is unchanged by rewriting and would overwrite the corrected parameters with the original undesired ones. It may be the only way to make it work is an external redirect.

Related

.htaccess: redirect specific link to another?

I have these three links:
localhost/my_projects/my_website.php
localhost/my_projects/my_website.html
localhost/my_projects/my_website
The paths of the php and html files are as follows:
C:\xampp\htdocs\my_projects\my_website.php
C:\xampp\htdocs\my_projects\my_website.html
The link without an extension is "artificial" and I want to use said link:
localhost/my_projects/my_website
to get the contents of either of these links:
localhost/my_projects/my_website.php
localhost/my_projects/my_website.html
The reason for the two example files, instead of just one, is that I want to be able to switch between those two files when I edit the htaccess file. Obviously I only want to access one of those files at a time.
What do I need to have in my .htaccess file inside the my_projects folder to accomplish that? How can I make one specific link redirect to another specific link?
After reading your comment clarifying your folder structure I corrected the RewriteRule. (By the way, it would be best if you add that info to the question itself instead of in comments).
The url you want to target is: http://localhost/my_projects/my_website
http:// is the protocol
localhost is your domain (it could also be 127.0.0.1 or a domian name like www.example.com in the Internet)
I assume you are running Apache on port 80, otherwise in the url you need to also specify the port. For port 8086 for example it would be http://localhost:8086/my_projects/my_website.
The real path is htdocs/my_projects/my_website.php or htdocs/my_projects/my_website.html depending on your needs (obviously both won't work at the same time).
Here the my_projects in the "fake" url collides with the real folder "my_projects" so Apache will go for the folder and see there is no my_website (with no extension) document there (it won't reach the rewrite rules).
There is a question in SO that provides a work around for this, but it is not a perfect solution, it has edge cases where the url will still fail or make other urls fail. I had posted it yesterday, but I seem not to find it now.
The simple solution if you have the flexibility for doing it is to change the "fake" url for it not to collide with the real path.
One option is for example to replace the underscores with hyphens.
Then you would access the page as http://localhost/my-projects/my-website if you want to keep a sort of "fake" folder structure in the url. Otherwise you could simply use http://localhost/my-website.
Here are both alternatives:
# This is for the directory not to be shown. You can remove it if you don't mind that happening.
Options -Indexes
RewriteEngine On
#Rule for http://localhost/my-projects/my-website
RewriteRule ^my-projects/my-website(.+)?$ my_projects/my_website.php$1 [NC,L]
#Rule for http://localhost/my-website
RewriteRule ^my-website(.+)?$ my_projects/my_website.php$1 [NC,L]
(Don't use both, just choose one of these two, or use them to adapt it to your needs)
The first part the rewrite rule is the regular expression for your "fake" url, the second part is the relative path of your real folder structure upto the page you want to show.
In the regular expression we capture whatever what we assume to be possible query parameters after .../my_website, and paste it after my_website.php in the second part of the rule (the $1).
Later on if you want to point the url to my_website.html, you have to change the second part of the rule, where it says .php, replace it by .html.
By the way, it is perfectly valid and you'll see it in most SEO friendly web sites to write an url as http://www.somesite.com/some-page-locator, and have a rewrite rule that translates that url to a page on the website, which is what I had written in my first answer.

.htaccess dynamic links rewrite engine

I need your help creating some links using mod_rewrite.
I have some pages like:
register.php
login.php
And have the code for them:
RewriteRule ^register/?$ register.php [NC,L]
RewriteRule ^login/?$ login.php [NC,L]
My problem is with "dynamic" links I have since I can't get them working.
For exemple I have links like:
index.php?id=news
índex.php?id=news&article=2
How can I transform those links into:
/news/
/news/article_name
And I have some products (that could have the same name in the same category) but with different ID's like:
índex.php?id=products&p=30
How can I change it to
/products/product-name
After this, is it possible to "generate" an unique name? Since I would like not set in the link the unique ID like products/45342/product-name?
What are the changes I need to make to my code to work with those links?
For example I have links like:
To clarify, you must first change the links in your application to be of the form /news/ or /news/article_name (but see below). You then rewrite these "pretty" URLs back to the underlying filesystem path.
So, to rewrite /news/ back to index.php?id=news you can do something like:
RewriteRule ^(news)/$ index.php?id=$1 [L]
Using the $1 backreference just saves typing. Only use the NC flag if this must be a case-sensitive match, but note that this potentially creates duplicate content, so you must specify the canonical URL in some other way (eg. rel="canonical" link element). For the same reason, only make the trailing slash optional if this is a specific requirement.
However, it's not possible to rewrite /news/article_name back to index.php?id=news&article=2 (I assume that should be i, and not í, as in your question?) since the article ID (ie. 2) is not present in the source URL. You need to include the ID in the source URL (or make the article_name unique and a key in your lookup). It would be more usual to create a URL like /news/2/article_name (which is what StackOverflow does), which can be easily rewritten. The article_name in the URL is purely for users (and indirect SEO). In which case you could rewrite this like so:
RewriteRule ^(news)/(\d+)/ index.php?id=$1&article=$2 [L]
This will rewrite /news/N/<anything> to /index.php?id=news&article=N (where N is 1 or more digits).
However, since it rewrites <anything> you should also implement a redirect in your application when the non-canonical article_name is accessed. (Which again, is what StackOverflow does.)
And I have some products (that could have the same name in the same category) but with different ID's like: índex.php?id=products&p=30
How can I change it to /products/product-name
The same principle as mentioned above applies here also.
After this, is possible to "generate" an unique name?
You can generate this "unique name" in your application, not .htaccess. Build you URLs in your application etc.
Since I would like not set in the link the unique ID like "products/45342/product-name" ?
As mentioned above, either your product-name is unique, and behaves like your id. Or you incorporate the unique ID in the URL - this is the far more common approach, offers greatest flexibility and is less prone to error. A "short" URL like /products/45342 will redirect you to the correct canonical URL.

howto rewrite engine rule

i'm trying to understand some rules or rewrite engine but i can't figure how to do it.
i have this link:
w**.example.com/index.php?city=new+york
and i wish to rewrite to this new:
w**.example.com/good-parties-in-new-york
the value of city can change to any other city.
but the point here is I only what to rewrite if all the key is:
index.php?city=
because the
index.php?zone=
is used for other things, etc...
any suggestion? thanks.
I'm a little confused on what exactly you want to achieve. URL rewriting is normally done to make URLs look nicer, not the other way around.
You would typically want to have a nice URL like this (which you'd communicate to your users):
w**.example.com/good-parties-in-new-york
act as an "alias" for a not-so-nice looking URL like this (= the actual page being served, unbeknownst to the users):
w**.example.com/index.php?city=new+york
With Rewrite, you can backreference regular expressions. In this case, you could convert parts of the "nice" URL into RegEx's which you would then backreference with variables in the query string of the page working in the background.
E.g.:
RewriteEngine On
RewriteBase /
RewriteRule ^good-parties-in-([a-z]+)-([a-z]+)$ index.php?city=$1+$2 [NC,L]
The first RegEx (([a-z]+)) is referenced as $1, the second as $2 (and so on).
Note that this example will only work for city names consisting of two words, like New York, San Francisco etc. You'll have to figure out of how many words city names can consist of and rewrite your code accordingly. (You might also have to set different flags.)
Plus, you should make sure that your php script checks against existing city names and throws an appropriate error/gives out a warning if users enter fantasy names like good-parties-in-magical-rainbow-city or similar.
If this isn't what you're looking for, maybe you could clarify your question?

Is it possible with canonical URL for this pattern in htaccess: /a/*/id/uniqueid?

A big problem is that I am not a programmer….! So I need to solve this with means within my own competence… I would be very happy for help!
I have an issue with a lot of duplicated URLs in the Google index and there are strong signs that it is causing SEO problems.
I don’t have duplicate links on the site itself, but as it once was set-up, for certain pages the system allows all sorts of variations in the URL. As long as is it has a specific article-id, the same content will be presented under an infinite number of URLs.
I guess the duplicates in Google's index has been growing over long time and is due to links gone wrong from other sites that links to mine. The problem is that the system have accepted the variations.
Here are examples of variations that exists in the Google index:
site.com/a/Cow_Cat/id/5272
site.com/a/cow_cat/id/5272
site.com/a/cow…cat/id/5272
site.com/a/cowcat/id/5272
site.com/a/bird/id/5272
The first URL with mixed case is the one used site-wide and for now I have to live with it, it would take too long time to make a change to all lower case. I cannot make a manual effort via htaccess as it is a total of 300.000 articles. I believe there are 10 ‘s of thousands that have one or more duplicates.
My question is this:
Is it possible to create rules for canonical URLs in htaccess in order to make the above URLs to be handled as one as well as for the rest of the 300.000?
I e, is there a way to say that all URLs having
/a/*/id/uniqueid
should be seen as one = based only on the unique ID and not give any regard to the text expressed with the “*”?
My hope is that it would be possible to say that a certain pattern like above should only be differentiated by the last unique segment.
If it is not possible in htaccess, how would it be done with link rel="canonical" on each page, can the code include wildcards?
I should add that the majority of the duplicates are caused by incoming links being lower case where the site itself is using a mix. Would it be OK to assign a canonical URL only with lower case although the site itself is basically always using a mix of lower/upper case?
If this is possible, I would be very happy to be helped with how to do it!!!!
Jonas
Hi Michael! I am not an expert but this is how I think it could be done:
1) My problem is that the URLs have mixed cases and I cannot change that now.
2) If it is OK for the searchengines, it would be fine for me to make the canonical URL identical to the actual URLs with the difference that it was all lower case, that would solve approx 90% of the duplicates. I e this would be the used URL: site.com/a/Cow_Cat/id/5272 and this would be the canonical: site.com/a/cow_cat/id/5272. As I understand, that would be good SEO...or...?
My idea was NOT to change the address browser address bar (i e using 301 redirect) but rather just telling the search engines which URLs that are duplicates, as I understand, that can be done by defining a canonical URL either in htaccess (as a pattern - I hope) or as a tag on each page.
3) IF, it would be possible to find a wildcard solution...I am not sure if this is possible at all, but that would mean it was possible to NOT assign a specific canonical URL but rather a "group pattern", i e "Please search engine, see all URLs with this patter - having the unique identifier in the end - as if they are one and the same URL, you SE, decide which one you prefer": /a/*/id/uniqueid
Would that work? It will only work in htaccess if canonical URLs can be defined as a group where the group is defined as a pattern with a defined part as the unique id.
Is it possible when adding a tag for each page to say that "all URLs containing this unique id should be treated the same"? If that would work it would look something similar to this
link rel="canonical" /a/*/id/5272
I dont know if this syntax with wildcard exist but it would be nice : )
My advice would be to use 301 redirects, with URL rewriting. Ask your webmaster to place this in your apache config or virtual host config:
RewriteMap lc int:tolower
Then inside your .htaccess file you can use the map ${lc:$1} to convert matches to lower case. Here, the $1 part is a match (backreference from brackets in a regex in the RewriteRule) and the ${lc: } part is just how you apply the lc (lowercase) function set up earlier. Here is an example of what you might want in your .htaccess file:
RewriteCond %{REQUEST_URI} [A-Z] #this matches a url with any uppercase characters
RewriteRule (.*) /${lc:$1} [L,R=301] #this makes it lowercase
As for matching the IDs, presuming your examples mean "always end with the ID" you could use a regex like:
^(.+/)(\d+))$
The first match (brackets) gets everything up to and including the forward slash before the ID, and the second part grabs the ID. We can then use it to point to a single, specific URL (like canonical, but with a 301).
If you do just want to use canonical tags, then you'll have to say what you're using code wise, but an example I use (so as not add tags to hundreds of individual pages, for instance) in PHP would be:
if ($_SERVER["REDIRECT_URL"] != "") {
$canonicalUrl = $_SERVER["SERVER_NAME"] . $_SERVER["REDIRECT_URL"];
} else if ($_SERVER["REQUEST_URI"] != "") {
$canonicalUrl = $_SERVER["SERVER_NAME"] . preg_replace('/^([^?]+)\?.*$/', "$1", $_SERVER['REQUEST_URI']);
}
Here, the redirect URL is used if it's available, and if not the request uri is used. This code strips off the query string (this bold bit in http://www.mysite.com/a/blah/12345/?something=true). Of course you can add to this code to specify a custom path, not just taking off the query string, by playing with the regex.

Create search engine friendly urls for our blog

We run a blog, and really need to tidy up the URLs using htaccess, but I am really stumped.
Example:
Working on a site, and I need to generate search engine friendly URLs
So I have the url currently as:
http://mywebsite.com/blog/read.php?art_id=11
Title of this page is:
Why do Australians pay so much for Cars ?
I need to change it to its corresponding SEF url. like so:
http://mywebsite.com/blog/Why-do-Australians-pay-so-much-for-Cars-?
The question mark is part of the title, and we could remove these if its a issue. Any suggestions please?
Also would prefer to drop the read.php portion. Need to create a rule that works across our entire blog.
They all follow the same pattern, only the art_id number changes.
(Assuming that you're using apache as a webserver)
Take a look at this answer for a very similar question: https://stackoverflow.com/a/8030760/851273
The problem here is that .htaccess and mod_rewrite doesn't know how to map page names to art_id's so there's 2 ways you can try to do this.
You can add some functionality to your read.php so that it can do a similar lookup but instead of art_id, it uses art_title or something. Essentially you'll have to do the backend lookup of a database (or wherever your articles are stored) and use the title as a key instead of the ID. This is a little messy since it's possible to have weird characters in titles such as non-ascii or reserved characters (like ? for instance), so you'll need to create a title encoder and decoder when pulling titles out of the database or when using titles to lookup an article in your database.
If you have access to the server config or vhost config, you may be able to setup a RewriteMap using an outside program (the prg type) and create a php script that does the title-to-ID lookup for you. Then you can create rewrite rules in your .htaccess that does something along the lines of:
RewriteRule ^blog/(.*)$ /blog/read.php?art_id=${title-to-id:$1} [L]
Where you are extracting the article title from your pretty URL, and feeding it through a rewrite map called title-to-id to get the art_id. Again you'll need to setup a title encoder/decoder so your titles will have the non-ascci and reserved characters dealt with.
Another thing that you can do is to stick an article ID in your pretty URLs so they look like this: http://mywebsite.com/blog/11-Why-do-Australians-pay-so-much-for-Cars. This is still pretty easy to see what the link is about, it's SEO friendly, and it bypasses the need to do title-to-ID lookups. The Rewrite Rules would also equally be simpler:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# add whatever other special conditions you need here
RewriteRule ^blog/([0-9]+)-(.*)$ /blog/read.php?art_id=$1 [L]
And that's it. Of course, you'd have to now generate all of your blog URL's to be of the form: http://(host)/blog/(art_id)-(art_title), and you'd also have to remove special characters from the title, but you don't have to worry about writing additional code to translate titles back to IDs.

Resources