Does anyone know why this simple bit of code wont work? The second loop doesnt seem to take place.
while(list($get_key, $get_value) = each($HTTP_GET_VARS)) {
if (!${$get_key}) {
${$get_key}=$get_value;
}
}
while(list($keyone, $valueone) = each($HTTP_GET_VARS))
{
echo $keyone;
}
Your problem here is the use of each(). It remembers the index it has reached in the array so in your second loop there is nothing left to loop out so it evaluates to false. If you use reset() this should resolve the issue.
while(list($get_key, $get_value) = each($HTTP_GET_VARS)) {
if (!${$get_key}) {
${$get_key}=$get_value;
}
}
reset($HTTP_GET_VARS);//will put the pointer back to the first element
while(list($keyone, $valueone) = each($HTTP_GET_VARS))
{
echo $keyone;
}
Alternatively you can just use the foreach(){} syntax which will always start from the first element in the array.
Related
i'm sorry if my english not good.
I have a problem in my code. how I can stop access when in my array have duplicate. I mean, when one or more data in array have duplicate, user must repeat input from first page. and when array have not duplicate, user can access next page.
this is my code I have try.
$no_id=array('100100','100200','100300','100200','100200','100100');
$array = array();
foreach ($no_id as $key => $value)
{
if(isset($array[$value]))
{
$array[$value] += 1;
} else
{
$array[$value] = 1;
}
}
foreach ($array as $alert => $n)
{
if($n >= 2)
{
header('location:../../home');
} else
{
header('location:../../questionnair');
}
}
but when found the duplicate data (in array 100100 have two data and 100200 three data), the system still bring user to access questionnair page, not home.
thanks for helping.
I think the main problem is that you should always use exit() after using header() with location, otherwise the page will continue to execute.
This would still cause a problem though if the first value was a unique value as the first loop would always exit;.
You could fix this (only ever call header() if the value is > 2, then the default of all are unique is after the loop), but an alternative is to use array_count_values() which counts how many each value exists in the list and then use max() to find the most occurring one, then test against that...
$no_id=array('100100','100200','100300','100200','100200','100100');
$n = max(array_count_values($no_id));
if($n >= 2)
{
header('location:../../home');
exit;
} else
{
header('location:../../questionnair');
exit;
}
Update:
An alternative and slightly quicker version would be to use your original first loop, but as soon as it detects the value is already set, then it can stop working and just return then...
$no_id=array('100100','100200','100300','100200','100200','100100');
$array = array();
foreach ($no_id as $key => $value)
{
if(isset($array[$value]))
{
header('location:../../home');
exit;
} else
{
$array[$value] = 1;
}
}
header('location:../../questionnair');
exit;
If you just need to check if the array does have dupliate, you can use array_unique and compare the new array with the old array. If the arrays are not the same, it means there are duplicates.
With code:
$no_id = array('100100','100200','100300','100200','100200','100100');
$new_array = array_unique($no_id);
if (count($no_id) == count($new_array)) {
// 2 arrays have same number of items => they are equal => no duplicates
$redirect = "questionnair.php";
} else {
// 2 arrays have different number of items => they are not equal => duplicates
$redirect = "home.php";
}
header("location: {$redirect}");
NOTE
You have to redirect to an another PHP page (ex. home.php and not just home).
First of all, it's simplier to use array_unique function, which will remove all duplicated values.
After that you can make checks, if nothing was changed, then there is no duplicated items.
Like this:
$no_id=array('100100','100200','100300','100200','100200','100100');
$no_id_unique = array_unique($no_id);
if(count($no_id)===count($no_id_unique)){
header('location:../../questionnair');
}else{
header('location:../../home');
}
exit();
Next thing that you using ../ in path which means go to parent directory.
I don't know your environment, but must likely it's a bad idea.
According to documentation it's better to specify full url of page where user must be forwarded:
header("Location: http://www.example.com/home/");
Also, please be aware, that you need to prevent all others output from a script, especcially before the header() call. Read more here.
you can use foreach (array_unique($no_id) as $key => $value)
You can use array_count_values for this, not tested, but could be like:
$counts = array_count_values($no_id);
$duplicate = false;
foreach ($no_id as $value) {
if ($counts[$value] > 1) {
$duplicate = true;
break; // found a duplicate, no need to check further.
}
}
if ($duplicate === true) {
header('location:../../home');
} else {
header('location:../../questionnair');
}
Using array_flip()
$no_id = array('100100','100200','100300','100200','100200','100100');
$no_id_unique = array_flip($no_id);
if(count($no_id) === count($no_id_unique)){
header('location:../../questionnair');
}else{
header('location:../../home');
}
exit();
I have a piece of code as following:
while ( $conver = mysqli_fetch_assoc($converQ)) // for each conversation
{
$group_mark = array();
if ($conver['send_from'] == 1) // send from group
{
if (in_array($conver['sender_id'], $group_mark))
{
continue;
}
else
{
array_push($group_mark, $conver['sender_id']);
}
...
In the beginning of the while-loop, I have to check whether the conversation is from group or individual. If it is from group, I should check whether the id has appeared or not. But now the continue can not stop executing the following code in the while-loop and start the next loop. I think the reason is that its outer function is if-else but not the while-loop directly. Could you please tell me how to edit the code to do what I want? Thank you in advance!
EDIT:
I have tried this: continue 2 but it doesn't work. Why?
Thanks to #ThinkingMedia, I know what's the problem now. I put the $group_mark in the wrong place. Sorry.
In these cases which you want to stop check other rows you can develop a function and return as true in the location which you need:
function check()
{
while ( $conver = mysqli_fetch_assoc($converQ)) // for each conversation
{
$group_mark = array();
if ($conver['send_from'] == 1) // send from group
{
if (in_array($conver['sender_id'], $group_mark))
{
return true;
}
else
{
array_push($group_mark, $conver['sender_id']);
}
}
}
}
Your code is right. But continue does not jump off those if/else statements.
In php docs they say is deprecated: continue {var}
5.4.0 Removed the ability to pass in variables (e.g., $num = 2; continue $num;) as the numerical argument.
You can modify your code as follows:
while ( $conver = mysqli_fetch_assoc($converQ)) // for each conversation
{
$group_mark = array();
if ($conver['send_from'] == 1) // send from group
{
if (!in_array($conver['sender_id'], $group_mark)) {
array_push($group_mark, $conver['sender_id']);
}
}
...
}
Found some interesting, curious about why your $group_mark = array(); is in the while loop. It seem like this will get overwrited and will not able to hit the if condition, because of the group_mark always is empty array.
Try to move this to before of your while loop. This should solve and get what you need.
When dealing with arrays I am forced to add a bunch of repetitive code to handle arrays with one child versus multiple:
//If more than one step, process each step, elcse processs single
if(!array_key_exists('command',$pullcase['steps']['step'])) {
foreach($pullcase['steps']['step'] as $step) {
$command=$step['command'];
$parameter=$step['parameter'];
if(isset($step['value'])){
$value = $step['value'];
$this->runCommands($command,$parameter,$value);
} else {
$this->runCommands($command,$parameter);
}
}
} else {
$command = $pullcase['steps']['step']['command'];
$parameter = $pullcase['steps']['step']['parameter'];
if(isset($pullcase['steps']['step']['value'])){
$value = $pullcase['steps']['step']['value'];
$this->runCommands($command,$parameter,$value);
}
else { $this->runCommands($command,$parameter); }
}
As you can see, I'm having to duplicate my efforts depending on if there is a single item in an array versus multiple:
$pullcase['steps']['step'][0]['command']
vs
$pullcase['steps']['step']['command']
How can I simplify this code so that I can use a single variable for all instances?
If you control the creation of the array, make step an array of one even if there is only one so you always have an array. Is that possible?
You either have a step array [step][0][command] or you have a single step [step][command]. So when you create the array instead of [step][command] make it [step][0][command] etc. Standard way of doing it, problem solved as you only need the foreach.
If you can't do it at array creation then consider doing it before the loop:
if(is_array($pullcase['steps']['step'])) {
$steps = $pullcase['steps']['step'];
} else {
$steps[] = $pullcase['steps']['step'];
}
foreach($steps as $step) {
$value = isset($step['value']) ? $step['value'] : null;
$this->runCommands($step['command'], $step['parameter'], $value);
}
Also, if runCommands() can detect a empty argument, then an alternative to the if/else for the function call is used above.
The following may help. It doesn't do much but call the function "runcommands" on a value if the key is 'command'. I am using it to show how you can use array_walk_recursive to possibly solve your problem.
First, you need the function to use:
function runcommandswhencommand($value, $key)
{
if($key == 'command') runcommands($value);
}
Now, you can use the recursive walk on your array:
array_walk_recursive($pullcase, 'runcommandswhencommand');
With this, whenever the key is 'command', the value of that index will be used in the parameter of the function runcommands().
Here's my code:
function prepare_machine($variables)
{
foreach ($variables AS $varname => $vartype)
{
if (isset($_REQUEST[$varname]))
{
$value = $_REQUEST[$varname];
return do_clean($value, $vartype);
}
else
exit;
}
}
It is called like this:
prepare_machine(array('order_by_time' => TYPE_BOOLEAN));
it all works fine, but if you have multiple things in the array, for examples;
prepare_machine(array('order_by_time' => TYPE_BOOLEAN, 'order_by_date' => TYPE_BOOLEAN));
it will only do anything with the first one.
Can anybody see what is wrong with my code?
Thanks
You're doing a return ... when you find a match in your inner loop. That's why it only processes one.
Also, you should be using array_key_exists($varname, $_REQUEST) because isset($_REQUEST[$varname]) will fail if $_REQUEST[$varname] is null.
return returns whatever you give it, and exits the function. You need to change your function somehow so that it only returns after processing all the variables.
I'm using references to alter an array:
foreach($uNewAppointments as &$newAppointment)
{
foreach($appointments as &$appointment)
{
if($appointment == $newAppointment){
$appointment['index'] = $counter;
}
}
$newAppointment['index'] = $counter;
$newAppointments[$counter] = $newAppointment;
$counter++;
}
If I print the array contents, then I receive the expected result. When I iterate over it, all elements seem to be the same (the first).
When I remove the reference operator & in the inner array, all goes normal, except index isn't set.
Using references in foreach loops is asking for trouble :) I've done that several times, and I always rewrote that code.
You should to it as well. Like this:
foreach($uNewAppointments as $newAppointmentKey => $newAppointment)
{
foreach($appointments as $appointmentKey => $appointment)
{
if($appointment == $newAppointment){
appointments[$appointmentKey]['index'] = $counter;
}
}
$uNewAppointments[$newAppointmentKey]['index'] = $counter;
$$uNewAppointments[$newAppointmentKey][$counter] = $newAppointment;
$counter++;
}
Though I have just rewritten it "mechanically", so it will probably not work. But it's to get the idea of how to achieve the same effect, without the side effects. You are still modifying the original arrays in this loop.
If you do this, you must unset $newAppointment when you exit the loop. Here is the relevant entry.