Looping through a recordset twice - php

I'm developping a Moodle 2.9.1 pluggin and I need to loop through a small recordset twice on the same page.
I'm using
$rs = $DB->get_recordset_sql($sql, array());
to get the data from mysql.
I would need a function like mysql data_seek(0) to work on the recordset again but I cannot find anything related to this in the moodle API or forums.

If you know the data is not going to be excessively huge, then you can use get_records_sql() instead. This will return an array, indexed by the first field in the SELECT. You can then do what you want with this array (loop through it multiple times, split, pop, shift, etc).

Just loop twice through $rs ??
foreach ($rs as $data){
}
foreach ($rs as $data){
}
Or to do it clean make a function loop_thorught and call it twice ?

Related

Using Same Variable in Multiple PHP `while` Loops

I have a PHP page with multiple mysql_query instances. Almost every one uses a while loop to retrieve multiple rows of data.
As I keep a snippet of this often used code, and the example I was taught with, used the variable $row, I have multiple instances of the following on my page:
while ($row = mysql_fetch_assoc($foo_data)) {
$barArray[] = $row['barValue'];
}
I even have an instance of $row = mysql_fetch_assoc($foo_data) without a while loop.
I'm wondering if the multiple uses of $row as a variable on a single page, is all right?
The PHP is functioning fine, but I always want to be sure that my code is proper and conforms to standard rules.
Thank you.
yes, it's all right.
it's all right to use the same spoon when you're eating soup.
Yes that is fine. but if you try:
var_dump($row);
at the end of your code -- it will only return that last value of $row
Yup, not a problem at all.
Just like always using $i as your count in a for loop, you can repeatedly use $row to no ill effect.

Sort multi-dimensional array built from CSV data using PHP

Trying to sort an array in PHP that is being populated from a CSV. I would also, ideally, LOVE to be able to control the sort by clicking on tabs in the table here .. Right now, though, my first task at hand is just sorting the damn thing.. been working on this for over 3 days now.. any help is GREATLY appreciated!! Cheers!
PHP
<?php
$fp = fopen("https://spreadsheets.google.com/pub?key=0AjZgwY03sLMGdHVoWjhucGowWWJBb2g2NnQzVG9HZFE&hl=en&single=true&gid=0&output=csv","r");
$rows = array();
while (($row = fgetcsv($fp)) !== FALSE) {
$rows[] = $row;
}
fclose($fp);
$headers = array_shift($rows);
foreach ($rows as $row) : list($ShowKey, $ShowFeedURL, $ShowLink, $ShowIcon, $ShowTitle, $ShowTag, $ShowCategory, $ShowEps, $ShowLastUpdate, $ShowNew) = $row;
$oddpost = ( empty( $oddpost ) ) ? '_odd' : ''; ?>
I recently did this. I had a multi-dimensional array of records from a database, and I needed to sort them based off of one specific column in the array. Here's what I did:
foreach($TimeRecords as $key => $value)
{
$Rates[$key] = $value['rate'];
}
array_multisort($Rates, SORT_ASC, $TimeRecords);
I build an array of only the column I need, then I use the array_multisort() function to sort the array based off of that column.
You can write functions that will do this in PHP and then just call them with javascript ajax calls and reload that part of the page when it's done sorting.
Instead of sorting the table in PHP, you may consider doing it client-side in Javascript. For instance have a look at this jQuery plugin: http://tablesorter.com/
You may find usort() function helpful. It accepts callback argument, which may be used for sorting by specific field.
I had a similar issue to this today. Basically what I ended up doing is creating a temporary table which I loaded in the rows from the csv file that I needed. From there, I used php to sort and organize the data and update or add to the table I needed to alter.
Example, I made a table called 'temp' and loaded in all the rows of the category I needed. Then, once this was in the table, I made a php script which sorted the information by number of total sales in descending order. From there, I did a query to update my main table and used a limit to control this (only the top 200 items by number of sales).
It was very easy to do and hopefully it will help you or someone else.
Keep in mind. If you're going to do this more than once, you will need to truncate the temporary table to remove the old rows first.

drupal--why $node->taxonomy is an array

someone wrote this code.
foreach ($node->taxonomy as $term) {
$tids[] = 't.tid = %d';
$args[] = $term->tid;
}
how he knows that in foreach "$node->taxonomy" is an array? and when i loop it,
foreach ($node->taxonomy as $term) {
}
the output that i get will be the $term's value. i don't know how it is change into the 't.tid = %d' and $term->tid. thank you.
In Drupal-related code, a $node is almost always an object produced by the node_load() function. Since every module has the opportunity to add its own properties to this object, it's very hard to find a central documentation of these properties.
By experience and by variable inspection, seasoned Drupal developers know that when set $node->taxonomy is always an array of term object (as returned by the taxonomy_get_term() function) indexed by their respective ids (named tids, for Term ID). This array is set by the taxonomy_nodeapi() function when $op == 'load' and is produced by the taxonomy_get_terms() function.
The question give little information but we can guess that the loop is meant to build two arrays used to generate a database query that filter on the tid column matching those of the $node object. Because the terms' data is already stored in the items of $node->taxonomy, let's hope that this query is not used to re-load the terms to display some of their name and/or description. Collecting 't.tid = %d' is probably a bad idea, the query would be better build with a single "tid in (". db_placeholder($args) .")" WHERE clause after collecting all the tids in $args.
The question is very unclear. All Items under the node object are arrays. You can check it yourself bu using:
print_r($node);
die;
Or using any PHP debugger.
for the foreach, It is very simple foreach... I don't understand what is the problem with that.
t.tid is simply an SQL query. %d is a placeholder for $args[], which consists of $term->tid. It's like this structure: PDO connections.

Initiating the same loop with either a while or foreach statement

I have code in php such as the following:
while($r = mysql_fetch_array($q))
{
// Do some stuff
}
where $q is a query retrieving a set of group members. However, certain groups have there members saved in memcached and that memcached value is stored in an array as $mem_entry. To run through that, I'd normally do the following
foreach($mem_entry as $k => $r)
{
// Do some stuff
}
Here's the problem. I don't want to have two blocks of identical code (the //do some stuff section) nested in two different loops just because in one case I have to use mysql for the loop and the other memcached. Is there some way to toggle starting off the loop with the while or foreach? In other words, if $mem_entry has a non-blank value, the first line of the loop will be foreach($mem_entry as $k => $r), or if it's empty, the first line of the loop will be while($r = mysql_fetch_array($q))
Edit
Well, pretty much a few seconds after I wrote this I ended up coming with the solution. Figure I'd leave this up for anyone else that might come upon this problem. I first set the value of $members to the memcached value. If that's blank, I run the mysql query and use a while loop to transfer all the records to an array called $members. I then initiate the loop using foreach($members as as $k => $r). Basically, I'm using a foreach loop everytime, but the value of $members is set differently based on whether or not a value for it exists in memcached.
Why not just refactor out doSomeStuff() as a function which gets called from within each loop. Yes, you'll need to see if this results in a performance hit, but unless that's significant, this is a simple approach to avoiding code repetition.
If there's a way to toggle as you suggest, I don't know of it.
Not the ideal solution but i will give you my 2 cents. The ideal would have been to call a function but if you dont want to do that then, you can try something like this:
if(!isset($mem_entry)){
$mem_entry = array();
while($r = mysql_fetch_array($q))
{
$mem_entry[] = $r;
}
}
The idea is to just use the foreach loop to do the actual work, if there is nothing in memcache then fill your mem_entry array with stuff from mysql and then feed it to your foreach loop.

PHP scope question

I'm trying to look through an array of records (staff members), in this loop, I call a function which returns another array of records (appointments for each staff member).
foreach($staffmembers as $staffmember)
{
$staffmember['appointments'] = get_staffmember_appointments_for_day($staffmember);
// print_r($staffmember['appointments'] works fine
}
This is working OK, however, later on in the script, I need to loop through the records again, this time making use of the appointment arrays, however they are unavailable.
foreach ($staffmembers as $staffmember)
{
//do some other stuff
//print_r($staffmember['appointments'] no longer does anything
}
Normally, I would perform the function from the first loop, within the second, however this loop is already nested within two others, which would cause the same sql query to be run 168 times.
Can anyone suggest a workaround?
Any advice would be greatly appreciated.
Thanks
foreach iterates over a copy of the array. If you want to change the value, you need to reference it:
foreach($staffmembers as &$staffmember) // <-- note the &
{
$staffmember['appointments'] = get_staffmember_appointments_for_day($staffmember);
// print_r($staffmember['appointments'] works fine
}
From the documentation:
Note: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.
and
As of PHP 5, you can easily modify array's elements by preceding $value with &. This will assign reference instead of copying the value.

Categories