homepage Welcome to WebmasterWorld Guest from 50.19.169.37
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / Apache Web Server
Forum Library, Charter, Moderators: Ocean10000 & incrediBILL & phranque

Apache Web Server Forum

    
GET parameter becomes the page name after rewrite
Lussay




msg:4599342
 10:54 pm on Aug 4, 2013 (gmt 0)

Hi guys,

I have a problem and I've literally been banging my head into this for the last 24 hours.

I have an url that looks like:

/platforms.php?platform_id=xxx

where xxx is a number

I'm rewriting the URL's inside the php aplication so for example the above url would look like:

/xbox/ or /playstation/

Now in httaccess I have:

RewriteRule ^([^/]+)/$ platforms.php?platform_id=$1 [L,QSA]

However when I go to a platform page the GET url becomes /xbox/ or /playstation/ , instead of xxx.

Any pointers would be appreciated.

 

lucy24




msg:4599356
 11:57 pm on Aug 4, 2013 (gmt 0)

Uhm.... What "GET url"? Did you mean the result of
$_GET["platform_id"]
? Or some other parameter? Or some other function entirely?

I'm rewriting the URL's inside the php aplication

Please explain exactly what you mean by this. It is obvious to you, but not to everyone else-- and the word "rewrite" has a long history of leading to calamitous misinterpretations :(

Rule as written:
RewriteRule ^([^/]+)/$ platforms.php?platform_id=$1 [L,QSA]

Meaning: if there is a request for the directory
www.example.com/blahblah/
then quietly serve content from
www.example.com/platforms.php
adding a two-part query string:
platform_id=blahblah
AND
any other pre-existing query

From your post it's impossible to tell what is supposed to happen and in what order. So it will work best if you backtrack and say in English
#1 what action the human user takes
#2 what should appear in the browser's address bar
#3 where the intended page content lives

After that's out of the way we can proceed to
#4 are we talking about one php action (processing an incoming request) or two-or-more php actions (one of which creates outbound links in a particular format).
But not until nos. 1-3 have been sorted.

Lussay




msg:4599359
 12:42 am on Aug 5, 2013 (gmt 0)

Hi,

Thanks for the answer and sorry for the bad explanation.

Yep, when I said GET url I was referring to $_GET["platform_id"] .

Basically I have an URL called

www.example.com/platforms.php?platform_id=1

In the above example $_GET['platform_id'] = 1.

In the actual php aplication I have a function (let's call it make_link ), with which I make the above URL output like:

www.example.com/xbox/ (since 1 is the id of the xbox platform)

Now in httaccess I also need a rewrite rule that will make accessing the URL work.

So I have :

RewriteRule ^([^/]+)/$ platforms.php?platform_id=$1 [L,QSA]

This does make the rewrite work in the terms that I can access

www.example.com/xbox/

However on the newly accessed page, if I get $_GET['platform_id'], the value for it is xbox/ .

Thanks,

lucy24




msg:4599363
 1:41 am on Aug 5, 2013 (gmt 0)

Uhm.... Yeah. Isn't that exactly what you told it to do? Capture request, turn it into parameter.

Request
www.example.com/xbox/

RewriteRule ^([^/]+)/$ platforms.php?platform_id=$1 [L,QSA]

Result: the page /platforms.php (btw, it's safer to include a leading slash in the target) receives the parameter
platform_id=xbox

I cannot say where the trailing / is coming from, unless there's some other rule you haven't mentioned. What's the rest of the query string? (The part that necessitates a QSA flag.)

Lussay




msg:4599364
 1:47 am on Aug 5, 2013 (gmt 0)

Well ... yes, that's what I did tell it to do. It works but as mentioned above it screws the GET.

The rest could be the pagination, but that's not necessarly relevant.

g1smd




msg:4599366
 1:53 am on Aug 5, 2013 (gmt 0)

Having retrieved "xbox" from the GET parameter, you then need to look up the ID number for it.

This is just a few lines of PHP. You can hold the data such as "xbox = 1", etc, in an array or in a database.

Lussay




msg:4599371
 3:00 am on Aug 5, 2013 (gmt 0)

Yes ... I could do that.

However, I have my entire system working around ID's. I'm getting all the info from the database by quering id's, not names.

lucy24




msg:4599372
 3:10 am on Aug 5, 2013 (gmt 0)

How many platforms can there be? Toss something into the php itself along the lines of
$variable["xbox"] = 1;
$variable["wii"] = 2;
et cetera-- only in some php-optimal format, which you will not get from me ;) And then plug these numbers into your database search.

Looking back at the first post, I don't understand where the xxx numerical value is supposed to come from, if not from a php lookup.

Lussay




msg:4599383
 4:03 am on Aug 5, 2013 (gmt 0)

Well,

I ended up working with the platform names in the urls as well.

The problem are not the platforms, but the fact that platforms will have games,cheats etc. ... so overall there is quite a lot of stuff to modify to make this work.

However, I was just thinking, in order to not modify all my queries (that currently search data in the database based on GET['platform_id']), is it possible to also pass the platform_id in the URL, but masked in some way?

And to try to make it more clear here is where I am

I create my url like:

www.example.com/xbox/

I have in httaccess:

RewriteRule ^([^/]+)/$ platforms.php?platform_id=%1&platform_name=$1 [L,QSA]

When I go to the above example in GET I have:

platform_id=&platform_name=xbox

So I'm not sure if %1 is correct in order to also pass that ID.

Lucian

lucy24




msg:4599390
 5:29 am on Aug 5, 2013 (gmt 0)

is it possible to also pass the platform_id in the URL, but masked in some way?

It is, but I honestly don't understand what you would gain from it. You'd still have to do some kind of php lookup to find out what the masking represents-- so why not look up the platform:id equivalence instead?

I have in httaccess:

RewriteRule ^([^/]+)/$ platforms.php?platform_id=%1&platform_name=$1 [L,QSA]

When I go to the above example in GET I have:

platform_id=&platform_name=xbox

So I'm not sure if %1 is correct in order to also pass that ID.

% represents a capture from the most recent RewriteCond. You haven't got any Conditions, so what was %1 intended to represent?

There are now at least two unanswered questions:

What is in the query string before the URL meets the rewrite?

How many different ids are there?

Oh, a third one that I'd overlooked. Is platform:id a one-to-one correspondence, like
xbox=1
wii=2
sega=3
etc she said, dating herself
or are there multiple id's to a single platform?

Lussay




msg:4599392
 5:34 am on Aug 5, 2013 (gmt 0)

Hi,

the query string can look like:

platforms.php?platform_id=1&platform_name=xbox

and could also have page=1

Yes there is some lookup done in php based on the GET paramaters. However the lookup is done based on the ID of the platform/game etc.

So I don't want to do the lookup based on the platform name, game name etc. as that's ... messy

So ... to conclude what I need is:

Before URL:

www.example.com/platforms.php?platform_id=1&platform_name=xbox

To have it rewritten to

www.example.com/xbox/

And also be able to get the platform_id GET parameter from the new URL.

Lussay




msg:4599393
 5:41 am on Aug 5, 2013 (gmt 0)

Oh, and yes, each platform has it's unique ID.

g1smd




msg:4599401
 6:17 am on Aug 5, 2013 (gmt 0)

You should use URLs like example.com/1-xbox or example.com/p1-xbox then you have the ID number immediately available.

The URL format is important. On a shopping site I would use:
/c1p1-category-name for page 1 of category 1,
/p1-product-name for products,
/r1-product-name for reviews, etc

URLs for pages would not have a trailing slash. Trailing slash denotes a folder.

Use a similar rewrite to the one that you have now:
RewriteRule ^p([0-9]+)-([^/.]+)$ /platforms.php?platform_id=$1&platform_name=$2 [L,QSA]

Extract both the ID and the name from the GET parameter. Look up the requested ID in the database. If it is not valid, send HTTP 404 header and "include" the HTML 404 error page. If the ID is valid, compare the requested name against the name stored in the database. If they are not an exact match send a HTTP 301 header pointing to the correct URL built from the requested ID and the name as stored in the database. If the ID and the name are correct then show the content.

The 404 and 301 functionality are crucial parts of the system.

[edited by: bill at 8:12 am (utc) on Aug 5, 2013]
[edit reason] fixed typo [/edit]

Lussay




msg:4599403
 6:42 am on Aug 5, 2013 (gmt 0)

Hi,

Well ... the example that you gave to me with the id's in the url ... I already have that done.

However what I am after is for clean URL's, no ID's.

So if you can help me with the above request, that would be great. If not then when I'll find a solution I'll come back and post it :).

lucy24




msg:4599418
 8:03 am on Aug 5, 2013 (gmt 0)

You have two choices.

ONE. Include the numerical ID as a separate URL element, to be converted to a second parameter passed to the php file. The exact form of the URL isn't important, so long as it includes a numerical component that can be recognized and extracted by mod_rewrite alone.

TWO. Using the existing URL, which is converted to a single parameter, do a php lookup to derive the numerical ID from the platform name before going to the database.

If you are looking for an approach that will make the id invisible to humans but visible to the php page-- a sort of {display: none} for mod_rewrite-- there isn't one.

Question still not answered: how many platform:id pairs are there?


Edit:
Before URL:
www.example.com/platforms.php?platform_id=1&platform_name=xbox

To have it rewritten to
www.example.com/xbox/

This is backward. A rewrite means that the address bar shows A while the content is taken from B. In your example, the address bar-- and any linking from within your site-- would say
www.example.com/xbox (no trailing slash unless you want to pretend your site is composed entirely of directory-index pages)
while the content lives at
platforms.php
which will then be given the two parameters
platform_id=1
and
platform_name=xbox

Except that, as already explained, this is impossible. The value for "platform_name" is deducible from the URL; the value for "platform_id" is not deducible from the URL in its present form.

g1smd




msg:4599430
 10:32 am on Aug 5, 2013 (gmt 0)

Without a RewriteRule a request for example.com/something will cause Apache to look on the server hard disk for {site_root}/something.

A RewriteRule does not "make" or "change" a URL.

What Apache does, is match the "something" from the requested URL using the RegEx pattern. If the pattern matches the request, Apache then uses the information from the matching RewriteRule target to look in a completely different location on the server hard drive.

User requests: /something
If pattern matches, internal "pointer" is changed from "something" to "index.php?something" as per the RewriteRule target.
Finally, Apache fetches content internally from: /index.php?something - crucially it does this without revealing what that internal location actually is.

The act of changing the target of the internal file pointer is called "rewriting a request".

A RewriteRule cannot alter a URL nor can it change the links on your page. You must alter your PHP scripts so that the href of the links on your pages contains the URL that you want users to see and use.

When the internal file pointer is updated when the matching RewriteRule is processed, the rule target can only use things that were in the originally requested URL. If the user requested example.com/xbox the rule cannot know that the "id" is "1", unless that "1" is also somewhere in the requested URL, e.g. example.com/1-xbox.

I always include the id number in the URL. It makes the initial coding much more simple and much easier to maintain.

The last part of the puzzle is to add another RewriteRule, this time configured as a redirect, so that if a user should request example.com/index.php?something they are redirected to make a new request for example.com/something. This step stops the site having a Duplicte Content problem.

A RewriteRule can be configured either as a redirect or as a rewrite. You will need one of each. Make sure you are clear on the differences in functionality.

Before you proceed any further you need to make a list of all of the old URL formats the site uses and work out what the new URL for each one will look like. You casually mentioned that some sections will have multiple pages, but haven't shown how those additional pages will be specified in the URL that a user requests. Would it be example.com/xbox-2 or example.com/xbox?page=2 or something else?

Designing the URL structure before you do any more coding is vital.

Lets say your website had a "platforms" section served by "platforms.php", and a "manufacturers" section server by "manufacturers.php".

How would the RewriteRule know to route a request for example.com/xbox to platforms.php and a request for example.com/atari to manufacturers.php?

The answer is that it cannot know unless you have a clue in the requested URL: example.com/p-xbox and example.com/m-sega for example, the "p" and "m" being the clues for "platforms" and "manufacturers".

You need to sort the URL design out before you do any more coding.

With example.com/m1p2-sega (manufacturer "1" (sega), page "2") I would have:
RewriteRule ^m([0-9]+)p([0-9]+)-(.*) /manufacturers.php?manu=$1&page=$2&name=$3 [L]

The PHP extracts the 3 parameters then looks in the manufaturers database for id=1, page=2. If id=1 does not exist or there is no page 2 for id=1 then send 404 header and error page out. If id=1 does exist, check that requested manu name is identical to the manu name in the database. If it is not identical send a 301 redirect to the correct URL. If id=1 and page=2 exists in the database and the requested manu name is correct, then serve the content.

lucy24




msg:4599499
 3:49 pm on Aug 5, 2013 (gmt 0)

:: shuffling papers ::

Here are the two most recent (= active within the past week) long, long threads about rewriting. Between the two of them they probably cover all points that need to be raised here.

[webmasterworld.com...]
[webmasterworld.com...]

g1, I know an Englishman currently living in Portugal. Periodically he goes home to see the grandchildren and, more importantly, to visit a particular pub in (really) Basingstoke. I'll meet you there.

Lussay




msg:4599614
 1:44 am on Aug 6, 2013 (gmt 0)

Hey Guys,

Thanks a lot for your advice.

Finally what I used is something like this to handle all the cases for the platforms.php pages:

RewriteRule ^([^/]+)/$ platforms.php?platform_name=$1 [L,QSA]
RewriteRule ^([^/]+)/letter(.*)/page(.*)$ platforms.php?platform_name=$1&letter=$2&page=$3 [L,QSA]
RewriteRule ^([^/]+)/letter(.*)$ platforms.php?platform_name=$1&letter=$2 [L,QSA]

This covers the cases

/platform/
/platform/letterA (B,C,D,E)
/platform/letterA/page1 (2,3,4)

Basically I ended up creating slugs for all my pages and storing them in the database.

The in PHP I get the slug on each page request, look for it in the database and get the ID of the platform.

Either way, thanks again for all your advice. You guys are great.

lucy24




msg:4599629
 4:58 am on Aug 6, 2013 (gmt 0)

The bits you've given as .* look as if they can be narrowed down to-- at a minimum-- [^/]* and maybe even [A-Z] or \d (the latter may have to go to [0-9] if your server is grumpy). The idea is to stop capturing before you hit the directory slash, so the server doesn't have to backtrack "Oh, oops, nobody told me I wasn't supposed to capture the whole thing".

It looks as if requests with no "page" or "letter" value won't result in a valid URL, so it's better to use + instead of * each time. Then if someone does mistype "blahblah/letter/page" you can proceed directly to a 404 without bothering about the rewrite and php.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Apache Web Server
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved