PHP array has the same index for every element - php

I'm working on a program that prints the qualities of every individual in a team.
I have 3 tables:
The Teams table:
TeamID
1
2
The TeamPlayers table :
PlayerID
Team
100
1
269
1
357
2
The program works like this: There is a textbox in the HTML page where the user is typing the ID of the team and the program outputs the members. The problem is that each player is stored in an array. and all have the same index:
$fetchPlayersSQL = "SELECT Player_ID
FROM TeamPlayers
WHERE Team = $TeamID;";
$fetchPlayers = ibase_query($dbConnection, $fetchPlayersSQL);
while ($row2 = ibase_fetch_object($fetchPlayers)) {
$fetchPlayersArray = get_object_vars($row2);
print_r($fetchPlayersArray);
}
Keep in mind $TeamID is the value introduced by the user in the HTML textbox.
Now, this program outputs this:
Array ( [Player_ID] => 2157 )
Array ( [Player_ID] => 734 )
Array ( [Player_ID] => 2160 )
Array ( [Player_ID] => 3744 )
Array ( [Player_ID] => 2166 )
(Keep in mind, 2157, 734, 2160, 3744 and 2166 are other players, there are a lot of them, but I listed only a few)
The problem is that I need every player to have their own index in the array, because I have to print their qualities
I really can't find where the problem comes from. Maybe I am using an incorrect method to select since there are more players in a team.
The 3rd table is just the qualities of every player
PlayerID
Height
Weight
HairColor
100
187
80
black
357
167
67
grey
269
182
95
brown
And the expected output is something like this:
The user enters 1 in the HTML textbox, Team 1 players are 100 and 269 so they should see:
Array ( [0] => 2157 )
Array ( [1] => 734 )
echo $row2->Player_ID; just prints their IDs, we have player 100 and 269 in the Team 1, and this prints 100269

It might not be the most elegant solution, but you can always build that array yourself in a loop:
$a = array();
while ($row2 = ibase_fetch_object($fetchPlayers)) {
$a[] = $row2->Player_ID;
}
print_r($a);
See if that works for you, I am not able to code at the moment.

Related

How to create a three dimensional array from sql query PHP

I have 2 tables in a database, 1 of them are linked with a foreign key to the first one. Each row on table 1 is linked to multiple rows in table 2. I am trying to make a query that looks at a WHERE from table 2 and returns multiple rows from table 2 which are sorted into the rows they linked with in table 1 and then put this all into one big multi dimensional array, so it should work something like this:
$array[0][column_name][0] this would use row 1 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][0] this would use row 2 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][3] this would use row 2 from table 1 and give me a the 4th result in the column called column_name
etc
How can I query this and store it in a 3 dimensional array using PHP.
I have tried to word this in as clear manner as possible, if you are unsure what I am asking, please comment and I will update my question to make it clearer.
Assume that we have two tables, Company and Employee:
Company
------------------
ID Company_Name
1 Walmart
2 Amazon.com
3 Apple
Employee
---------------------------------
ID Company_Id Employee_Name
1 1 Sam Walton
2 1 Rob Walton
3 1 Jim Walton
4 1 Alice Walton
5 2 Jeff Bezos
6 2 Brian T. Olsavsky
7 3 Steve Jobs
8 3 Tim Cook
The easiest way to envision a multi-dimensional (nested) array is to mimic the looping required to get it: outer loop is the company, inner loop is the employees:
// ignoring database access, this is just pseudo code
$outer = [];
// select id, company_name from company
foreach $companyResult as $companyRow {
// select * from employee where company_id = ? {$companyRow['id']}
$inner= [];
foreach $employee_result as $employeeRow {
$inner[] = $employeeRow; // ie, ['id'=>'1','Company_Id'=>'1','Employee_Name'=>'Sam Walton']
}
$outer[] = $inner;
}
print_r($outer);
// yields ====>
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[Company_Id] => 1
[Employee_Name] => Sam Walton
)
[1] => Array
(
[id] => 2
[Company_Id] => 1
[Employee_Name] => Rob Walton
)
[2] => Array
(
[id] => 3
[Company_Id] => 1
[Employee_Name] => Jim Walton
)
[3] => Array
(
[id] => 4
[Company_Id] => 1
[Employee_Name] => Alice Walton
)
)
[1] => Array
(
[0] => Array
(
[id] => 5
[Company_Id] => 2
[Employee_Name] => Jeff Bezos
)
[1] => Array
(
[id] => 6
[Company_Id] => 2
[Employee_Name] => Brian T. Olsavsky
)
)
[2] => Array
(
[0] => Array
(
[id] => 7
[Company_Id] => 3
[Employee_Name] => Steve Jobs
)
[1] => Array
(
[id] => 8
[Company_Id] => 3
[Employee_Name] => Tim Cook
)
)
)
It is also possible to do if you use associative arrays. Consider the flat file that this query produces:
select company.id company_id, company.name company_name,
emp.id employee_id, emp.employee_name
from company
inner join employee on company.id = employee.company_id
-----
company_id company_name employee_id employee_name
1 Walmart 1 Sam Walton
1 Walmart 2 Rob Walton
1 Walmart 3 Jim Walton
1 Walmart 4 Alice Walton
2 Amazon.com 5 Jeff Bezos
2 Amazon.com 6 Brian T. Olsavsky
3 Apple 7 Steve Jobs
3 Apple 8 Tim Cook
Just use the primary IDs as the keys for your arrays:
$employeeList = [];
foreach($result as $row) {
$cid = $row['company_name'];
$eid = $row['employee_name'];
// avoid uninitialized variable
// $employeeList[$row['company_name']] = $employeeList[$row['company_name']] ?? [];
// easier to read version of above
$employeeList[$cid] = $employeeList[$cid] ?? [];
// assign it...
$employeeList[$cid][$eid] = $row;
}
Or, if you simply want each company row to hold an array of employee names,
$employeeList[$cid][] = $row['employee_name'];
The way that I've shown you is useful if you know the company_id and want to find the associated rows:
foreach($employeeList[2] as $amazon_guys) { ... }
But it's not at all useful if you're trying to group by employee, or some other field in the employee table. You'd have to organize the order of your indexes by your desired search order.
In the end, it's almost always better to simply do another query and let the database give you the specific results you want.

How to allow duplicate mysql row id in array?

My data in table t1 as below (only 2 record),
+-----------+-----------------+----------+
| shid | lvlmin | lvlmax |
+-----------+-----------------+----------+
| 1 | 1 | 10 |
| 2 | 5 | 10 |
+----------------------------------------+
My php code is:
$userinfo[0] = '9';
$ghunt = DB::fetch_all("SELECT shid FROM t1
WHERE lvlmin <= ".$userinfo[0]." AND lvlmax >= ".$userinfo[0].
"ORDER BY rand() LIMIT 5");
print_r($ghunt);
Result got 2 array:
Array ( [0] => Array ( [shid] => 2 ) [1] => Array ( [shid] => 1 ) )
How do I do when the array result is less than the LIMIT 5 in mysql query, auto use the array result in $ghunt to fill up the array?
What I mean is:
Array (
[0] => Array ( [shid] => 2 )
[1] => Array ( [shid] => 1 )
[2] => Array ( [shid] => 2 )
[3] => Array ( [shid] => 1 )
[4] => Array ( [shid] => 1 )
)
The shid can be random place in array.
Why don't you do something like this?
If (count($ghunt) < 5){
$realResultCount = count($ghunt);
for ($i = realResultCount; $i <= 5; $i++){
$ghunt[$i] = $ghunt[rand(0,realResultCount-1)];
}
}
Basically, what above code does is, if ghunt has less than 5 records in it, it tops it up to 5, by randomly selecting records out of initially returned records.
I don't code PHP, but I can describe one way you can achieve your goal simply. Most languages have a MOD operator, usually % - the php manual page for mod is here
It gives us the remainder of a division operation, so 10 mod 3 is 1, because 10 divided by 3 is 9 remainder 1
A useful property of MOD then, is that it always cycles between 0 and 1 less than what you're modding by. If you mod an incrementing number by 5, the result will always be 0,1,2,3,4,0,1,2,3,4 in a cycle. This means you can have a for loop with some incrementing number, mod by an array length and the result will be an integer that is certainly an array index. If the loop variable goes higher than the end of the array, the mod operator will make it wrap round to the start of the array again
MyArray[ 1746262848 mod MyArray.length ]
Will certainly not crash, even if the array only has 2 items
So for your case, just have a loop.. make he following pseudo code into PHP
// run the loop 5 times
For I as integer = 0 to 4 do
Print MyArray[ i mod MyArray.length ]
If you have 2 items in your array, A and B, it will simply print ABABA
If you have 3 items A B C it will print ABCAB
Hopefully this info will be helpful to you for implementing a solution in php for this, and many future problems. Mod can be really useful for implementing various things when working with arrays

php mysql check if vendor has 3 low consecutive ratings

on my ratings table for my software i have 4 fields.
id autoincrement
rvid vendor id
ratedate date of rating
rating the actual numeric rating
I have done alot with it over the last few months but this time im stumped and i cant get a clear picture in my head of the best way to do this. What i am trying to do is find out if the vendor has had 3 low 'consecutive' ratings. If their last three ratings have been < 3 then i want to flag them.
I have been playing with this for a few hours now so i thought i would ask (not for the answer) but for some path direction just to push me forward, im stuck in thought going in circles here.
I have tried GROUP BY and several ORDER BY but those attempts did not go well and so i am wondering if this is not a mysql answer but a php answer. In other words maybe i just need to take what i have so far and just move to the php side of things via usort and the like and do it that way.
Here is what i have so far i did select id as well at first thinking that was the best way to get the last consective but then i had a small breakthrough that if they have had 3 in a row the id does not matter, so i took it out of the query.
$sql = "SELECT `rvid`, `rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `rvid` DESC";
which give me this
Array
(
[0] => Array
(
[rvid] => 7
[rating] => 2
)
[1] => Array
(
[rvid] => 5
[rating] => 1
)
[2] => Array
(
[rvid] => 5
[rating] => 0
)
[3] => Array
(
[rvid] => 5
[rating] => 3
)
)
this is just just samples i tossed in the fields, and there are only 4 rows here where as in live it will be tons of rows. But basically this tells me that these are the vendors that have low ratings in the table. And that is where i get stumpted. I can only do one sort in the query so that is why i am thinking that i need to take this and move to the php side to finish it off.
I think i need to sort the elements by rvid with php first i think, and then see if three elements in a row are the same vender (rvid).
Hope that makes sense. My brain hurts lol...
update - here is all of the table data using *
Array
(
[0] => Array
(
[id] => 7
[rvid] => 7
[ratedate] => 2016-05-01
[rating] => 2
)
[1] => Array
(
[id] => 8
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 1
)
[2] => Array
(
[id] => 6
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 0
)
[3] => Array
(
[id] => 5
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 3
)
)
Here's one way you can begin approaching this - completely in SQL:
Get the last rating for the vendor. ORDER BY date DESC, limit 1.
Get the second to last rating for the vendor. ORDER BY date DESC, limit 1, OFFSET 1.
Then write a query that does a LEFT join of the first two tables. You will have a dataset that has three columns:
vendor id
last rating
second to last rating
Then you can write an expression that says "if column1 is <3 and column2 < 3, then this new column is true"
You should be able to extend this to three columns relatively easily.
Here is what a came up with to solve this riddle. I think explaining it on here helped as well as Alex also helped as he keyed my brain on using the date. I first started looking at using if statment inside of the query and actually that got my brain out of the box and then it hit me what to do.
It is not perfect and certainly could use some trimming to reduce the code, but i understand it and it seems to work, so that is par for me on this course.
the query...
$sql = "SELECT `rvid`, `ratedate`,`rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `ratedate`, `rvid` DESC";
which gives me this
Array
(
[0] => Array
(
[rvid] => 7
[ratedate] => 2016-05-01
[rating] => 2
)
[1] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 1
)
[2] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 0
)
[3] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 3
)
)
notice how vendor (rvid) 5 is grouped together which is an added plus.
next a simple foreach to load a new array
foreach($results as $yield)
{
$rvidarray[] = $yield['rvid'];
}//close foreach
which gives me this
Array
(
[0] => 7
[1] => 5
[2] => 5
[3] => 5
)
then we count the array values to group dups
$rvidcounter = array_count_values($rvidarray);
which results in this
Array(
[7] => 1
[5] => 3
)
so now vender 7 as 1 low score and vendor 5 has 3 low scores and since they were already sorted by date i know that its consecutive. Well it sounds good anyway lol ")
then we create our final array with another foreach
foreach($rvidcounter as $key => $value)
{
//anything 3 or over is your watchlist
if($value > 2)
{
$watchlist[] = $key; //rvid number stored
}
}//close foreach
which gives me this
Array
(
[0] => 5
)
this was all done in a service function. So the final deal is everyone in this array has over 3 consecutive low ratings and then i just use a returned array back in my normal php process file and grab the name of each vender by id and pass that to the html and print out the list.
done...
please feel free to improve on this if you like. I may or may not use it because the above code makes sense to me. Something more complicated may not make sense to me 6 mos from now lol But it would be interesting to see what someone comes up with to shorten the process a bit.
Thanks so much and Happy Coding !!!!!
Dave :)
You could do it in SQL like that:
SET #rvid = -1;
SELECT DISTINCT rvid FROM
(
SELECT
rvid,
#neg := rating<3, /* 0 or 1 for addition in next line */
#count := IF(#rvid <> rvid , #neg, #count+#neg) AS `count`, /* set or add */
#rvid := rvid /* remember last row */
FROM
testdb.venrate
ORDER BY
rvid, datetime desc
) subq
WHERE count>=3
;
You set a variable to a non existing id. In each chronologically sorted row you check if rating is too low, that results in 1 (too low) or 0 (ok). If rvid is not equal to the last rvid, it means a new vender section is beginning. On begin of section set the value 0 or 1, else add this value. Finally store the current row's rvid for comparison in next row process.
The code above is looking for 3 consecutive low ratings (low means a value less than 3) over all the time.
A small modification checks if all the latest 3 ratings has been equal to or less than 3:
SET #rvid = -1;
SELECT DISTINCT
rvid
FROM
(
SELECT
rvid,
#high_found := rating>3 OR (#rvid = rvid AND #high_found) unflag,
#count := IF(#rvid <> rvid , 1, #count+1) AS `count`,
#rvid := rvid /* remember last row */
FROM
testdb.venrate
ORDER BY
rvid, datetime desc
) subq
WHERE count=3 AND NOT unflag
;

getting index of outer array if there's a match in inner array

when i print_r my array gives
Array (
[0] => Array ( [userid] => 2 [popularity] => 41.7 )
[1] => Array ( [userid] => 5 [popularity] => 33.3 )
[2] => Array ( [userid] => 7 [popularity] => 25.0 )
)
is the array returned after querying users and sort by popularity desc, meaning
user with id 2 has popularity 41.7, user with id 5 has popularity 33.3 and so on,
Then i have a dynamic query that shows each user with his popularity
example: user with id 2 has popularity of 41.7
user with id 5 has popularity of 33.3 etc.
All i want is to show the position(outer array index) of each user if user id of dynamic query matches the output of array above then increment by 1 because array index always starts 0
example: user with id 2, will have position of 1 (the winner)
user with id 5, will have position of 2
user with id 7, will have position of 3 etc..
how can i do that...
This code modifies array and ads new key 'position' (= $key + 1) to each element.
function addPosition(&$item, $key) {
$item['position'] = $key + 1;
}
array_walk($data, 'addPosition');

How to utilize method with RegEx in order to print into a dynamic table on with PHP

I have a list of courses and the hours they require for students to take them. The courses are as follows:
CON8101 Residential Building/Estimating 16 hrs/w
CON8411 Construction Materials I 4 hrs/w
CON8430 Computers and You 4 hrs/w
MAT8050 Geometry and Trigonometry 4 hrs/w
I have used this RegEx to extract the name of course and the hours each course takes each week. There are more than 4 courses, the 4 are examples above. There can be as many as 50 courses.
$courseHoursRegEx = "/\s[0-9]{1,2}\shrs/w/";
$courseNameRegEx = "/[a-zA-Z]{3}[0-9]{4}[A-Z]{0,1}\s?/[a-zA-Z]{3,40}/";
And applied the following function (not sure if 100% right) to extract the RegEx'd strings. Using $courseLine is the variable I saved the string of each line from a text document that early I have fopened. It keeps track of the total hours that has been extracted from the string.
$courses is an array of check boxes that the user enters in the html section
$totalHours += GetCourseHours($courseLine);
function GetCourseHours($couseLine)
{
if(!preg_match($courseHoursRegEx, $courseLine))
{
return $courseLine;
}
}
function GetCourseName($courseLine)
{
if(!preg_match($courseNameRegEx, $courseLine))
{
return $courseLine;
}
}
I used a foreach loop to output all the selected courses to be sorted out in a table.
foreach($courses as $course)
{
$theCourse = GetCourseName($course);
$theHours = GetCourseHours($course)
}
Edit: output code
for($i = 1; $i <= $courses; ++$i)
{
printf("<tr><td>\$%.2f</td><td>\$%.2f</td></tr>", $theCourse, $theHours);
}
I am not sure how to output what I have into a dynamic table organized by the course name, and hours for each course. I cannot get my page to run, I cannot find any syntax errors, I was afraid it was my logic.
First of all, (after fixing a few minor things within the regexes) you can do all of that in one preg_ call. Here is how:
preg_match_all("~([a-zA-Z]{3}\d{4}[A-Z]{0,1}\s.+)\s(\d{1,2})\shrs/w~", $str, $matches);
$str can either be a multiline string with all rows at once. Or you can pass in a single line at a time. If you pass in all lines at once, $matches will afterward look like this:
Array
(
[0] => Array
(
[0] => CON8101 Residential Building/Estimating 16 hrs/w
[1] => CON8411 Construction Materials I 4 hrs/w
[2] => CON8430 Computers and You 4 hrs/w
[3] => MAT8050 Geometry and Trigonometry 4 hrs/w
)
[1] => Array
(
[0] => CON8101 Residential Building/Estimating
[1] => CON8411 Construction Materials I
[2] => CON8430 Computers and You
[3] => MAT8050 Geometry and Trigonometry
)
[2] => Array
(
[0] => 16
[1] => 4
[2] => 4
[3] => 4
)
)
Now you can simply iterate over all names in $matches[1] and sum up the hours in $matches[2]. Notice that those two inner arrays correspond to what's inside of the round brackets I used in the regex. These are so called subpatterns, and they capture additional (sub-)matches. Also $matches[0] will always contain the full match of the whole pattern, but you don't need that in this case.

Categories