Forum Moderators: coopster

Message Too Old, No Replies

data persistence and sessions

         

tryan

3:43 pm on Jul 7, 2004 (gmt 0)

10+ Year Member



I have a form that sends data to a MySQL database. If any required fields are not filled in, the page that would otherwise write the data to the database catches the problems, notifies the user and directs them to click the Back button to enter the missing data.

However, when they do that the data that was entered is gone, so thay have to start again. A bad thing, cause there are a couple of hundred fields.

The problem appears to be that I begin an included file with session_start();. If I remove the line that includes the file (which tests that the user is logged in) then the data is preserved. If not - poof! If I put the code from the included file into the main file (rather than "including" it), it still clears the form.

Here is the code from the included file:

<?php
session_start();
if(!isset($_SESSION['username'])) {
echo'<html>
<head>
<meta http-equiv="Refresh" content="0; URL=Login.htm">
</head>
</html>';
}
?>

Anyone know a way around this little glitch?

Tom

ergophobe

4:20 pm on Jul 7, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



How are you passing the data? Are you reposting, or storing it as session variables?

If you are reposting, the problem is here:


<meta http-equiv="Refresh" content="0; URL=Login.htm">

You are refreshing, but losing the post information. If you don't include this info and go straight to the login, and you have

if (isset($_POST['var1']) && $_POST['var1'] )

This will work, but after the refresh, the var is no longer set.

Two ways to get around it.

1. before refresh, say
$_SESSION['post_vars'] = $_POST;
and then use that array to refill the form.

2. Have the "action" of the form, be the form itself. If it passes the validation test, *then* redirect to the success page.

I almost always use option 2.

BTW, you should probably redirect not by echoing a refresh, but with a simple

header("Location: success.php");

Tom

brucec

4:32 pm on Jul 7, 2004 (gmt 0)

10+ Year Member



I have run into this problem as well. It really depends ont he version of Internet Explorer and the person's computer.

The way to solve this in a foolproof is to fill in a new form with all the values. I don't redirect the user back to the first form. Just keep them on that page with a form that they can edit on that web page.

httpwebwitch

5:01 pm on Jul 7, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Is this a multi-page form? like a wizard?
If so, I solved that problem using sessions where other methods were lacking.

Every time someone presses submit (or "next" or "back"), have the following page perform this process, whether the data is validated or not:

foreach($_POST as $k=>$v){
$_SESSION[$k]=$v;
}

Then if you go back to any step in the process, populate the form with the Session value in the HTML:

<input type="text" name="phonenumber" value="<?php print($_SESSION['phonenumber'])?>">

Where browsers can choose whether or not to "remember" form contents when you go back, forth, or navigate, your server can do the work by remembering those values in a session.

I would also suggest that in your login authentication (where you are checking for the $_SESSION['username']), use a header() redirection instead of writing a <meta> redirection.

<?php
session_start();
if(!isset($_SESSION['username'])){
header("Location:Login.htm");
}
?>

ergophobe

5:11 pm on Jul 7, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I don't redirect the user back to the first form.

They don't need to be sent back to the first FORM necessarily. I just meant send them to the FILE that will create the form you want now (which is likely to be the file that created the first form, but not necessarily). IF IT VALIDATES, then redirect, rather than doing the validation and if it fails, redirect.

tryan

5:34 pm on Jul 7, 2004 (gmt 0)

10+ Year Member



Thanks everyone

I suspect I'll be trying httpwebwitch's suggestion first. I should set everything as session variables.

Responses to some of the responses:

I am not refreshing. The code I posted will not be run because the user has logged in, so the "if" is false. It should test if he is logged in, return true and move onto the rest of the file that includes this. I only posted it to show the "session_start()".

Also, two of you mentioned that I should use 'header("Location:Login.htm");' instead of echoing a refresh. Why is that?

Thanks again all

Tom

ergophobe

5:49 pm on Jul 7, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I noticed too late that the if meant the refresh would only fire if not logged in. Sorry for the confusion

As for the "header" versus refresh

- header is server side and does not depend on the client and therefore is more reliable.
- it does not require anything to be sent to the client before refreshing, so it's faster/lower bandwidth
- header potentially lets you set any http header you want and send a redirect code or not, etc etc etc

There are probably additional reasons.

ergophobe

5:54 pm on Jul 7, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




I suspect I'll be trying httpwebwitch's suggestion first.

It should work fine.

The reason I suggested assigning

$_SESSION['post_vars'] = $_POST;

is because I don't know if there might be collisions between the post vars from the form and already existing session vars. You will need to watch for that if you use httpwebwitch's method. If there are no such collisions possible, it will be a much more convenient way (less typing).

Second, make sure you unset the session vars when you are done with them. Remember, they are persistent by nature, so you will have to make sure they go away when you want them too. That's one other advantage of assigning everything to $_SESSION['post_vars'].

Once the form is repopulated, you can just say
unset $_SESSION['post_vars'];

Tom

tryan

8:38 pm on Jul 7, 2004 (gmt 0)

10+ Year Member



Ah, collisions. I'll watch for that, thanks. I'm still a bit of a newbie at php, so I don't think of all these things yet. But there's lots more work coming. Best way to learn and all...

And BTW, httpwebwitch's code is working beautifully - at least on the type="text" fields. Now I have to do the checkboxes and radio buttons... a little more complicated. I think.

Thanks again all

Tom

httpwebwitch

2:51 pm on Jul 8, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



hmm... yes, collisions. take his advice; be careful.

Since you're using sessions for login/authentication, you're opening up a security gap by throwing all the POST variables in there indiscriminately. It's the same problem as having register_globals turned on - someone could throw a POST value into your page called "username", and that would trickle into your sessions and allow them access without ever having entered a valid password.

httpwebwitch

2:58 pm on Jul 8, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



For radios and checkboxes, use the ternary operator to determine whether to write the CHECKED attribute into the input tag.

condition?true:false

checkboxes:

<input type="checkbox" name="signup" value="1"<?php print($_SESSION['signup']?'CHECKED':'')?>>

radios:

<input type="radio" name="gender" value="male"<?php print($SESSION['gender']=='male'?'CHECKED':'')?>>Male

<input type="radio" name="gender" value="female"<?php print($SESSION['gender']=='female'?'CHECKED':'')?>>Female

ergophobe

3:18 pm on Jul 8, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




It's the same problem as having register_globals turned on - someone could throw a POST value into your page called "username",

That is, in fact, the specific collision I was thinking of.

Tom

tryan

7:09 pm on Jul 8, 2004 (gmt 0)

10+ Year Member



Okay, I see.

I'll try '$_SESSION['post_vars'] = $_POST;' and 'unset($_SESSION['post_vars'])'. It's not as clear how I'll access the individual values to refill the form, but that, too, I'll figure out.

Will that solve the security problem httpwebwitch mentioned?

And thank you httpwebwitch for the code for the checkboxes and radios. I had already figured it out, except I used if's instead of ternary. I always forget the ternary operator.

Tom

ergophobe

7:20 pm on Jul 8, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




I'll try '$_SESSION['post_vars'] = $_POST;' and 'unset($_SESSION['post_vars'])'. It's not as clear how I'll access the individual values to refill the form, but that, too, I'll figure out.

Exactly the same way, but you're one more index down in your array. So instead of

$_SESSION['field1']

you use

$_SESSION['post']['field1']

This works in other contexts too

foreach ($_SESSION['post'] as $key=>$val)

is perfectly valid.


Will that solve the security problem httpwebwitch mentioned?

As long as you don't overwrite a session var that is used to check login, yes.

tryan

7:42 pm on Jul 8, 2004 (gmt 0)

10+ Year Member



Will that solve the security problem httpwebwitch mentioned?


As long as you don't overwrite a session var that is used to check login, yes.

Ah, I see. So that:

$_SESSION['post_vars']['username']
doesn't collide with
$_SESSION['username']

Always learning, I am...

Tom

ergophobe

8:16 pm on Jul 8, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Exactly. If you put your post vars in one element of the $_SESSION super global, you won't overwrite anything. If you automatically put your $_POST vars in a $_SESSION using the same array index, you'll have to be more careful.

So

$_SESSION['post']['username'] = $_POST['username'];

will almost always be safe

$_SESSION['username'] = $_POST['username'];

might start causing problems and it might take you a long time to figure out the source when you change your code six months from now and erratic things start happening.

Tom

httpwebwitch

2:10 pm on Jul 9, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Those are some excellent suggestions. I'm going to do that from now on.

ergophobe

2:35 pm on Jul 9, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ah. Happy to have offered a new trick to an old (er, make that "a very young I'm sure") dog.

Cheers,

Tom

Notawiz

10:28 am on Jul 10, 2004 (gmt 0)

10+ Year Member



Perhaps not completely "to the point", but in one of the tutorials on the Zend website, I've found this IE6 fix:
header("Cache-control: private"); //IE 6 Fix
to keep the already entered information in a form.
Perhaps this can help someone.

tryan

3:45 pm on Jul 14, 2004 (gmt 0)

10+ Year Member



This could be a separate thread, except it directly follows on some of the info generated earlier in this one. So:

buildYearDD(1955,-20,"hdobyear");

calls this function in an included file:

function buildYearDD($startYear,$endOffset,$elemName){
$i = $startYear;
$end = (date(Y)+$endOffset);
print "<select name=\"$elemName\">\n";
print "<option>----</option>\n";
while ($i <= $end){
print "<option";
if($_SESSION['post_vars']['$elemName'] == $i){print ' selected';};
print ">".$i;
print "</option>\n";
$i += 1;
}
print "</select>";
}

and builds a drop down (selection list) listing years where $startYear is the lowest yaer in the list, $endOffset is where I want it to end relative to the current year (like -5 would end the list at 1999...),$elemName is the name of the html <select> element.

The "if" line is irrelevant unless you are going Back to the page and want to reload the data as it appeared before submitting.

The problem is that it doesn't work when I do click Back. And it has to do with the way I'm attempting to concatenate the variable, $elemName, in that line. When I hardcode the name of the element it works fine.

So it's a simple syntax problem. Right?

How should that be written? I've tried dots, quotes, double quotes, prints.

I hate asking such an elementary question, but I'm stumped.

humbly, Tom

ergophobe

4:09 pm on Jul 14, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Normally, when you use the back button, the page does NOT reload, so your PHP file wouldn't be getting called at all. What happens if you completely clear the cache and whatnot and then go back?

Tom

tryan

5:39 pm on Jul 14, 2004 (gmt 0)

10+ Year Member



ergophobe

You, httpwebwitch and I already resolved that part of this conversation in the earlier postings of the thread. It wasn't reloading the form when I hit Back until I did what you said and wrote all the $_POST variables into a $_SESSION variable, then read them out of it when I re-opened the form. That works great.

if($_SESSION['post_vars']['$elemName'] == $i){print ' selected';};
is attempting to do just that. It works when I write it:
if($_SESSION['post_vars']['hdobyear'] == $i){print ' selected';};
, or when it's hardcoded into the form code, but using the passed variable ($elemName) stops it. It seems to ignore the whole line and doesn't select any one of the <option>'s.

So my question is, what's wrong with my syntax? How should the variable be concatenated into that line?

A little more detail:
The function call is in the .php page that renders the form (for the sake of this discussion, let's call it enterNewGuy.php). The function definition is in a separate "included" file called common.php along with some other functions.

Make sense?

Tom

ergophobe

10:33 pm on Jul 14, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Lots of sense. I get it now.


if($_SESSION['post_vars']['$elemName'] == $i)

What's wrong with my syntax?

Easy. You are using the index '$elemName' which is a STRING, you want the VARIABLE, so you need to lose the quotes, like so:

$_SESSION['post_vars'][$elemName]

Because
if $elemName = "hboday"

$_SESSION['post_vars']['$elemName']!= $_SESSION['post_vars']['hboday']

$_SESSION['post_vars'][$elemName] == $_SESSION['post_vars']['hboday']

Tom

tryan

1:06 am on Jul 15, 2004 (gmt 0)

10+ Year Member



Aww *&%$#! <knocking heel of hand on forehead>

Could you guess I do this for a living? I doubt it'll surprise you that it's working now.

D'ya ever have one of those... oh never mind. Thanks

Tom

jatar_k

2:42 am on Jul 15, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



no worries tryan, we all do, that's why we post here :)

ergophobe

2:41 pm on Jul 15, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Could you guess I do this for a living?

Well, I mostly don't do it for a living, but I consider myself fairly experienced. I have lost count of the number of times I have spent the better part of a day tracking down some PHP syntax error that I knew was wrong since my first day of learning PHP.... in fact, I think it happened a few days ago.

Tom