SitePoint Sponsor

User Tag List

Results 1 to 16 of 16
  1. #1
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Advanced Search and Query String

    Hi, folks. I'm in the design stage of adding an Advanced Search page to my website. I'm not quite sure how to phrase this, but when someone does a complex search on my site, I want them to be able to cut and paste the URL of the page that shows their results, and email it to a buddy, or bookmark it or whatever, and be able to recreate those exact results whenever they want simply by revisiting that URL. Know what I mean? I realize that this is the idea behind using "method=get" on your form, but I'm generally not happy with the URL's produced by the default behavior of GET.

    I'll give you a quick example of what I mean. Let's say that I have a multiple select widget, with the name of a color for each option, and you can select several colors by holding down Ctrl. Each color is represented by a hex value, with one bit turned to on:

    red=1
    blue=2
    green=4
    orange=8

    When I query my database for color matches, I send in a single value that is the bitwise AND of several colors. So if the user selects red and green, what I want to see up in the URL is "colors=5". However, the default behavior of the GET method is to produce something like "colors%5B%5D=1&colors%5B%5D=4". Bleah.

    That was only an example, there are countless variations on that I want to do. To put it bluntly, how does one sort of override the GET behavior of html form input controls, so that the URL query string looks the way you want? I have a dread suspicion that I'm going to have to do a lot of this in javascript, and if so then fine, but something tells me I'm just missing something basic and profound--surely this is the kind of issue that anyone runs into once they decide to do their own advanced search.

    I took a look at this site's advanced search, and my confusion only deepened. The form uses GET method, but the results page show only a "searchid" and a number in the URL query string. I assume that your exact search is stored in a database or something--what are the advantages of that? Or is that a different discussion?

    Any thoughts?

    - Max

  2. #2
    SitePoint Evangelist priti's Avatar
    Join Date
    Aug 2006
    Location
    India
    Posts
    488
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by shmax View Post
    Hi, folks. I'm in the design stage of adding an Advanced Search page to my website. I'm not quite sure how to phrase this, but when someone does a complex search on my site, I want them to be able to cut and paste the URL of the page that shows their results, and email it to a buddy, or bookmark it or whatever, and be able to recreate those exact results whenever they want simply by revisiting that URL. Know what I mean? I realize that this is the idea behind using "method=get" on your form, but I'm generally not happy with the URL's produced by the default behavior of GET.

    I'll give you a quick example of what I mean. Let's say that I have a multiple select widget, with the name of a color for each option, and you can select several colors by holding down Ctrl. Each color is represented by a hex value, with one bit turned to on:

    red=1
    blue=2
    green=4
    orange=8

    When I query my database for color matches, I send in a single value that is the bitwise AND of several colors. So if the user selects red and green, what I want to see up in the URL is "colors=5". However, the default behavior of the GET method is to produce something like "colors%5B%5D=1&colors%5B%5D=4". Bleah.

    That was only an example, there are countless variations on that I want to do. To put it bluntly, how does one sort of override the GET behavior of html form input controls, so that the URL query string looks the way you want? I have a dread suspicion that I'm going to have to do a lot of this in javascript, and if so then fine, but something tells me I'm just missing something basic and profound--surely this is the kind of issue that anyone runs into once they decide to do their own advanced search.

    I took a look at this site's advanced search, and my confusion only deepened. The form uses GET method, but the results page show only a "searchid" and a number in the URL query string. I assume that your exact search is stored in a database or something--what are the advantages of that? Or is that a different discussion?

    Any thoughts?

    - Max

    Hi Max,

    I got little consfused so please clarify that ........are you not able to get the correct value after posting the form??

    try
    print_r($_GET)
    or
    $_GET['color'];

    It suppose to show you the value you received from the form.I hope you know $_GET is used when you have <form method='GET'> and $_POST when <form method='POST'>

    I think you should be able to get the values correctly.

    regards

  3. #3
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You should be using method=get for this.

    The colors&#37;5B%5D=1 is indeed ugly looking and is actually a non-standard (Although widely supported) way to do it. You can replace your ctrl-click list with checkboxes (These two widgets are always interchangeable) and give each checkbox a meaningful name. For example, color_red, color_orange etc. You would then get URL's like color_red=true&color_orange=true. If you want a different looking URL, you would have to use Javascript. I don't think that's a good idea -- Better to stick with an ugly standard, than invent a pretty non-standard.

  4. #4
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the response, I appreciate it, but I don't know if you're really quite grasping the spirit of what I want to do. In the case of the color widget, I have greater motives than just prettiness. It's about maintainability. Each color can be represented by a single bit (ie. 2, 4, 8, 16, 32, etc). I have an associative table of colors, where the number is the key, and the color name is the value (ie. "red", "orange", etc). If I want to add another color, I simply shift the bit to the left one, add it as a new array element along with a color name, and voila, I have a new color in my table, with no need to write an additional line of code.

    To represent a list of colors, I simply AND the desired keys together. My interpreting code doesn't have to know about color names. It shouldn't have to--when it comes time to query my database for color matches, all I want to send in is the single number that is the AND of various colors. If I have a long list of query items in the URL like you suggest ("?blue=true&red=true&yellow=true"), all that beautiful elegance goes out the window, and now I have to parse the string looking for color names I recognize, and rebuild the AND'ed value I want. Yes, I could do this iteratively by using the associative array of color names I have, but then stored URLs with all those color names in them become brittle--what happens if I decide to change the name of a color? What if instead of "Beige" I want "Hazelnut Cream"? Then someone's bookmarked URL with "Beige" in the name breaks and doesn't work anymore. I dunno, it just seems clunky.

    Maybe I'm over-thinking this, but I have to think that what I'm asking isn't totally unheard of...

    Quote Originally Posted by kyberfabrikken View Post
    You should be using method=get for this.

    The colors%5B%5D=1 is indeed ugly looking and is actually a non-standard (Although widely supported) way to do it. You can replace your ctrl-click list with checkboxes (These two widgets are always interchangeable) and give each checkbox a meaningful name. For example, color_red, color_orange etc. You would then get URL's like color_red=true&color_orange=true. If you want a different looking URL, you would have to use Javascript. I don't think that's a good idea -- Better to stick with an ugly standard, than invent a pretty non-standard.

  5. #5
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Hmmm, maybe it's not so bad after all...

    ...I was just poking through my script with the debugger, and I realized that although the URL looks garbage-y, it does resolve back into an orderly array in $_REQUEST, which I'm prepared to deal with. In other words, the place to "override" the behavior of method=GET is when building the page, not when constructing the URL--I already have code to convert the array created by the multiple select widget into my bitwise number, so I'm good to go. So, never mind, I guess! Me and my big, uninformed, long-winded mouth. Thanks, guys.

    - Max

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by shmax View Post
    What if instead of "Beige" I want "Hazelnut Cream"? Then someone's bookmarked URL with "Beige" in the name breaks and doesn't work anymore. I dunno, it just seems clunky.
    Wouldn't the user be confused, that their bookmark for "beige" suddenly show "hazelnut cream"?

    It sounds to me, like you're leaking implementation details to the view layer, where it isn't needed. For a regular user, I don't think it's very intuitive to expect them to interpret a bit-mask. In comparison, it's easy for a user to remove &red=true from the URL ?blue=true&red=true&yellow=true. The interface is intuitive.

  7. #7
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How about this:
    When the user does the initial search it builds the SQL query as per usual. In addition to executing the query it also saves the string query, and it's MD5 hash in a separate DB table (the hash can be the table key).

    You can then use the MD5 hash in your query string (give link to friend etc.) which will lookup the appropriate SQL query to execute.
    If your DB, form or query structure changes then just delete all the stored queries and start again. This table would be populated as searches occur.

  8. #8
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, I'd suggest the following

    Code:
    	<select name="color" multiple>
    		<option value="red">red</option>
    		<option value="green">green</option>
    		<option value="blue">blue</option>
    	</select>
    The url for this form will be like "index.php?color=red&color=blue". Php cannot parse this correctly, so we have to write out own "parser". Fortunately, this is quite easy:

    PHP Code:
    preg_match_all('/color=(\w+)/'$_SERVER['QUERY_STRING'], $m);
    $colors $m[1]; 
    From the url "color=red&color=blue" this will create an array("red", "blue"). The rest is hopefully obvious.

    If, for some reason, you want numeric id's instead of color names, just replace option values in html:

    Code:
    <select ...>
       <option value="1">red</option>

  9. #9
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cranial-bore View Post
    How about this:
    When the user does the initial search it builds the SQL query as per usual. In addition to executing the query it also saves the string query, and it's MD5 hash in a separate DB table (the hash can be the table key).

    You can then use the MD5 hash in your query string (give link to friend etc.) which will lookup the appropriate SQL query to execute.
    If your DB, form or query structure changes then just delete all the stored queries and start again. This table would be populated as searches occur.
    See, now that's interesting, and seems to be similar to what this site does. All you see in the query string is a search id (no hash--you just see the id of an entry in some search parameter table). I'm still not entirely sure what the advantage of that is, other than reducing what would otherwise be a very convoluted query string down to almost nothing. The only thing I can guess is that you wind up hiding functional details of the site from the user, which is probably useful for security reasons. And, as you say, anything you like can change under the hood, though that doesn't change the fact that you can potentially wind up with invalid search URLS floating around in the wild. Interesting...

    -Max

  10. #10
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    Wouldn't the user be confused, that their bookmark for "beige" suddenly show "hazelnut cream"?
    But the link would still work, and would still show the same search results. I would think that the fact that the literal string "beige" in the body of the html is now "hazelnut cream" would be less jarring than a 404 error.

    It sounds to me, like you're leaking implementation details to the view layer, where it isn't needed. For a regular user, I don't think it's very intuitive to expect them to interpret a bit-mask. In comparison, it's easy for a user to remove &red=true from the URL ?blue=true&red=true&yellow=true. The interface is intuitive.
    Typing color names and other bits of business into the URL, no matter how you encode it, isn't really what I consider an interface. Neither eBay, Amazon, nor google, nor any other site of considerable complexity that I can think of expects users to navigate their site with hand-coded URLS, and neither does my site.

    Your point about leaking implementation details is certainly valid, and I think the idea of stashing query strings away in a table somewhere and only showing a row id or hash value that was suggested in another post would neatly solve that. In fact, that seems to be exactly what eBay does--do a search on there sometime and look at the URL--complete gibberish. I'd often wondered what was going on there!

    - Max

  11. #11
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This, as I discovered, is exactly what happens naturally if I just leave things as-is. I wind up with an array in $_REQUEST called "colors", structured like this (assuming that the user chose red and green):

    colors[0]==1
    colors[1]==4

    Perfect! I can then call my little conversion function, which converts the array to the value 5, which I can then use to query my database. Color names are left out of it, I don't have to write any javascript, and the only thing I have to tolerate is an ugly query string, but if that really bothers me I can hide it away in a table somewhere and just show an id.

    Quote Originally Posted by stereofrog View Post
    From the url "color=red&color=blue" this will create an array("red", "blue"). The rest is hopefully obvious.

    If, for some reason, you want numeric id's instead of color names, just replace option values in html:

    Code:
    <select ...>
       <option value="1">red</option>

  12. #12
    SitePoint Wizard silver trophybronze trophy Cups's Avatar
    Join Date
    Oct 2006
    Location
    France, deep rural.
    Posts
    6,869
    Mentioned
    17 Post(s)
    Tagged
    1 Thread(s)
    'm in the design stage of adding an Advanced Search page to my website. I'm not quite sure how to phrase this, but when someone does a complex search on my site, I want them to be able to cut and paste the URL of the page that shows their results, and email it to a buddy, or bookmark it or whatever, and be able to recreate those exact results whenever they want simply by revisiting that URL. Know what I mean?
    Do you mean you would like to stop your server having to do the same searches over and again?

    user1 comes in, does a search, gets a page of results, you cache that page.

    Lets say you save it as "/results/123abc.htm"

    That's the page you load into the browser window for user1, OR its that url that you automagically add to a "tell a friend about these results" box.

    So user2 is send the address $website . "/results/123abc.htm"

    Thus:
    providing a url to a query
    saving your server the re-processing of that query
    giving you the opportunity to cheaply "show last 10 queries" etc

    On first reading that is what I understood your question to mean. Is that the case or not?

  13. #13
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog View Post
    Well, I'd suggest the following

    Code:
    	<select name="color" multiple>
    ...
    That is awesome! I'm so damaged from using PHP, that I didn't even think about doing that.

    Quote Originally Posted by shmax View Post
    I would think that the fact that the literal string "beige" in the body of the html is now "hazelnut cream" would be less jarring than a 404 error.
    You could send a 302 instead. Would probably be more appropriate in this case -- Esp. if you think the values are interchangeable.

    Quote Originally Posted by shmax View Post
    Neither eBay, Amazon, nor google, nor any other site of considerable complexity that I can think of expects users to navigate their site with hand-coded URLS, and neither does my site.
    Oh, but they do. Google has a query param q, which is used for the query. You can write the URL directly, and get a response.

    I'm not suggesting that regular users should handcraft URL's, but it makes it a lot easier to interact with your site. Even if you don't expect anyone to do this, it's just a good practise to follow.

    Quote Originally Posted by shmax View Post
    Your point about leaking implementation details is certainly valid, and I think the idea of stashing query strings away in a table somewhere and only showing a row id or hash value that was suggested in another post would neatly solve that. In fact, that seems to be exactly what eBay does--do a search on there sometime and look at the URL--complete gibberish. I'd often wondered what was going on there!
    That is a bad idea, even if it's commonly used. Try to make a search in this forum and bookmark it. Then come back to it, a month later. Client side state is a much better solution.

  14. #14
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    You could send a 302 instead. Would probably be more appropriate in this case -- Esp. if you think the values are interchangeable.
    Missing the point. The goal is NOT to have to show any kind of error. If I use ids for colors instead of literal names, the risk is diminished.

    Oh, but they do. Google has a query param q, which is used for the query. You can write the URL directly, and get a response.
    Well, you glommed onto the one site that can just barely squeak by with hand-encoded URL's, but I have never in my life seen someone do it. Here's one from eBay: http://search.ebay.com/search/search...fsoo%3D1&fgtp=

    Happy typing!

    I'm not suggesting that regular users should handcraft URL's, but it makes it a lot easier to interact with your site. Even if you don't expect anyone to do this, it's just a good practise to follow.
    I think you're nuts. I can't think of a single site where typing in the URL by hand is "easier" than using the interface provided. But that's just me. It could be that there are legions of uber-nerds out there that have evolved to the point where they are only slowed-down by the search forms, and are doing everything by hand.

    That is a bad idea, even if it's commonly used. Try to make a search in this forum and bookmark it. Then come back to it, a month later. Client side state is a much better solution.
    So the ids expire? Well, that WOULD suck. I wonder how large the tables swell. I was thinking of following eBay's lead again; they seem to leave any literal search string untouched, so you DO see that in the query string, but all the other fussy little details like sort order, and whether or not you want to see completed listings and that sort of thing seem to get encoded into a hash string. If I did things that way, my search parameter table wouldn't bloom out of control, and I would never have to blow it away. I'm not saying I'm completely sold on the idea--an hour ago I had never heard of it--just trying to learn all the different approaches.

    - Max

  15. #15
    SitePoint Enthusiast
    Join Date
    May 2006
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Cups View Post
    On first reading that is what I understood your question to mean. Is that the case or not?
    Let's just say that what I meant was that I want to use method=GET for my form, so that the posted variables wind up in the URL. -M

  16. #16
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by shmax View Post
    Missing the point. The goal is NOT to have to show any kind of error. If I use ids for colors instead of literal names, the risk is diminished.
    302 is also known as a redirect. The browser should (and will) immediately load the new URL. Actually, in this case, 301 would probably be more appropriate.

    Quote Originally Posted by shmax View Post
    Well, you glommed onto the one site that can just barely squeak by with hand-encoded URL's, but I have never in my life seen someone do it.
    My browsers "home" page is pointing to /home/tkn/htdocs/home.html. This is a custom HTML page, where I, among other search engines, have a form, that queries Google. The premise for me being able to create that form, is that it has a simple interface. I don't think normal end users are going to fiddle with URL's directly, but users may also be automated bots, mashups or search engines. Or your self in 6 months, trying to write a test-suite.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •