/    Sign up×
Community /Pin to ProfileBookmark

[RESOLVED] Iterate Through Array with Function using while

OK, so this one’s a little tricky.

I wrote a database abstraction layer for a CMS that I’m developing, and I’m trying to adapt it to use a flatfile DB. I am currently able to get all of my DB information into an array similar to that returned by mysql_fetch_assoc(). Here’s the problem though: it must remain compatible and provide the same functionality. Let me do an example.

To iterate throw the rows of a result, someone calls something like this:

[code=php]
while ($row = $db->dbRow($result)) {
echo $row[‘column’];
}
[/code]

For the MySQL driver, the function looks like this:

[code=php]
function dbRow(&$result) {
return mysql_fetch_assoc($result);
}
[/code]

This works perfectly. My problem, however, is what to do when I have an array? This creates an infinite loop:

[code=php]
function dbRow(&$result) {
$item = each($result);
if ($item == false) {
return false;
} else {
return $item[‘value’];
}
}
[/code]

(I’ve tried many other things, but all seem to create some sort of infinite loop).

Suggestions?

-Matt

to post a comment
PHP

21 Comments(s)

Copy linkTweet thisAlerts:
@mudeltaJan 16.2007 — since you're passing a reference to your function i expect that you use php5?

When you do this:

[code=php]
function dbRow(&$result) {
$item = each($result);
echo($item);
}

$arr = array("a","b","c","d");
for(i=0;i<=count($arr);i++){
dbRow($arr);
}
[/code]


what does it return?
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — Well, first of all, according to the PHP docs, pass-by-reference works fine from PHP 4.0.4 and on.

Second, I have to use a "while," I can't use a for statement. True, that solves the issue, but breaks compatibility with other drivers.

For the record, however, your code doesn't exactly solve my problem. For each iteration, I need to assign the current item to a variable that I can reference, like a MySQL database. Thus, I cannot put any program-specific instructions into the dbRow() function. Further, each() returns an array. $item['value'] returns the information I want, not just $item.

Thanks for the help though. ?

-Matt
Copy linkTweet thisAlerts:
@mudeltaJan 17.2007 — i know you have to use a while.

This code was just for testing.

I also now that each() normally returns an array.

except when the pointer is at the end of the array, then it returns false, and that's the purpose of the code: to see if the pointer gets to the end of the array.

(therefor i do a for loop like this: i<=count($arr); it will loop 5 times, but the array has 4 items, so normally the 5th time it will echo false)
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — Ahh, I get it now. :p

Well, on my console test, it printed Array 4 times, but no false.

-Matt
Copy linkTweet thisAlerts:
@mudeltaJan 17.2007 — ok,

try this one(also for testing purpose ? ) :

[code=php]
function dbRow(&$result) {
$item = each($result);
if(!$item){
echo("returned false");
}else{
echo($item['value']);
}
}

$arr = array("a","b","c","d");
for(i=0;i<=count($arr);i++){
dbRow($arr);
}

[/code]


what does this return?

[edit]i'm going to sleep now, i will test some later[/edit]
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — abcdreturned false

I like where this is going ?

-Matt
Copy linkTweet thisAlerts:
@NightShift58Jan 17.2007 — [code=php]<?php

$result = array();
$result[] = array(fname => "bob", lname => "smith", addr1 => "main street", city => "nyc");
$result[] = array(fname => "bill", lname => "smyth", addr1 => "side street", city => "kc");
$result[] = array(fname => "pete", lname => "smoth", addr1 => "left street", city => "sf");
$result[] = array(fname => "mike", lname => "smutt", addr1 => "main street", city => "la");

// Instead of **while ($row = $db->dbRow($result)) { **
while ( $row = dbRow($result)) {
print $row['fname'] . "<br>";
print $row['lname'] . "<br>";
print $row['addr1'] . "<br>";
print $row['city'] . "<hr>";
}

function dbRow(&$result) {
$item = each($result);
if ($item == false) {
return false;
} else {
return $item['value'];
}
}
?>[/code]
The above is a slight variation of the code posted previously. All I basically did was to create an array that is structured the way a table record would be. In the end, that's the true test to be applied.

The code originally posted by "patenaudemat" worked fine from the outset. If the idea is to simulate looping through a database record set, then you do want a false to be returned at the end of the array and you want the while loop to deal with it the same way it deals with the end of record set.

As such, I'm not really sure there was a problem to begin with... The original code worked as it should've.
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — The code originally posted by "patenaudemat" worked fine from the outset. If the idea is to simulate looping through a database record set, then you do want a false to be returned at the end of the array and you want the while loop to deal with it the same way it deals with the end of record set.

As such, I'm not really sure there was a problem to begin with... The original code worked as it should've.[/QUOTE]


OK, see, I didn't [i]think[/i] anything was wrong with my code. :p It just was never returning. There's only one possibility I can see:

I think that, somehow, the internal counter for the array is getting reset. Could have to do with the fact that the dbRow function is a method of a DB manager object?

-Matt
Copy linkTweet thisAlerts:
@NightShift58Jan 17.2007 — We have to be careful here... I thought you just wanted to substitute a method for a function.

What seems to be a function in $db->dbRow() is not a function that you can just substitute... It's part of a class. If you want to use continue using $db->dbRow() literrally, you'll have to create your own $db class.

For full compatibility with the existing code, you'll have to substitute each method in the class with your own, as was done with dbRow().
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — This is intended for a flat-file database driver. I wrote the class myself from scratch, so I designed it all from the beginning to work with existing code. However, for some reason, this method fails to ever return false. Like I said, I think the counter must somehow keep getting reset.

Edit: I attached the driver file, and the calling script, just so you can see.

-Matt

[upl-file uuid=4c529f0a-6d54-49b9-9a4e-319fb4272619 size=4kB]db-core.php.txt[/upl-file]

[upl-file uuid=ef5bc056-0d3f-4f2c-a421-4aa455f30888 size=7kB]json.driver.txt[/upl-file]
Copy linkTweet thisAlerts:
@NightShift58Jan 17.2007 — It doesn't reset on my server and I can't imagine that it would on yours...

See: http://www.nightshift58.com/webdev/eachtest/test_each.php (using code posted above)
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — Just attached the scripts I'm using to the previous post. ?

-Matt
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — *sigh* Found the problem. Once again, my stupidity. The driver is loaded through another file, which does [i]not[/i] take the parameters as references. Thus, the counter was getting reset, but way before my function even touched it.

Thanks for all of the help guys. ?

-Matt
Copy linkTweet thisAlerts:
@NightShift58Jan 17.2007 — Ok, better this way than none at all.

Interesting code you're writing..
Copy linkTweet thisAlerts:
@The_WandererJan 17.2007 — *jeez* matt, way to not know whats going on ? jkjk
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — *jeez* matt, way to not know whats going on ? jkjk[/QUOTE]

Shut up, DeBeasi :p (classmate)

Anyway, NightShift, if you're interested in checking the code out, grab a copy of the Tux CMS project from CVS on SourceForge (http://sf.net/projects/tuxcms). It'll probably take a little while for my latest changes to show up, and the whole project is nowhere near done, but the relevant files here are tux-dal.php (the database abstraction layer) and db/json.driver (the driver file for my flat-file JSON database). ?

-Matt
Copy linkTweet thisAlerts:
@The_WandererJan 17.2007 — Tuxcms is a quality piece of software, I highly recommend it!

Shut up, DeBeasi :p (classmate)

Anyway, NightShift, if you're interested in checking the code out, grab a copy of the Tux CMS project from CVS on SourceForge (http://sf.net/projects/tuxcms). It'll probably take a little while for my latest changes to show up, and the whole project is nowhere near done, but the relevant files here are tux-dal.php (the database abstraction layer) and db/json.driver (the driver file for my flat-file JSON database). ?

-Matt[/QUOTE]
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — Tuxcms is a quality piece of software, I highly recommend it![/QUOTE]

I appreciate the plug... but right now, it's not ready for prime-time. :p Manual install only, the installer isn't fully built. Should be cool once I finish though.

-Matt
Copy linkTweet thisAlerts:
@bokehJan 17.2007 — You don't have to do this by reference:[code=php]<?php

function dbRow($in)
{
static $temp;
$temp === $in || $temp = $in;
$out = each($temp);
return $out['value'];
}

$array = array('a','b','c','d','e');

while($out = dbRow($array))
{
echo $out;
}

?>[/code]
Copy linkTweet thisAlerts:
@patenaudematauthorJan 17.2007 — Hmmm... well, because of the nature of the driver setup, I think I'll keep it by reference if only because (with the various drivers) you never know exactly what type of data will be passed to this function, and whether it will have to be modified directly.

However, does this provide much of (if any) a performance/compatibility gain? ?

-Matt
Copy linkTweet thisAlerts:
@bokehJan 17.2007 — does this provide much of (if any) a performance/compatibility gain? ?[/QUOTE]Who knows! The real difference between these functions and [I]mysql_fetch_assoc()[/I] is that the latter takes a [I]resource [/I] rather than an [I]array[/I] as the argument.
×

Success!

Help @patenaudemat spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.7,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...