Recursive function returns nothing [duplicate] - php

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I have a database full of autopart numbers that needs old part numbers prices updated. Each row features a part number (field name "master") a price and a field with superseded (newer) part numbers (field name "pnc"). The script needs to check if the "pnc" field isn't empty. If it's not, it should go and grab the price for that number. Easy enough.
However, some part numbers have an unknown level of numbers to go through until it reaches the most current part number and price. So, I figured a recursive function would be the best solution. However, it's not working correctly. Here's the code:
public function updatePricing()
{
//method to update pricing by referencing supersession prices
$sql = "SELECT * FROM prices";
$result = mysql_query($sql);
$num_rows = mysql_num_rows($result);
for($i=0;$i<2000;$i++) //using 2000 for testing, use $num_rows after
{
$row = mysql_fetch_array($result);
$id = $row['id'];
$super_num = $row['pnc'];
//if there is a supersession in this row find original
if(!empty($super_num))
{
$final_super_price = $this->findSuperPrice($super_num);
echo "partnum: " . $row['master'];
echo " ";
echo "price: " . $final_super_price . "<br /><br />";
}
}
}
public function findSuperPrice($part_num)
{
$sql = "SELECT * FROM prices WHERE master='" . $part_num . "'";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if (empty($row['pnc'])) //if there aren't any supersession numbers
{
$final_price = $row['list'];
return $final_price;
}
else //recursively call itself until we find the last number
{
$this->findSuperPrice($row['pnc']);
}
}
What's happening is the updatePricing() function runs until it finds a row that has an entry in the "pnc" field. When it does, the findSuperPrice() function is called. The findSuperPrice() function should run recursively until the "pnc" field is empty. When that happens a number is returned.
However, if it actually reaches the else part of the if statment in findSuperPrice(), it doesn't return anything. Basically, if it's more than one level deep. I'm not getting any errors, it's just returning a blank statement. I've verified there is information there that it should be returning also. Thanks.
Also, I should mention this is inside of a larger class. The rest of the class has no bearing on these two methods.

You need to return a value. Change this code:
else //recursively call itself until we find the last number
{
$this->findSuperPrice($row['pnc']);
}
To this:
else //recursively call itself until we find the last number
{
return $this->findSuperPrice($row['pnc']);
}

You currently do not get a return value because the result of findSuperPrice is ignored if $row['pnc'] is not empty. Correctly return the value of the recursive calls:
return $this->findSuperPrice($row['pnc']);

You are missing a return statement in the else case inside findSuperPrice.
But... it looks like you are pumping a whole lot of data to look at/manipulate only a single field. You could also write function in mysql, similar to the one I posted here: MySQL: Get Root Node of Parent-Child Structure
That could enable you to query the required value directly from the database. If you have the structure for your tables I'd be happy to help out.

Related

Information regarding SQL queries, stored with php

So let me explain my problem, lets assume that I run query like so:
$myquery = sql_query("SELECT name FROM table WHERE name='example' LIMIT 0,1");
Now.. I want to store the retrieved name into a variable so I would do something like this:
while ($myrow = sql_fetch_assoc($myquery)) {
transfer_row($myrow);
print"Name: $row_name";
}
$stored_name = $row_name;
NOTE: transfer_row() is just a function I wrote that takes $myrow['name'] and stores it in $row_name, for easier reference
Now, all is fine at this stage, here is where it gets interesting. Note that at this stage I still have a name assigned to $row_name. Further down the page I run another query to retrieve some other information from the table, and one of the things I need to retrieve is a list of names again, so I would simply run this query:
$myquery = sql_query("SELECT name, year FROM table WHERE DESC LIMIT 0,10");
while ($myrow = sql_fetch_assoc($myquery)) {
transfer_row($myrow);
$year = $row_year;
$link = "/$year";
print "<li style=\"margin-bottom: 6px;\">$row_name\n";
}
Now, I want to write an if statement that executes something if the $row_name from this query matches the $row_name from the old query, this is why we stored the first $row_name inside the variable.
if ($row_name == $stored_name){
// execute code
}
However as most of you know, this WONT work, the reason is, it simply takes $stored_name again and puts the new $row_name into $stored_name, so therefore the value of the first $row_name is lost, now it is crucial for my application that I access the first $row_name and compare it AFTER the second query has been run, what can I do here people? if nothing can be done what is an alternative to achieving something like this.
Thanks.
EDIT, MY transfer_row() function:
function transfer_row($myrow) {
global $GLOBALS;
if(is_array($myrow)) {
foreach ($myrow as $key=>$value) {
$key=str_replace(":","",$key);
$GLOBALS["row_$key"] = $value;
}
}
}
Without you posting the code for the function transfer_row, we won't be able to give you an answer that exactly matches what you request, but I can give you an answer that will solve the problem at hand.
When matching to check if the names are the same, you can modify the if statement to the following.
if ($row_name == $myrow['name']){
// execute code
}
What I suggest you do though, but since I don't have the code to the transfer_row function, is to pass a second variable to that function. The second variable will be a prefix for the variable name, so you can have unique values stored and saved.
Refrain from using the transfor_row function in the second call so your comparison becomes:
if ($myrow['name'] == $row_name)
If you need to use this function, you could do an assignment before the second database call:
$stored_name = $row_name;
...
transfer_row($myrow);
In your first query you are selecting the name field WHERE name='example' , Why are you quering then? You already have what you want.
Your are querying like:
Hey? roll no 21 what is your roll no?
So perform the second query only and use the if condition as :
if ($row_name == 'example'){
// execute code
}
Does it make sense?
Update
//How about using prefix while storing the values in `$GLOBAL` ??
transfer_row($myrow, 'old_'); //for the first query
transfer_row($myrow, 'new_'); //for the second query
function transfer_row($myrow, $prefix) {
global $GLOBALS;
if(is_array($myrow)) {
foreach ($myrow as $key=>$value) {
$key=str_replace(":","",$key);
$GLOBALS["$prefix"."row_$key"] = $value;
}
}
}
//Now compare as
if ($new_row_name == $old_row_name){
// execute code
}
//You'll not need `$stored_name = $row_name;` any more

How do I echo the contents of a MySQL table field?

I seem to be having trouble understanding the concept of how to properly use the information in a MySQL database using PHP/MySQLi. As I understand it, you generate a variable representing the connection object:
$connectionObject = mysqli_connect('serverString', 'userString', 'passString', 'databaseString');
then, generate a variable representing the query string you want to use:
$queryString = "SELECT rowName FROM tableName";
then, generate a variable representing the result object returned from a successful query:
$resultObject = mysqli_query($connectionObject, $queryString);
then, you use the fetch_assoc() function to generate an array from the result object and assign it to a variable:
$resultArray = myqli_fetch_assoc($resultObject);
then, you can use a while loop to (I have trouble with this one) to sort through the array and use the content of the row somehow:
while ($resultArray) {
echo $resultArray["rowName"];
}
Do I have this concept the wrong way, somehow, because its just not working for me, even to output the text content of a text-based CHAR(10) field with the contents of no more than: "BLAH".
The need to loop through the array to pick out the array item by name in the end anyway seems moot to me to begin with, but no matter where I look, I find the same concept.
My script code, minus a few key details, is:
if ($connectionObject=mysqli_connect("host0", "username0", "password0", "mysqldatabase0")) {
echo "Con";
}
if ($queryString="SELECT 'testdata' FROM 'testtable'") {
echo "Query";
}
if ($resultObject=mysqli_query($connectionObject, $queryString)) {
echo "Result";
}
if ($resultArray=mysqli_fetch_assoc($resultObject)) {
echo "Array";
}
while ($row=$resultArray) {
echo $row["testdata"];
print_r ($row);
}
mysqli_fetch_assoc returns an associate array of string representing the fetched row in the result set which is your $resultObject.
The problem is where you're using the while loop. You want to capture the returned associative array in a variable and access your data via that variable like follows:
while ($row = $resultArray) {
echo $row["rowName"];
}
To sort by rowName you can use the mysql order by clause in your query like follows which returns your results sorted by rowName:
$queryString = "SELECT rowName FROM tableName order by rowName";
Update after OP posted full code:
In your first if statement what would happen if the connection failed? You want to add some error handling there:
$connectionObject=mysqli_connect("host0", "username0", "password0", "mysqldatabase0"));
if (!$connectionObject) {
// exist out of this script showing the error
die("Error connecting to database " . mysqli_error($connectionObject));
} else {
// Don't really need this else but I'll keep it here since you already had it
echo "Con";
}
The problem is here You are using single quotes for column name and table name which are mysql identifiers. MySQL identifiers quote character is backtick not single quote.
Basically you need to use backticks if one of these identifiers are one of mysql reserved words (MySQL Reserved words), for other cases you don't need to use them.
Update your query:
if ($queryString="SELECT `testdata` FROM `testtable`") {
echo "Query"; // Leaving as is, not required
}
Lastly, an improvement. You want to add error handling here too:
if ($resultObject=mysqli_query($connectionObject, $queryString)) {
echo "Result"; // Leaving as is, not required
} else {
echo "Error executing Query " . mysqli_error($connectionObject);
}
Please note that when you use this script the error messages will be printed at the client i.e. when you use this script in a web application the errors will be shown in the user's browser. So you want to look into implementing logging and not printing them directly.
mysqli_fetch_assoc() returns one row as an associative array, of a mysqli_result object. Each time it is called, it returns the next row of results automatically and when used with a while loop, can be used to fetch an unknown number of result rows.
The $row['columnName'] is used to refer to the column. For example, if you had a person object with columns firstName, lastName, dateOfBirth, you could iterate through each person with a while loop as such:
while($row=mysqli_fetch_assoc($resultObject)){
$fname = $row['firstName'];
$lname = $row['lastName'];
$dob = $row['dateOfBirth'];
echo $fname . ' ' . $lname . ' ' . $dob;
}
This will echo details for a result returning an unknown amount of people.
Remember, calling the
if ($resultArray=mysqli_fetch_assoc($resultObject)) {
echo "Array";
}
before the while loop will skip the first result, so make sure the query returns multiple results when testing, as if you are only providing a resultObject containing one result, this might be why it isn't returning anything.
A better way to check if any results are returned is with the mysqli_num_rows($resultObject) function.
if(mysqli_num_rows($resultObject) > 0){
echo "Array";
}
Also not sure if it was just a typo but just to be sure, in your query you are selecting columnName not rowName:
$queryString = "SELECT columnName1(eg. firstName), columnName2(eg. lastName) FROM tableName";
I just recently started learning PHP, and the mysqli_fetch_assoc function confused me too, so I hope this helps!

Image located in directory; Image name loaded in MySql. PHP Script is not returning the image

I have been trying different things in order to get this script to query the MySql DB for the image name and then go to the directory and return the image with the same name. It seems simple in concept, but I keep getting a bunch of mixed results and none of the results return the image.
Here is the most recent code that I tried:
$sqlCar = mysql_query("SELECT img_nm FROM vehicles WHERE sold='n' ORDER BY year DESC");
/***************************
****
Code Returns '1'
******************************/
$dbImage = $sqlCar;
$dirImage = scandir($_SERVER['DOCUMENT_ROOT'].'/car-pics/');
function imgCompare($dbImage){
if ($dbImage == $dirImage[img_nm]){
echo $dirImage[img_nm];
} else {
echo "Image Coming Soon";
}
}
You're not adding $dirImage as a parameter to the function. You can solve this by adding it as a parameter, or adding the global keyword to the first line of your function like this:
function imgCompare($dbImage){
global $dirImage;
if ($dbImage == $dirImage[img_nm]){
echo $dirImage[img_nm];
} else {
echo "Image Coming Soon";
}
}
Also, what values are in img_nm in the database? scandir uses an array of index values. So $dirImage[0] would work, but $dirImage['filename.jpg'] would not.
The mysql_query function is not going to return the value you are looking for directly into $sqlCar where it is directly accessible.
you will have to do something like
$row = mysql_fetch_array( $sqlCar );
And then reference the array to get the image name
$dbImage = $row['img_nm'];

PDO best way to check if 300+ values exist in database

I have a time dependent script I am working on and used microtime() to find the bottle neck. I determined the time increase is caused by doing a check on 300+ values to see if they exist in a database one at a time at 0.04 seconds a query.
The background of the script is it is a caching script. I need to see if it exists in the DB so I need a true/false (obtained by a rowCount) but i also need a way to relate a false to a value so I can update it. I know using a WHERE tag IN (:ARRAY) would work faster than the individual calls, but I cant think of a way to apply an association of true/false to value in this method.
My current code is below:
//loop through all our values!
//prepare out reusuable statement
$stmt = $db->prepare("SELECT * from cache WHERE value=?");
foreach($values as $tempVal)
{
//find if its in the database
try
{
$stmt->execute(array($tempVal));
$valCount = $stmt->rowCount();
} catch(PDOException $ex) {
echo "PDO error send this to us: " . $ex->getMessage();
}
//update flag
$addToUpdate = 1;
//if its in the database
if($valCount > 0)
{
//get the tag data
$valRes= $stmt->fetch();
//check if cache expired
$addToUpdate = 0;
}
//add to update list
if($addToUpdate)
{
//needs updating
$updateList[] = $tempVal;
//add to not in DB list to minimize queries
if($tagTCount == 0)
{
$notInDB[$tempVal] = $tempVal;
}
}
Any suggestions? I can explain more if anything is not clear.
Thank you,
Nick
So you just issue your query with the complete array, using the IN (?,?,?,?,?...) list:
// abstract, use a PDO wrapper of your choosing
$query = db("SELECT * FROM cache WHERE value IN (??)", $values);
Then iterate over the result list. Only matched $values will return. So build your first list from that:
foreach ($query as $row) {
$updateList[] = $row["value"];
}
To get the list of absent entries, just diff that against your original array:
$notInDB = array_diff($values, $updateList);
You could of course use a second NOT IN query. But doing that differentiation in PHP is simpler.

Check if no result found in mysql db [duplicate]

This question already has answers here:
Checking if mysqli_query returned any values?
(2 answers)
Closed 4 months ago.
I wrote a php search for a table in mysqli and it works fine but i want to show the correct message to user if no result were found.
here is my current code:
$search_string=$_GET["design"];
$connect= mysqli_connect("mysql.myhost.com","abc","123456","mydb_db");
$query="select * from product where product_design like '%$search_string%'";
$rows= #mysqli_query($connect,$query) or die("Error: ".mysqli_error($connect));
if ($rows!=null)//I put this if to check if there is any result or not but its not working
{
while(($record=mysqli_fetch_row($rows))!=null)
{
.
.//i have working code for showing the result here
.
}
mysqli_close($connect);
}
else{
echo"no result found";
}
could you please help me what is wrong , even when i search for something which is not exist in the db still the program not displaying "no result found"
Thank you
What you need is mysqli_num_rows specifically the mysqli_result::num_rows bit. This adds a num_rows property to mysqli result sets. This means you can do
$rowCount = $rows->num_rows
There's also a non-OO equivalent ...
$rowCount = mysqli_num_rows($rows);
(The difference is purely one of coding style)
Use one of these to determine how many records are returned and output the appropriate messages.
The following line doesn't make sense, that might be the issue.
while(($record=mysqli_fetch_row($rows))!=null)
However, $row wouldn't return 'null' if it was empty, but be not set. Do it like this:
if ($rows) { echo 'works';} else { echo 'no rows'; }

Categories