Update URL after Form Submit?

I just added a drop-down box to my Subsection page to allow users to sort.

How do I update the URL after the user submits the form?

If a user selects “Sort by Title (A-to-Z)” then I want my URL to change from this…


www.debbie.com/finance/economy/

To this…


www.debbie.com/finance/economy/sortname=by-title/asc/1

It’s embarrassing to ask such a simple question, but my experience with forms is for data entry (e.g. Registration Form).

Sincerely,

Debbie

Maybe that’s not such a simple question. Looks to me like you are creating directory path(s) /sortname=by-title/asc/1 for each of these.

As a GET test I made this sample form.

<form action="" method="get">
	<select name="sortname">
		<option value="by-title/asc/1">Sort by Title (A-to-Z)</option>
		<option value="by-title/desc/1">Sort by Title (Z-to-A)</option>
	</select>
<input type="submit" value="Set" />
</form>

Resulting with a GET URL of

testpage6.php?sortname=by-title%2Fasc%2F1

So we’re getting %2F instead of / but I suppose you don’t want GET at all in the first place.

I always POST with forms or use links for GET and would send as different key/value pairs like so.

?sortby=title&order=asc

IF posting these values I would set these values to session.

Anyway, I’m sure someone will address your question more directly.

Back in January, I created a Private Message module and created the ability to sort by each column heading in the Inbox. In that case, I just put a hyperlink behind an up/down arrow, so that was easier, because I could actually build the URL I needed.

But in this situation, I am using a Form where I need to take the value in a drop-down box and somehow convert that to a Query String like this…


www.debbie/finance/markets/?sortname=by-date&sortdir=asc&page=1

thinking out loud

Well, when a Form is submitted - at least using POST - you get a $_POST array, right?

So I would have the value in the $_POST array, but I’m not sure how to get that int my URL… :-/

My understanding is that it is better to do things like sorting using the URL versus a Session, because it allows users to bookmark the search/sort. And I also suspect it is better for SEO…

Sincerely,

Debbie

And how about something like this?

<?php
if(isset($_POST['sortname'])):
	$link = $_SERVER["HTTP_REFERER"] . "/" . $_POST['sortname'];
	header("location: $link");
	exit;
endif;
?>

OR did you actually want a GET with ?

<?php
if(isset($_POST['sortname'])):
	$link = $_SERVER["HTTP_REFERER"] . "?" . $_POST['sortname'];
	header("location: $link");
	exit;
endif;
?>

Yep. I agree this isn’t nearly as easy as one would think.

I follow what you are doing, but all my mind says is, “Security risks!!!”

Here is hoping some of the resident SitePoint gurus have an approach which is proven and secure…

(Your approach might be the way to do it, but clearly this stuff is out of my league!!) :blush:

Sincerely,

Debbie

I don’t think there is any security risk using GET if you validate the input. You may of course disregard what I say and wait for one more qualified to give you an answer. I do think the way you have GET formed makes it more difficult to get the values, because there is no key=value pair to grab info. Maybe there’s a better way I’m not seeing right now. To compare,

?by-title/asc/1

<?php
//example get
//?by-title/asc/1
$allowed_sorts = array("by-title","by-author","by-category");
$allowed_order = array("asc","desc");
if(isset($_GET)):
	$get_parts = array();
	foreach($_GET as $k => $v):
		$get_parts = explode("/",$k);
	endforeach;	
	// Get sortby matches
	$sortby_matches = array_intersect($get_parts, $allowed_sorts);
	// Get order matches
	$order_matches = array_intersect($get_parts, $allowed_order);
	
	// Check for sortby
	if(!empty($sortby_matches)):
		foreach($sortby_matches as $sm):
			$sortby = $sm;
		endforeach;
	endif;
	
	// Check for order
	if(!empty($order_matches)):
		foreach($order_matches as $om):
			$order = $om;
		endforeach;
	endif;
		
	// Check for any numeric values
	foreach($get_parts as $nu):
		if(is_numeric($nu)):
			$number = $nu;
		endif;
	endforeach;
	
	//echo results
	echo $sortby;
	echo "<br />";
	echo $order;
	echo "<br />";
	echo $number;
endif;
?>

?sortby=title&order=asc&num=1

<?php
//example get
//?sortby=title&order=asc&num=1
$allowed_sorts = array("title","author","category");
$allowed_order = array("asc","desc");
if(isset($_GET)):
	
	// Check for sortby
	if(isset($_GET['sortby']) && !empty($_GET['sortby'])):
		if(in_array($_GET['sortby'],$allowed_sorts)):
			$sortby = $_GET['sortby'];
		endif;
	endif;
	
	// Check for order
	if(isset($_GET['order']) && !empty($_GET['order'])):
		if(in_array($_GET['order'],$allowed_order)):
			$order = $_GET['order'];
		endif;
	endif;
		
	// Check for any numeric values	
	if(isset($_GET['num']) && !empty($_GET['num'])):
		if(is_numeric($_GET['num'])):
			$number = $_GET['num'];
		endif;
	endif;
		
	//echo results
	echo $sortby;
	echo "<br />";
	echo $order;
	echo "<br />";
	echo $number;
endif;
?>

Both return the same values for respective URL

title
asc
1 

Try this:


<?php
  $links = array 
  (
     'Title-asc',
     'Title-desc',
     'Date-asc',
     'Date-desc',
  );
  
 if(count($_POST) > 0 && isset($_POST['sorted']) )
  {
     $sorted = $_POST['sorted'];
     $_POST = array();
     header('Location: http://localhost/gocode/index-debbie.php?' .$sorted );
     exit;
  }

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<title>Testing</title>
<style type="text/css">
  body     {background-color: aqua;}
  pre,
  fieldset,
   textarea {width:42%; margin: 1em auto; background-color: white;}
  pre,
  textarea {width:88%;}
</style>
</head>
<body>

  <form action="?" method="post">
     <fieldset class="XXXtoggle">
       <legend>Sort </legend>
       <?php 
           foreach($links as $url => $link)
           {
             echo '<label>' .$link .'</label>';
             echo '<input type="radio" name="sorted" value="' .$link .'" /> ';
           }
       ?>
       <br />
       <textarea>User blurb goes here</textarea> 
       <input type="submit" value="Set" />
    </fieldset>
  </form>

<pre>
  <?php /* DEBUG */
      echo '$_POST == '; 
      print_r($_POST); 
      echo '<hr />';
      highlight_file( __FILE__);
  ?>
</pre>

</body>
</html>


Output

Sort
Title-asc x Title-desc x Date-asc x Date-desc x
User blurb goes here

set

To correct my post above #6, the first example returns the values in the URL

by-title
asc
1

I suspect it may be simpler to write the HTML as a list of ordinary links, then decorate those links with CSS and possibly a touch of JS to give them the appearance of a dropdown menu.

Thanks, but JavaScript is off the table.

The code in Posts #6 and #7 doesn’t run, so I’m not sure what you guys wanted me to see.

Debbie

This is as close as I could get things to working…

Sample Code:
(The Name and Email stuff was just to make sure I understood how GET works. It can be ignored.)


<?php
	$name = (isset($_GET['name']) ? $_GET['name'] : '');
	$email = (isset($_GET['email']) ? $_GET['email'] : '');
	$sort = (isset($_GET['sortname']) ? $_GET['sortname'] : '');

	
	echo "<p>Welcome $name!</br></br>
				Your e-mail is: $email</br></br>
				You chose to sort by: $sort</p>";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
	<form action="" method="get">
		Name: <input type="text" name="name"></br></br>

		E-mail: <input type="text" name="email"></br></br>

		<select id="sortname" name="sortname">
			<option value="by-date&sortdir=desc" <?php echo (($sort=='by-date&sortdir=desc') ? ' selected="selected"' : '') ?>>Date (Newest 1st)</option>
			<option value="by-date&sortdir=asc" <?php echo (($sort=='by-date&sortdir=asc') ? ' selected="selected"' : '') ?>>Date (Oldest 1st)</option>
			<option value="by-title&sortdir=asc" <?php echo (($sort=='by-title&sortdir=asc') ? ' selected="selected"' : '') ?>>Title (A-to-Z)</option>
			<option value="by-title&sortdir=desc" <?php echo (($sort=='by-title&sortdir=desc') ? ' selected="selected"' : '') ?>>Title (Z-to-A)</option>
		</select></br></br>
	
		<input type="submit">
	</form>
</body>
</html>

Sample Input:


Name: Bob
Email: bob@mail.com
Dropdown: Title (Z-to-A)

Output:


Welcome Bob!

Your e-mail is: bob@mail.com

You chose to sort by: by-title&sortdir=desc

URL:


http://local.debbie/test20.php?name=Bob&email=bob%40mail.com&sortname=by-title%26sortdir%3Ddesc

Remember, the goal is that I want the URL to contain a series of key-value pairs that are normally formatted. (If I just wanted to pass the sorting choice back to my PHP, that would be easy.)

There must be a way to do what I want…

Sincerely,

Debbie

Here we go and just in case you are unable to get the source code working:

http://www.johns-jokes.com/downloads/sp-c/debbie-update-url/

Results:

// no name
index-debbie.php?

// no email
index-debbie.php?

// name & email
index-debbie.php?name=Double-Dee&email=debbie@debbie.com

// name & email & sortTitle
index-debbie.php?name=Double-Dee&email=debbie@debbie.com&sortname=Title-asc

// name & email & sortDate
index-debbie.php?name=Double-Dee&email=debbie@debbie.com&sortname=Title-desc&sortdir=Date-asc

// name & email & sortTitle & sortDate
index-debbie.php?name=Double-Dee&email=debbie@debbie.com&sortname=Title-asc

Source:


<?php
  $linkT = array ( 'Title-asc', 'Title-desc' );
  $linkD = array ( 'Date-asc',  'Date-desc'  );


  $email = isset($_POST['email']) ? $_POST['email'] : NULL;
  $name  = isset($_POST['name'])  ? $_POST['name']  : NULL;
    
  if( $name && $email )
  {
    $name      = '?name='  .str_replace("%20", '-', $name);
    $email     = '&email=' .$email;
    $sortTitle = isset($_POST['sortTitle']) ? '&sortname=' .$_POST['sortTitle'] : ''; 
    $sortDate  = isset($_POST['sortDate'])  ? '&sortdir='  .$_POST['sortDate'] : ''; 


    $_POST  = array();
    $url   =  $_SERVER['SERVER_NAME'] .$_SERVER['REQUEST_URI']
           .  $name
           .  $email
           .  $sortTitle
           .  $sortDate;
    $url = str_replace('??', '?', $url);       
    // echo $url;die;
    header('Location: http://' .$url);
    exit;
  }
  $_POST = array();


?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<title>Testing</title>
<style type="text/css">
 body     {background-color: aqua;}
 pre,
 fieldset,
 textarea {width:88%; margin: 1em auto; background-color: white;}
 pre,
 textarea {width:88%;}
</style>
</head>
<body>


  <form action="?" method="post">
    <fieldset>
      <legend>Sort </legend>
      <?php 
        foreach($linkT as $url => $link)
        {
          echo '<label>' .$link .'</label>';
          echo '<input type="radio" name="sortTitle" value="' .$link .'" /> ';
        }
        foreach($linkD as $url => $link)
        {
          echo '<label>' .$link .'</label>';
          echo '<input type="radio" name="sortDate" value="' .$link .'" /> ';
        }
      ?>
      <br /><br />
      <label>Name: </label> <input type="text" name="name"></br></br>


      <label>E-mail: </label> <input type="text" name="email"></br></br>


      <!-- textarea>User blurb goes here</textarea --> 
      <input type="submit" value="Set" />
      <?php echo '<br /><b>' .$_SERVER['HTTP_REFERER'] .'</b>';?>
    </fieldset>
  </form>


  <pre>
    <?php highlight_file( __FILE__);?>
  </pre>


</body>
</html>



Post #6 was talking about validating GET and does work for picking up the get values from the example URL and validating against an array of valid values. The “allowed sorts” array would need to be modified to hold the allowed values you are using. And I’m referring to the second example that uses the key=value pair.

HOWEVER although it may look like the URL has the key=value pairs, if you print_r($_GET) you will see that the sortdir is part of the value of sortname.

Array ( [name] => Debbie [email] => debbies@eeemail,com [sortname] => by-date&sortdir=asc ) 

Is there any reason you can’t have another selection for ascending, descending? You would then have the correct key value matches.

If you really want to use a single selection, then you can use a header to change POST to GET like this. I also have the validate GET code here.

<?php
if(isset($_POST['sortname'])):	
	$link = "?sortname=" . $_POST['sortname'];
	header("location: $link");
	exit;
endif;
?>
<?php
    $sort = (isset($_GET['sortname']) ? $_GET['sortname'] : '');
    $sortdir = (isset($_GET['sortdir']) ? $_GET['sortdir'] : '');


    echo "<p>You chose to <br />Sort by: $sort  <br />Sort order: $sortdir</p>";
?>
<?php
$allowed_sorts = array("by-date","by-title");
$allowed_order = array("asc","desc");

if(isset($_GET)):
	// Check for sortby
	if(isset($_GET['sortname']) && !empty($_GET['sortname'])):
		if(in_array($_GET['sortname'],$allowed_sorts)):
			$valid_sort = $_GET['sortname'];
		endif;
	endif;
	
	// Check for order
	if(isset($_GET['sortdir']) && !empty($_GET['sortdir'])):
		if(in_array($_GET['sortdir'],$allowed_order)):
			$valid_dir = $_GET['sortdir'];
		endif;
	endif;
		
    echo "<p>Valid <br />Sort by: $valid_sort  <br />Sort order: $valid_dir</p>";
endif;
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
    <form action="" method="post">
        <select id="sortname" name="sortname">
            <option value="by-date&amp;sortdir=desc" <?php echo (($sort=='by-date' && $sortdir=='desc') ? ' selected="selected"' : '') ?>>Date (Newest 1st)</option>
            <option value="by-date&amp;sortdir=asc" <?php echo (($sort=='by-date' && $sortdir=='asc') ? ' selected="selected"' : '') ?>>Date (Oldest 1st)</option>
            <option value="by-title&amp;sortdir=asc" <?php echo (($sort=='by-title' && $sortdir=='asc') ? ' selected="selected"' : '') ?>>Title (A-to-Z)</option>
            <option value="by-title&amp;sortdir=desc" <?php echo (($sort=='by-title' && $sortdir=='desc') ? ' selected="selected"' : '') ?>>Title (Z-to-A)</option>
        </select></br></br>

        <input type="submit">
    </form>
</body>
</html>

And yes those valid variables could be set like this.

<?php
$allowed_sorts = array("by-date","by-title"); 
$allowed_order = array("asc","desc");

$valid_sort = (isset($_GET['sortname']) && !empty($_GET['sortname']) && in_array($_GET['sortname'],$allowed_sorts) ? $_GET['sortname'] : '');
$valid_dir = (isset($_GET['sortdir']) && !empty($_GET['sortdir']) && in_array($_GET['sortdir'],$allowed_order) ? $_GET['sortdir'] : '');
	
   echo "<p>Valid <br />Sort by: $valid_sort  <br />Sort order: $valid_dir</p>";
?>