Logical clean up - php

I am currently having logical structure errors and I can't seem to think of a proper way of writing it out so it looks clean. Currently, I have a table in my database named USER. User has 6 fields out of the many, named: first, second, third, fourth, fifth, sixth.
What my code does is switch the data with two of the fields. So for example: the data in first is changed with the data in sixth.
Before: First - 1, Sixth - 6
After: First - 6, Sixth - 1
Currently, what I have is something that looks very messy, and I'm not sure how I can clean it up.
if($switch == true){ /* $switch just indicates if the numbers being switched is one of the fields i.e. first, second, etc.. */
if($slot == 1){ // The number is being switched into the first slot
if($first == $number){
return 1; // error, can't switch with itself
} else if ($second == $number){
$temp = $first;
// 1st QUERY TO UPDATE THE DATA IN FIRST, WITH THE DATA IN THE SECOND
// 2nd QUERY TO UPDATE THE DATA IN SECOND, WITH THE INFO STORED IN VARIABLE $temp
} else if ($third == $number){
$temp = $first;
// 1st QUERY TO UPDATE THE DATA IN FIRST, WITH THE DATA IN THE THIRD
// 2nd QUERY TO UPDATE THE DATA IN THIRD, WITH THE INFO STORED IN VARIABLE $temp
} // ... continues to check for 4, 5, 6...
} else if($slot == 2){ /* Then checks to see if it was slot 2, i.e. Second */
// ....
} else if($slot == 3){ /* Then checks to see if it was slot 3, i.e. Third */
// ....
} else if($slot == 4){ /* Then checks to see if it was slot 4, i.e. Fourth */
// ....
} else if($slot == 5){ /* Then checks to see if it was slot 5, i.e. Fifth */
// ....
} else if($slot == 6){ /* Then checks to see if it was slot 6, i.e. Sixth */
// ....
}
}
It continues for each slot, , 6 times each... I know it's bad programming but I have just started learning PHP (it's my first language, so bear with me). Any suggestions on what I can do to make this cleaner? Or even a better way of writing it? If anyone cares to explain to me over Skype or anything, I would be really grateful. Thank you.

Use a switch statement:
if($switch == true){
switch($slot) {
case 1 :
if($first == $number){
return 1; // error, can't switch with itself
} else if ($second == $number){
$temp = $first;
// 1st QUERY TO UPDATE THE DATA IN FIRST, WITH THE DATA IN THE SECOND
// 2nd QUERY TO UPDATE THE DATA IN SECOND, WITH THE INFO STORED IN VARIABLE $temp
} else if ($third == $number){
$temp = $first;
// 1st QUERY TO UPDATE THE DATA IN FIRST, WITH THE DATA IN THE THIRD
// 2nd QUERY TO UPDATE THE DATA IN THIRD, WITH THE INFO STORED IN VARIABLE $temp
}
break;
case 2 :
// ....
break;
case 3 :
// ....
break;
case 4 :
// ....
break;
case 5 :
// ....
break;
case 6 :
// ....
break;
default:
// ...
}
}
You will notice a default at the bottom. It's always good to have one in place in case none of your conditions match.
Also notice the break keyword. Without it the code block does not stop at the end and will "fall through" to the next block. This can be handy sometimes but not in your case.

You could do something like this:
// This function returns the column name for the specified slot
function getSlotColumn($slotNum)
{
switch($slotNum)
{
case 1:
retrun "first";
case 2:
return "second";
......
}
}
then in the switching function
// This function swaps the values of the two specified slots
function swapValues($slot1Num, $slot2Num)
{
if($slot1Num == $slot2Num) return;
if($slot1Num < 1 || $slot1Num > 6) return;
if($slot2Num < 1 || $slot2Num > 6) return;
$slot1Col = getSlotColumn($slot1Num);
$slot2Col = getSlotColumn($slot2Num);
//get value of the first slot
$slot1Val = //SELECT $slot1Col FROM ... WHERE ... slot
// Now since we have the value of the first slot, we can update it from the second slot with this pseudo query
//UPDATE ... SET $slot1Col = $slot2Col WHERE ...
// Then update second slot from the value in $slot1Val
//UPDATE ... SET $slot2Col = $slot1Val WHERE ...
}
Then use it like this:
if(switch == true)
{
swapValues(1, 6);
}

Related

adding up sums of multiple variables in php

ok
so I have been stuck on this problem for a while and I'm sure there is a more elegant way of doing it.
I have 3 columns in a database -
Stand1 | Stand2 | Stand3
each column will either have a stand number (i.e D30) or 'Not Assigned'
What I need to do is count how many stands have been assigned to that customer.
For example :
D30 | not assigned | not assigned would = 1
D30 | B30 | E30 = 3
The code I have so far is
if ($row["stand1"] == 'Not Assigned') {
$stand1 = '0';
}
else {
$stand1 = '1';
}
if ($row["stand2"] == 'Not Assigned') {
$stand2 = '0';
}
else {
$stand2 = '1';
}
if ($row["stand3"] == 'Not Assigned') {
$stand3 = '0';
}
else {
$stand3 = '1';
}
I then thought I could try and count how many stand were assigned :
$standcount = $stand1 + $stand2 + $stand3
But when I print this out (everything else is in an array so loops through every customer) all I get is the total 3 for every customer.
I tried saving the data into an array like:
$standcount = array($stand1, $stand2, $stand3);
But I get the same result. I thought a foreach loop may work but not sure how to do it.
I would suggest you to:
Set the columns' default value to NULL, so that if no value is provided in an entry you'll have a null value instead of a string (that can contains different letters, as in your case). After that you can simply perform the isset() check against each value.
Use a function to avoid code repetition (the main source of errors), something like:
function check($value) {
return (isset($value)) ? 1 : 0;
}
$stand_1 = check($row["stand1"]);
$stand_2 = check($row["stand2"]);
$stand_3 = check($row["stand3"]);
If you instead want to use a string as "Not Assigned" or "NA", you can perform a case-insensitive check with strcasecmp() between the strings in case, for any reason, a value contains an extra space or a lower-case letter.
In this case the check function would be:
function check($str) {
return (strcasecmp($str, "NA") == 0) ? 0 : 1;
}
$stand_1 = check($row["stand1"]);
$stand_2 = check($row["stand2"]);
$stand_3 = check($row["stand3"]);

How to filter foreach array for integers

I have a for-each statement based off a php generated query..
I am trying to figure out how I can make sure all the IDDestinations of the records are the same.
For example in my current query I have 2 records with an IDDestination of 12, one record with an IDDestination of 9 and the last is 3.
I know how to do this in the query but I am trying to generate a message to the user if the IDDestinations are not equivalent.
My code so far.
foreach($results as $row) {
$IDDestination =(int) $row['IDDestination'];
if ($IDDestination == $IDDestination){
echo "<script>alert('All Courses Match Destination.');</script>";
} else {
echo "<script>alert('Courses have different Destinations);</script>";
}
var_dump($IDDestination);
}
This is currently just verifying that each record has an IDDestination Present and tells ME All courses Match.
How can I make it so the INTEGERS are equivalent and give me the same message?
Here's one way; use a variable outside your loop to determine if it's ok or not:
$everything_matches = true;
$id = null;
foreach($results as $row) {
// Set it for the first record.
if($id === null)
$id = $row['IDDestination'];
// If the current iteration's ID matches the first record, $everything_matches
// will stay true, otherwise it's false and we should kill the loop.
if($id != $row['IDDestination']) {
$everything_matches = false;
break;
}
}
// Output your message
$message = $everything_matches ? 'All courses match destination.' : 'Courses have different destinations.';
echo '<script>alert("' . $message . '");</script>';

Re-run function if false

I'm working on code that takes a random value, checks if it's correct with a few checks and if it is, it'll return it. If it isn't, it's supposed to rerun the function untill one that does is found.
If the random value is correct it'll set a var to 1 like this: $chosen = 1; and then using a while loop it'll keep running the current function untill it's 0:
public function generate_chair($id, $optredenID)
{
$model = new Model_Shop;
// Get all the chairs for the given room
$chairs = $model->check_chair($id);
// Get an array of reserved chairs for a given event
$reserved = $model->get_reserved($optredenID);
do {
// If chosen = 0, all chairs are available.
// If chosen = 1, one of the chairs is not available
$chosen = 0;
// Create a new empty array
$rand_chairs = array();
// Pick a random chair
$chair = array_rand($chairs);
// Based off the amount chosen in the dorpdown, build array
switch($_POST['AantalPlaatsen']) {
case '1':
array_push($rand_chairs, $chair);
break;
case '2':
array_push($rand_chairs, $chair);
array_push($rand_chairs, $chair+1);
// Check if the chair chosen is the last chair in a row
// If it is, check for another chair
if($chair == 20 || $chair == 40 || $chair == 60 || $chair == 80 || $chair == 100 || $chair == 120 || $chair == 140 ||$chair == 160 ||
$chair == 180 || $chair == 200) {
$chosen = 1;
}
break;
case '3':
array_push($rand_chairs, $chair);
array_push($rand_chairs, $chair+1);
array_push($rand_chairs, $chair+2);
break;
case '4':
array_push($rand_chairs, $chair);
array_push($rand_chairs, $chair+1);
array_push($rand_chairs, $chair+2);
array_push($rand_chairs, $chair+3);
break;
}
// Check if one of the random generated chairs is in the reserved array
// If so, the chair is unavailable and new random must be generated
if( count(array_intersect( $rand_chairs, $reserved )) != 0 ) {
$chosen = 1;
}
} while ($chosen == 1);
return $rand_chairs;
What I wanted works now, but I'm wondering if anyone has a idea for another issue.
As shown in the switch-case, when the customer chooses 2 chairs and the first one is at the end of a row, it has to check for a new chair, because you can't spread multiple chairs over multiple rows.
The way I do this is with alot (too many) if statements. Does anyone know a better solution?
Why are you using recursion here? Why not just repeat the part of the function which you need to rerun?
do {
$chosen = 0;
// create a new empty array
$rand_chairs = array();
// Pick a random chair
$chair = array_rand($chairs);
...
foreach($rand_chairs as $key) {
if(in_array($key, $reserved)) {
$chosen = 1;
break; // oops, we need to rerun
}
}
} while( $chosen == 1 )
This uses a do-while control structure, which runs through the body at least once.
The break statement exits out of the while loop early, since the key has been found.
Additionally, instead of the foreach statement, you could use array_intersect():
if( count(array_intersect( $rand_chairs, $reserved )) != 0 ) {
$chosen = 1;
}
Faster algorithm would go something like this: you would run it one row of seats at a time, since "sitting at opposite ends of adjacent rows" isn't really "sitting together"...
Boolean seatsTaken()
int startsAt(), runLength()
For each row in seatsTaken
adjacent = 0
seat = 0
while not row(seat):
++adjacent
if adjacent > 0:
startsAt.push(seat-adjacent)
runLength.push(adjacent)
When this is done you have an array of all the blocks. Select only the blocks that are big enough (runLength() >= needed) and randomly choose one of them

php: looping thru results from mysql query to increment counter (associative array)

I'm retrieving data from a MySQL db and creating reports from it. I need to get counts when certain conditions are met, and since db queries are rather expensive (and I will have a lot of traffic), I'm looping thru the results from a single query in order to increment a counter.
It seems like it's working (the counter is incrementing) and the results are somewhat close, but the counters are not correct.
At the moment, there are 411 records in the table, but I'm getting numbers like 934 from a ['total'] counter and 927 for ['males'], and that definitely can't be right. However, I get 4 from ['females'], which is correct…
I'm pretty sure it was working last night, but now it's not—I'm quite baffled. (there are still just 411 records)
$surveydata = mysql_query("SELECT `age`,`e_part`,`gender` FROM $db_surveydata;") or die(mysql_error());
$rowcount = mysql_num_rows($surveydata);
$age=array('18+'=>0,'<18'=>0,'total'=>0);
$e_part=array('yes'=>0,'no'=>0,'total'=>0);
$genders=array('male'=>0,'female'=>0,'trans'=>0,'don\'t know'=>0,'total'=>0);
while ($responses = mysql_fetch_assoc($surveydata)) {
foreach ($responses as $response){
switch ($response){
case $responses['age']:
if ($responses['age'] > 18) {$age['18+']++;$age['total']++;}
// i tried putting the ['total'] incrementer in the if/else
// just in case, but same result
else {$age['<18']++;$age['total']++;}
break;
case $responses['e_part']:
if ($responses['e_part']) {$e_part['yes']++;}
else {$e_part['no']++;}
$e_part['total']++;
break;
case $responses['gender']:
switch ($responses['gender']){
case 1:$genders['male']++;break;
case 2:$genders['female']++;break;
case 3:$genders['trans']++;break;
case 9:$genders['don\'t know']++;break;
default:break;
}
$genders['total']++;
break;
default:break;
} // end switch
} //end for
} // end while
thanks!
this is the problem:
foreach ($responses as $response){
switch ($response){
case $responses['age']:
switch $responses looks for match
foreach ($responses as $k=>$v){
switch ($k){
case 'age':
if ($v > 18) ....
mysql_fetch_assoc() retrieves a single row from the table. You then loop over that row, processing each individual field. Then the long set of if() checks to determine which field you're on. That entire structure could be changed to:
while($response = mysql_fetch_assoc($surveydata)) {
if ($responses['age'] > 18) {
$age['18+']++;
} else {
$age['<18']++;
$age['total']++;}
if ($responses['e_part']) {
$e_part['yes']++;
} else {
$e_part['no']++;
}
$e_part['total']++;
switch ($responses['gender']){
case 1:$genders['male']++;break;
case 2:$genders['female']++;break;
case 3:$genders['trans']++;break;
case 9:$genders['don\'t know']++;break;
default:break;
}
$genders['total']++;
}
There's no need for the switch ($response); you can't really switch on an array like that. And even if you could, the 'values' you get wouldn't make any sense -- i'm thinking if it works at all, the value you're switching on would be either 'Array' or the length of the array. (I forget how PHP handles arrays-as-scalars.)
You'll want something like this...
$total = 0;
while ($response = mysql_fetch_assoc($surveydata))
{
if (isset($response['age']))
{
++$age[($response['age'] < 18) ? '<18' : '18+'];
++$age['total'];
}
if (isset($response['e_part']))
{
++$e_part[($responses['e_part']) ? 'yes' : 'no'];
++$e_part['total'];
}
if (isset($response['gender']))
{
switch ($response['gender'])
{
case 1: ++$genders['male']; break;
case 2: ++$genders['female']; break;
case 3: ++$genders['trans']; break;
case 9: ++$genders["don't know"]; break;
}
++$genders['total'];
}
++$total;
}
The benefit of the if (isset(...)) is that if 'age', 'e_part', or 'gender' is null, the corresponding code to count it won't get activated. It does about the same thing as your code, minus the embarrassing loop -- and minus the counting of the field even though it is null, because every row will have the same fields.

Categorizing non-ID categories PHP loop

On my project there're various search results of different content-types. For unimportant reasons, not all content-types carry a unique ID. However, I tried to write this loop that will detect IDless content-types, and will give them a unique ID.
Basically, the results look like this:
Category ID 3
Category ID 3
Category ID 4
NON-ID Category 1
NON-ID Category 2
[...]
I tried this:
$current = $result->section;
// if there's a category ID -- use it
if ($current != null) echo $result->sectionid;
else
// if this is the first IDless category -- initialize. this happens once.
if ($virginity == true) {
$store = $current;
$virginity = false;
}
// if initialized and current category string is the same as stored category string -- print it
if (($virginity == 0) && ($store = $current)) {
echo $defaultID;
}
// if initialized and current category string is different from the stored category string -- set new default category +1 and print it
if (($virginity == false) && ($store != $current)) {
$defaultID = $defaultID++;
echo $defaultID;
$store = $current;
}
Can you see where I'm going here?
Trying to give each new category that comes up in the search results a unique ID, on the next loop session - check if the category string is same as the previous one, if so -- use the same ID, else -- bump ID by 1, print the new ID and store a new category.
However: This doesn't work properly.
Why?
Your code is a little tough to read, but a big red flag I see is this block:
//You have a single equals sign here v
if (($virginity == 0) && ($store = $current))
{
echo $defaultID;
}
That means that as long as $virginity==0, that line will always be run, and $store will always equal $current.
By the way, I'm going to recommend some reformatting and readability suggestions. Take them or leave them , though, it's just my opinion.
$current = $result->section;
if ($current != null)
{//if one of the results has brackets, put brackets on both
echo $result->sectionid;
}
else if ($virginity == true)
{// if this is the first IDless category -- initialize. this happens once.
$store = $current;
$virginity = false;
}
//you're setting $virginity=false or true, so doing !$virginity makes sense
// if it was actually a number, then comparing to 0 is better
// also, use parentheses only where really needed, otherwise it's just clutter
if (!$virginity && $store == $current)
{
echo $defaultID;
}
if (!$virginity && $store != $current)
{// if initialized and current category string is different from the stored category string -- set new default category +1 and print it
$defaultID = $defaultID++;
echo $defaultID;
$store = $current;
}

Categories