Im trying to do a PHP script where it order users based on a point system. Problem is that the points is calculated after I execute the users. Like this:
$getScore = $db->prepare("SELECT * FROM `users`");
$getScore->execute();
$results = $getScore->fetchAll();
foreach($results as $row):
$likes = $get->likes("user", $row["id"]);
$subscribers = $get->subscribers("user", $row["id"]);
$score = $get->score($likes, $subscribers, $row["date"]);
echo $row["username"];
endforeach;
Without having another execution how do I order the results? I want the user with highest value on $score to be shown first. I've tried alot of things but without succession.
Thanks in advance!
You can implement this different ways.
If you have already loaded all the data from the databse you can order them using PHP.
Custom sorting can be done using usort.
PHP.net - usort documentation
Maybe you could use something like this:
$users = array();
// Load all the users and calculate scores
foreach($results as $row):
$users[$row["username"]] = $get->score($likes, $subscribers, $row["date"]);
endforeach;
// Sort users based on score
sort($users);
// Output users, sorted by score
foreach($score as $key => $row):
echo $key, " score:", $score;
endforeach;
If you would like to use a more complex data structure, all you have to do is implement the special comparision to ensure ordering by score with usort.
If you store the points in the database, then you could use a special query including an ORDER BY clause, this way returning the users already ordered.
I think using the DBMS to order the users would result in a more scalable solution. If you have really high number of users, it is not going to perform well to sort all the users each page load.
First, sorry for suggesting another execution flow. Next, this is my solution:
$getScore = $db->prepare("SELECT * FROM `users`;");
$getScore->execute();
$results = $getScore->fetchAll();
// Result is something like [rownum][colomname]
array_walk_recursive($results, function($item, $key) {
$id = $item["id"];
$date = $item["date"];
$arr = array();
$arr['likes'] = $get->likes("user", $id);
$arr['subscribers'] = $get->subscribers("user", $id);
$arr["score"] = $get->score($arr["likes"],
$arr["subscribers"],
$date);
$item = array_merge($item, $arr);
});
In this code you get the results from your database. Next you calculate things like the score and you add this to the array.
To sort this array on the score you can use the PHP multisort function (http://php.net/manual/en/function.array-multisort.php):
foreach ($results as $key => $row) {
$score[$key] = $row["score"];
}
array_multisort($score, SORT_DESC, $results);
When you're looping your loop to print the data for example you can do this:
foreach($results as $row) {
$likes = $row["likes"];
$subscribers = $row["subscribers"];
$score = $row["score"];
echo("your stuff over here");
}
Good luck!
Related
I have an query which select all ids from a table. Once I have all id's, they are stored in an array which I foreach over.
Then there is an second array which pull data from url (around 5k rows) and should update DB based on the id's.
The problem - second foreach is looping once for each ID, which is not what I want. What I want is to loop once for all id's.
Here is the code I have so far
$query = " SELECT id, code FROM `countries` WHERE type = 1";
$result = $DB->query($query);
$url = "https://api.gov/v2/data?api_key=xxxxx";
$api_responce = file_get_contents($url);
$api_responce = json_decode($api_responce);
$data_array = $api_responce->data;
$rows = Array();
while($row = $DB->fetch_object($result)) $rows[] = $row;
foreach ($rows as $row) {
foreach ($data_array as $key => $dataArr) {
$query = "UPDATE table SET data_field = $dataArr->value WHERE country_id = $row->id LIMIT 1";
}
}
The query returns 200 id's and because of than the second foreach (foreach ($data_array as $key => $dataArr) { ... }) execute everything 200 times.
It must execute once for all 200 id's not 200 * 5000 times.
Since the question is aboot using a loop, we will talk about the loop, instead of trying to find another way. Actually, I see no reason to find another way.
->Loops and recursions are great, powerful tools. As usually, with great tools, you need to also find ways of controlling them.
See cars for example, they have breaks.
The solution is not to be slow and sit to horses era, but to have good brakes.
->In the same spirit, all you need to master the power called recursions and loops is to stop them properly. You can use if cases and "break" command in PHP.
For example, here we have a case of arrays containing arrays, each first child of the array having the last of the other (1,2,3), (3,4,5) and we want to controll the loop in a way of showing data in a proper way (1,2,3,4,5).
We will use an if case and a counter :
<?php
$array = array( array(-1,0,1), array(1,2,3,4,5), array(5,6,7,8,9,10), array(10,11,12,13,14,15) );
static $key_counter;
foreach( $array as $key ){
$key_counter = 0;
foreach( $key as $key2 ){
if ( $key_counter != 0 ) {
echo $key2 . ', ';
}
$key_counter = $key_counter + 1;
}
}
Since I dont have access to your DB is actually hard for me to run and debbug the code, so the best I can say is that you need to use an if case which checks if the ID of the object is the ID we want to proccess, then proceed to proccessing.
P.S. Static variables are usefull for loops and specially for recurrsions, since they dont get deleted from the memory once the functions execution ends.
The static keyword is also used to declare variables in a function
which keep their value after the function has ended.
In my database I store email addresses. In the foreach loop how can I skip all email addresses that has #sample.com.ru?
$sql = "SELECT * FROM myMovieCustomers";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();
foreach ($result as $row) {
//skip if $row['email'] contains #sample.com.ru{
//do someting with these
//}
}
it's more efficient to do filtering at the database level for a couple of reasons
you're not wasting network resources transmitting unneeded data across the wire
with a well indexed table, the DBMS will be faster at making the search than php will with the result data
as is pointed out in the comments and other answers, you can use the LIKE operator
$sql = "SELECT * FROM myMovieCustomers WHERE email NOT LIKE '%#sample.com.ru'";
You can achieve what you want by using php function strstr() like below:
$all = array(
'name' => array('Thanga','Kima','Zara'),
'email'=> array('thanga#gmail.com','kima#gmail.com','zara#sample.com.ru')
);
echo '<pre>';
print_r($all);
foreach($all as $key=>$val):
foreach ($val as $k=>$v):
if(strstr($v,'#')=='#sample.com.ru'){
}else{
echo $v;
}
endforeach;
endforeach;
Just change the first line...
$sql = "SELECT * FROM myMovieCustomers WHERE email NOT LIKE'%#sample.com.ru'";
I'm fairly new to php, and I don't know how to work with arrays very well. Here's the deal, I want to add into a multidimensional array three or more values I obtain from my database, then I want to sort them based on the timestamp (one of the values). After that, I want to show all of the sorted values. I can't seem to do this, here's the code
$queryWaitingPatients = 'SELECT ArrivalTime, TargetTime, Order, Classification FROM exams WHERE (CurrentState = "Pending")';
$results = mysql_query($queryWaitingPatients) or die(mysql_error());
if (mysql_num_rows($results) == 0) {
echo '<p>There\'s currently no patient on the waiting list.</p>';
return;
}
while ($rows = mysql_fetch_array($results)) {
extract($rows);
//now is the part that I don't know, putting the values into an array
}
// I'm also not sure how to sort this according to my $TargetTime
asort($sortedTimes);
//the other part I don't know, showing the values,
Thanks for the help!
Well, let's look at your code. First, you have a query that's returning a result set. I don't recommend using mysql_fetch_array because it's not only deprecated (use mysqli functions instead) but it tends to lend itself to bad code. It's hard to figure out what you're referencing when all your keys are numbers. So I recommend mysqli_fetch_assoc (be sure you're fully switched to the mysqli functions first, like mysql_connect and mysqli_query)
Second, I really dislike using extract. We need to work with the array directly. Here's how we do this
$myarray = array();
while ($rows = mysqlI_fetch_assoc($results)) {
$myarray[] = $rows;
}
echo $myarray[0]['ArrivalTime'];
So let's go over this. First, we're building an array of arrays. So we initialize our overall array. Then we want to push the rows onto this array. That's what $myarray[] does. Finally, the array we're pushing is associative, meaning all the keys of the row match up with the field names of your query.
Now, the sorting really needs to be done in your query. So let's tweak your query
$queryWaitingPatients = 'SELECT ArrivalTime, TargetTime, `Order`, Classification
FROM exams
WHERE CurrentState = "Pending"
ORDER BY TargetTime';
This way, when your PHP runs, your database now churns them out in the correct order for your array. No sorting code needed.
$arr = array();
while ($rows = mysql_fetch_array($results)) {
array_push ($arr, $row);
}
print_r($arr);
<?php
$queryWaitingPatients = ' SELECT ArrivalTime, TargetTime, Order, Classification, CurrentState
FROM exams
WHERE CurrentState = "Pending"
ORDER BY TargetTime ';
$results = mysql_query($queryWaitingPatients) or die(mysql_error());
if ($results -> num_rows < 1)
{
echo '<p>There\'s currently no patient on the waiting list.</p>';
}
else
{
while ($rows = mysqli_fetch_array($results))
{
$arrivaltime = $row['ArrivalTime'];
$targettime = $row['targettime'];
$order = $row['Order'];
$classification = $row['Classification'];
echo "Arrival: ".$arrivaltime."--Target time: ".$targettime."--Order: ".$order."--Classification: ".$classification;
}
}
echo "Done!";
//or you could put it in a json array and pass it to client side.
?>
I feel incredibly stupid for not being able to figure this out, but I guess that's what Stackoverflow is for. If someone could point me to helpful resources or explain to me how to solve this, I would be very appreciative.
Basically I'm fetching a couple of rows from a table, and now I need to be able to print them out the value of each row's field, followed by the values of each row from a different field, and so on. It's hard to explain, but let me give you an example.
Let's say we have a table with three fields: id - name - url. Now I want to be able to output the result in this order:
1
2
3
John
Steven
Patrick
http://google.com/
http://stackoverflow.com/
http://php.net/
How do I loop through the results of my query in order to achieve this?
Well you should make an array and then spew it out:
$ids = array();
$names = array();
$urls = array();
while($row = ...){
$ids[] = $row['id'];
$names[] = $row['name'];
$urls[] = $row['url'];
}
foreach($ids as $id) {
echo $id . PHP_EOL;
}
//do the same for the other 2
You can do this via union. The only tricky part is making sure to cast all of the fields to a common data type (in this case, text). Also, each subquery is ordered by id to make sure that the ordering is consistent.
select id::text
from table
order by id
union
select name::text
from table
order by id
union
select url::text
from table
order by id
$result = mysql_query("SELECT id, name, url FROM yourtable") or die(mysql_error());
$data = array()
while($row = mysql_fetch_asssoc($result)) {
$data[] = $row;
}
foreach(array('id', 'name', 'url') as $key) {
foreach($data as $idx => $val) {
echo $val[$key], "\n";
}
}
The simplest way is
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$ids[] = $row['id'];
$names[] = $row['names'];
$wwws[] = $row['website'];
}
Then you iterate over the three arrays. There are surely better methods for doing this!
tl;dr - Pushing an array (by $array[] or $array[$id] is not working in Kohana 3, it gives a blank white page.
I'm using Kohana (3), it's my first experience with MVC and it's been great so far; however, I'm working with a database and encountered a weird problem that I was hoping someone could shed some light on:
My workflow is like this, to give you an idea of my problems surrounding:
$sql = "SELECT table1.row1, max(table2.row1) as `maxAwesome` FROM table1, table2 WHERE table1.id=table2.table1id GROUP BY table1.id";
$table1Results = DB::query(Database::SELECT, $sql)->execute();
$masterArray = array();
foreach ($table1Results as $result1)
{
$sql = "SELECT * FROM table2 WHERE table2id='" . $result1['id'] . "' AND column > 21";
$table2Results = DB::query(Database::SELECT, $sql)->execute();
$subArray = array();
foreach ($table2Results as $result2)
{
$subArray[$result1['id']] = $result2;
// Even had just $subArray[] = array("whatever");
}
$masterArray[] = array("table1Data" => array(), "table2Data"=> $subArray);
}
I do a query where I run a couple max/min functions then do a query within the foreach doing another select to build a master array of data formatted the way I want it and all the SQL etc works fine and dandy; however, the problem arises when I'm pushing the array.
It seems whenever I push the array by doing either $array[] = array("data"); or by specifying the key $array[$id] = array("data"); Kohana gives me a straight blank page, no error, no output etc.
Sometimes I get a Kohana error indicating the key does not exist (duh, I'm creating it) but for the most part the output is straight white.
Why is this happening? Am I going about it wrong?
Thanks in advance.
Clarity edit:
My SQL blunders aside, the issue lies in the building of the secondary array, for example:
$queryStores = "SELECT stores.store_id, stores.title, max(product.discount) as `max_discount`, min(product.discount) as `min_discount`
FROM stores, products
WHERE products.store=stores.store_id
GROUP BY products.store";
$stores = DB::Query(Database::SELECT, $queryStores)->execute();
$formattedStores = array();
if (count($stores))
{
foreach ($stores as $store)
{
$formattedStores[$store['store_id']] = array(
"title" => $store['title'],
);
// Same result if just doing $formattedStores[] = array();
// Problem goes away should I do:
// $formattedStores = array("This works");
//
}
}
echo "<pre>";
print_r($formattedStores);
echo "</pre>";
That does not print an array, it simply gives a blank page; however, if i change it to just re-set the $formattedStores array to something I get an output. What is it about pushing the array that's causing a problem, perhaps a Kohana bug?
Thanks
Your code should be like:-
$sql = "SELECT table1.id, table1.row1, max(table2.row1) as `maxAwesome`
FROM table1, table2
WHERE table1.id = table2.table1id
GROUP BY table1.id";
$table1Results = DB::query(Database::SELECT, $sql)->execute();
$masterArray = array();
if (count($table1Results))
{
foreach ($table1Results as $result1)
{
$sqlInner = "SELECT * FROM table2
WHERE table2id = '" . $result1['id'] . "'
AND column > 21";
$table2Results = DB::query(Database::SELECT, $sqlInner)->execute();
$subArray = array();
if (count($table2Results))
{
foreach ($table2Results as $result2)
{
$subArray[$result1['id']] = $result2;
// Even had just $subArray[] = array("whatever");
}
}
$masterArray[] = array("table1Data" => array(), "table2Data"=> $subArray);
}
}
Some valuable coding standards & miss-ups:-
You have got the "id" field (w.r.t. the "table1" DB table) missing from the first SQL.
The second SQL should be better written using another variable naming, so as to keep it separate from the first one. Hence the second variable is named as "$sqlInner".
It's always better to check for any existence of array elements in an array variable, so I have used the simple checks using the "if" statement.
Hope it helps.
I've determined this to be memory related.