Can't seem to return value from function

Echoing $final at the end works, fine. Returning it from the function yields an empty variable:




//determine the number of consecutive weeks a student appears in a database.
function get_consecutive_weeks($consecutive_count, $student, $upload_week){

//to check previous weeks, decrement upload_week with each iteration
$upload_week--;

$sql="select distinct(student_name) from my_database where student_name='$student' and upload_week=$upload_week";

$result=mysqli_query($dbConn, $sql);
if (!$result){
exit ("Couldn't perform query " . $sql);
}//result

while ($row=mysqli_fetch_row($result)){
    $name=$row[0];
}

//if the query returns a result, the student appears in the previous week. Increment $consecutive_count by 1 and call the function again:

if (isset($name)){
$consecutive_count++;
get_consecutive_weeks($consecutive_count, $student, $upload_week);
} 

//if no match was found the student does not appear in the previous week. Return the number of consecutive weeks the student does appear.
else {
$final = $student . ' ' .  $consecutive_count . '<br />';
echo $final;
    return $final;
} 

}

This recursive function is probably not the best way to handle this… but I’m not familiar enough with mysql to write a query to handle everything with just one query.

Anyway, when I echo $final at the end there, I get a nice list of students and the number of consecutive times they appear in the database. It looks like this:

Bob Smith 9
Ann Taylor 2
Brian Babbs 4

etc… etc…

However, when I return $final from the function, it’s empty… Can’t figure out why this is happening. Any ideas?

Your code, as posted, doesn’t exhibit this problem. You’ll probably have to show real working code that reproduces the issue.

Actually, that’s pretty much live code… the only thing I’ve done is removed the connection to the DB, which already know is working (otherwise I wouldn’t get any result), and added some comments. Here a copy and paste from my code:


//determine the number of consecutive weeks
function get_consecutive_weeks($consecutive_count, $student, $upload_week){
$dbConn=connectToMain();
if (!$dbConn){
    $error="Could not connect to database.";
    exit();
}
$upload_week--;

$sql="select distinct(student_name) from my_database where student_name='$student' and up_num=$upload_week";


$result=mysqli_query($dbConn, $sql);
if (!$result){
exit ("Couldn't perform query" . $sql);
}//result

while ($row=mysqli_fetch_row($result)){
    $name=$row[0];
}
if (isset($name)){
$consecutive_count+=1;

get_consecutive_weeks($consecutive_count, $student, $upload_week);
} else {
$final=$student . ' ' . $consecutive_count . '<br />';
echo $final;
return $final;
} 

}

I call the function and attempt to store the value in a variable:


$consecutive=get_consecutive_weeks(1, $student, $upload_num);

Echoing $consecutive from the page I need the data to display on yields an empty variable.

I’m guessing that $upload_week eventually is reduced to something that does not exist on you db. Each time thru your function you see the result that was obtained while it was valid, but the last time into your function it fails and your value of $final will be of course empty.

Thanks for the response. What should be happening (or rather, what I want to happen), is that when a match is not returned from the query (i.e. the student does not exist in the database for that week), it returns the value for $consecutive_count (the number of consecutive weeks the student was in the database).

So, for instance, take these actual queries being produced:

Imagine this is the 11th weekly upload. First iteration looks like this:


"select distinct(student_name) from my_database where student_name='Lincoln, Abraham' and up_num=10";

> Assume a match is found (i.e. student exists in the prior week’s upload), $consecutive_count==2. Function calls itself to look at previous upload:


"select distinct(student_name) from my_database where student_name='Lincoln, Abraham' and up_num=9";

> Assume a match is found, $consecutive_count==3. Function calls itself to look at previous upload:


"select distinct(student_name) from my_database where student_name='Lincoln, Abraham' and up_num=8";

> Assume a match is NOT found. $consecutive_count==3. Return $consecutive_count and move to the next student.

Like I said, when I echo the results of this, everything displays perfectly and correctly. But when I RETURN the results, it’s empty.

Your code is completely wide open to sql injection attacks. Your database could be deleted by somebody typing a specific string into a url on your site.

Thanks. This is localized and not production… so if someone wants to hack my local database and delete all my references to dead presidents posing as students, they are welcome to do so.

So it looks like you need to check the result of the last function call before replacing the value of $final with its result. That way you can return the ‘previous’ result.
<snip/>

Please keep the discussion on-topic

[OT]Personally. I feel that security (and error handling) should be part of code development from the start.
I think part of the problem is that the PHP documentation gives many code examples that to maintain “focus” are limited to demonstrating the particular functions, and this results in many adding security and error handling to their code as an after-thought.
Please read

and

Why not get your answer from a single query?
Note: I’m under the assumption that upload_week is a number and not a date.

//determine the number of consecutive weeks a student appears in a database.
function get_consecutive_weeks($consecutive_count, $student, $upload_week){
	$dbConn=connectToMain();
	if (!$dbConn){
	    $error="Could not connect to database.";
	    exit();
	}
	
	$weeks = array();
	$sql = "SELECT DISTINCT(upload_week) FROM my_database WHERE student_name = ? AND upload_week <= ? ORDER BY upload_week DESC";
	$stmt = $dbConn->prepare($sql);
	$stmt->bind_param('ss', $student, $upload_week);
	$stmt->execute();
	$result = $stmt->get_result();
		
	while ($row = $result->fetch_array()){
		if($upload_week == $row[0]){
		    $weeks[]= $row[0];
			$upload_week--;
		}
	}
	
        $stmt->close(); 

	$consecutive_count = count($weeks) + $consecutive_count;
	
	$final = $student . ' ' .  $consecutive_count . '<br />';
   return $final;
} 
//determine the number of consecutive weeks
function get_consecutive_weeks($consecutive_count, $student, $upload_week){
$dbConn=connectToMain();
if (!$dbConn){
    $error="Could not connect to database.";
    exit();
}
$upload_week--;

$sql="select distinct(student_name) from my_database where student_name='$student' and up_num=$upload_week";


$result=mysqli_query($dbConn, $sql);
if (!$result){
exit ("Couldn't perform query" . $sql);
}//result

while ($row=mysqli_fetch_row($result)){
    $name=$row[0];
}
if (isset($name)){
$consecutive_count+=1;

[COLOR="#FF0000"]get_consecutive_weeks($consecutive_count, $student, $upload_week);[/COLOR]
} else {
$final=$student . ' ' . $consecutive_count . '<br />';
[COLOR="#FF0000"]echo $final;
return $final;[/COLOR]
}

How you’re looping through the result is likely the problem. Assign $final in the if call as well otherwise you’re just returning the results of $final there and not outputting them ever as your return is then is only existant inside the function and never released outside of it (Sorry, don’t recall the technical term). In this case that’d mean changning the if to something more like this:

if (isset($name)){
$consecutive_count+=1;

[COLOR="#FF0000"]$final = get_consecutive_weeks($consecutive_count, $student, $upload_week);[/COLOR]
} else {
$final=$student . ' ' . $consecutive_count . '<br />';

}
[COLOR="#FF0000"]return $final;[/COLOR]

You don’t actually need the echo since you’re assigning it to a variable when called anyway and thus having this means you’re echoing AND assigning and probably outputing it twice, just echo the output variable after it’s assigned.

That being said Drummin’s method is much better for a number of reasons and including that, as you may notice, it doesn’t have to call itself. It will, however iirc, mean you’ll have to change your database connection script from procedural to object oriented.