I have the function getDistance(). The function findDistance() inside the while loop, calculates the distance between 2 users, by using coordinates (latitude-longitude), and returns to var $djson the distance in meters. $distance is a string committed by the user for first time and $user_old["distance"] is a string which is called from a database in $query. I wanted to be able in $matched_names, to save all the names of the users from my database, for who the condition inside if() is true, regarding the sum of the distance of the new user who commits his data and the old ones inside the database. The problem is that $matched_names saves the first name which is called from the database and for as many times the loop goes on without even considering the if() restriction. For example if the first name called in $user is "Mike", and $user has 5 rows then the output will be: Mike,Mike,Mike,Mike,Mike.
I suppose that i have made some mistake in the way things work inside while..
<?php
public function getDistance($uuid, $name, $distance, $latstart, $lonstart, $latend, $lonend, $gcm_regId) {
$query = sprintf("SELECT uid, gcm_regid, name, distance,latstart, lonstart, latend, lonend FROM user_demand WHERE latstart='%s' AND lonstart='%s'",
mysql_real_escape_string($latstart),
mysql_real_escape_string($lonstart));
$user = mysql_query($query);
$no_of_rows = mysql_num_rows($user);
$user_old = mysql_fetch_assoc($user);
while( $user_old = mysql_fetch_assoc($user)) {
$djson = $this->findDistance($latend,$lonend,$user_old["latend"],$user_old["lonend"] );
if ($user_old["distance"] + $distance >= $djson) {
$match = $this ->df->addUserMatch($user_old['gcm_regid'],$user_old['name'],$gcm_regId,$name);
$matched_names = array_fill(0,$no_of_rows,$user_old['name']);
$matched_gcmz = array_fill(0,$no_of_rows,$user_old['gcm_regid']);
}
}
$registatoin_ids = array($gcm_regId);
$message = array("names" =>$matched_names,"gcm" => $matched_gcmz);
$result = $this ->gcm->send_notification($registatoin_ids, $message);
}
?>
What i usually do is, when I'm going to write something that is complicated, is to get it to working without being in a function then break it down into functions.
It is less confusing and easier to troubleshoot problems that way.
It is kind of hard to tell what it is doing since you didn't post your other function and the if statement relies on the output of that function.
Offhand, it could be this line where you are using the $name and $user_old['name']
$match = $this ->df->addUserMatch($user_old['gcm_regid'],$user_old['name'],$gcm_regId,$name);
I think you would want it to match each other. Like if $name = $user_old['name'] then add it, if not, do something else.
Related
Good day everyone!
Currently I'm trying to find a workaround for my problem. As fair as I am concerned, MySqli doesnt support nested fetch'es, therefore my function doesn't quite work. I've tried to find a fix, but had no luck. My current code:
function viewQuestionnaire($id){
$questionStmt = $this->connection->prepare("SELECT id, type, name FROM TAP_questions WHERE questionnaire_id=?;");
$questionStmt->bind_param("i", $id);
$questionStmt->bind_result($id, $type, $name);
$questionStmt->execute();
$result = array();
while ($questionStmt->fetch()) {
$questions = new StdClass();
$questions->question_id = $id;
$questions->question_type = $type;
$questions->question_options = array();
$questions->question_name = $name;
if($questions->question_type=="2"){
$stmtOptions= $this->connection->prepare("SELECT id, options FROM TAP_options WHERE question_id=?;");
$stmtOptions->bind_param("i", $id);
$stmtOptions->bind_result($qu_id, $qu_opt);
$stmtOptions->execute();
while ($stmtOptions->fetch()) {
$options = new StdClass();
$options->option_id = $qu_id;
$options->option_name = $qu_opt;
array_push($questions->question_options, $options);
}
$stmtOptions->close();
}
array_push($result, $questions);
}
$questionStmt->close();
return $result;
}
As you can see, i'm trying to grab values from database, depending on the question type. If the question type is "2", i need to grab "additional" values from another table. How do i do that?
Vlad
I had more or less exactly this problem two weeks ago and found two working solutions:
1.) Nesting the queries, but using/initializing two different connections for them (even if it's to the same database)
2.) Doing one query first, saving the result in an array and using that array later inside the other query.
If you buffer the result, you can run the second query w/o loosing the result from the first query.
In Mysqli you buffer the result of an executed prepared statement (which by default is unbuffered) via the mysqli_stmt::store_result method.
...
$questionStmt = $connection->prepare(
"SELECT id, type, name FROM TAP_questions WHERE questionnaire_id=?;"
);
$questionStmt->bind_param("i", $id);
$questionStmt->bind_result($id, $type, $name);
$questionStmt->execute();
/* store result */
$questionStmt->store_result();
...
/* free result */
$questionStmt->free_result();
$questionStmt->close();
...
I have a mysql query:
$analyse_ot1="SELECT COUNT(*) AS ot_count FROM first, base, users
WHERE base.base_id=$base
AND
users.base_id=$base
AND
users.id=first.user_id
AND
first.$sub='OT'";
$result_ot1=mysqli_query($con,$analyse_ot1);
$row_ot1= mysqli_fetch_assoc($result_ot1);
$total_ot1= $row_ot1['ot_count'];
$otper1=($total_ot1/$total)*100;
I will be re-using this code many times on a web-page and want to be able to run it as part of a loop.
I don't want to have to rename my variables each time (where $result_ot1 become $result_ot2 etc...)
I've tried introducing an indexing variable $x and then appending it to another variable name:
$x=2;
$result_ot.$x=....
But , it doesn't want to work.
Any suggestions? I have an idea that arrays might be needed but I'm concerned that the queries will be throwing up arrays and I'm not sure an array in an array isn't going to set my computer on fire...
A hint to use your query everywhere.
//declare this in a folder, 'functions.php', for example
function analyse($base, $sub, $con)
{
$analyse_ot1 = 'SELECT COUNT(*) AS ot_count FROM first, base, users'
." WHERE base.base_id=$base AND users.base_id=$base"
." AND users.id=first.user_id AND first.$sub='OT'";
$result_ot1 = mysqli_query($con, $analyse_ot1);
$row_ot1 = mysqli_fetch_assoc($result_ot1);
return $row_ot1['ot_count'];
}
And in any other place of your project:
include 'functions.php';
$total_ot1 = analyse($base, $sub, $con);
$otper1 = ($total_ot1 / $total) * 100;
I did not understand well the loop thing. But in order to dave your results in an array, you could just do this:
$totalCounts = [];
foreach(loop){
$total_current = analyse($base, $sub, $con);
$totalCounts[] = $total_current;
}
And you will have $totalCounts that will be an array of the query result that we find in our function. That could be a way of saving your results in an array.
You could do it associative also:
$x = 0;
foreach(loop){
$total_current = analyse($base, $sub, $con);
$totalCounts['count_'.$x] = $total_current;
$x++;
}
So, if you now access: $totalCounts['count_3'] you would be accessing the result of the query on the third loop, for example.
I don't know if this is your answer. But maybe it helped a bit.
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
hello i want to create function with returning data, for example when i have the function advert i want to make it every time show what i need, i have the table id, sub_id, name, date, and i want to create the function that i can print every time what i need advert(id), advert(name), i want to make it to show every time what i need exactly and i want to save all my result in array, and every time grab the exactly row that i want
<?php
function advert($data){
$id = $_GET['id'];
$query = mysql_query("SELECT *FROM advertisement WHERE id = $id");
while($row = mysql_fetch_assoc($query)){
$data = array(
'id' => $row['id']
);
}
return $data;
}
echo advert($data['id']);
?>
but my result every time is empty, can you help me please?
There are so many flaws in this short piece of code that the only good advice would be to get some beginners tutorial. But i'll put some effort into explaining a few things. Hopefully it will help.
First step would be the line function advert($data), you are passing a parameter $data to the method. Now later on you are using the same variable $data in the return field. I guess that you attempted to let the function know what variable you wanted to fill, but that is not needed.
If I understand correctly what you are trying to do, I would pass in the $id parameter. Then you can use this function to get the array based on the ID you supplied and it doesnt always have to come from the querystring (although it could).
function advert($id) {
}
Now we have the basics setup, we want to get the information from the database. Your code would work, but it is also vulnerable for SQL injection. Since thats a topic on its own, I suggest you use google to find information on the subject. For now I'll just say that you need to verify user input. In this case you want an ID, which I assume is numeric, so make sure its numeric. I'll also asume you have an integer ID, so that would make.
function advert($id) {
if (!is_int($id))
return "possible SQL injection.";
}
Then I'll make another assumption, and that is that the ID is unique and that you only expect 1 result to be returned. Because there is only one result, we can use the LIMIT option in the query and dont need the while loop.
Also keep in mind that mysql_ functions are deprecated and should no longer be used. Try to switch to mysqli or PDO. But for now, i'll just use your code.
Adding just the ID to the $data array seems useless, but I guess you understand how to add the other columns from the SQL table.
function advert($id) {
if (!is_int($id))
return "possible SQL injection.";
$query = mysql_query("SELECT * FROM advertisement WHERE id = $id LIMIT 1");
$row = mysql_fetch_assoc($query);
$data = array(
'id' => $row['id']
);
return $data;
}
Not to call this method we can use the GET parameter like so. Please be advised that echoing an array will most likely not give you the desired result. I would store the result in a variable and then continue using it.
$ad = advert($_GET['id']);
if (!is_array($ad)) {
echo $ad; //for sql injection message
} else {
print_r($ad) //to show array content
}
Do you want to show the specific column value in the return result , like if you pass as as Id , you want to return only Id column data.
Loop through all the key of the row array and on matching with the incoming Column name you can get the value and break the loop.
Check this link : php & mysql - loop through columns of a single row and passing values into array
You are already passing ID as function argument. Also put space between * and FROM.
So use it as below.
$query = mysql_query("SELECT * FROM advertisement WHERE id = '".$data."'");
OR
function advert($id)
{
$query = mysql_query("SELECT * FROM advertisement WHERE id = '".$id."'");
$data = array();
while($row = mysql_fetch_assoc($query))
{
$data[] = $row;
}
return $data;
}
Do not use mysql_* as that is deprecated instead use PDO or MYSQLI_*
try this:
<?php
function advert($id){
$data= array();
//$id = $_GET['id'];
$query = mysql_query("SELECT *FROM advertisement WHERE id = $id");
while($row = mysql_fetch_assoc($query)){
array_push($data,$row['id']);
}
return $data;
}
var_dump($data);
//echo advert($data['id']);
?>
I'm trying to create a more succinct way to make hundreds of db calls. Instead of writing the whole query out every time I wanted to output a single field, I tried to port the code into a class that did all the query work. This is the class I have so far:
class Listing {
/* Connect to the database */
private $mysql;
function __construct() {
$this->mysql = new mysqli(DB_LOC, DB_USER, DB_PASS, DB) or die('Could not connect');
}
function getListingInfo($l_id = "", $category = "", $subcategory = "", $username = "", $status = "active") {
$condition = "`status` = '$status'";
if (!empty($l_id)) $condition .= "AND `L_ID` = '$l_id'";
if (!empty($category)) $condition .= "AND `category` = '$category'";
if (!empty($subcategory)) $condition .= "AND `subcategory` = '$subcategory'";
if (!empty($username)) $condition .= "AND `username` = '$username'";
$result = $this->mysql->query("SELECT * FROM listing WHERE $condition") or die('Error fetching values');
$info = $result->fetch_object() or die('Could not create object');
return $info;
}
}
This makes it easy to access any info I want from a single row.
$listing = new Listing;
echo $listing->getListingInfo('','Books')->title;
This outputs the title of the first listing in the category "Books". But if I want to output the price of that listing, I have to make another call to getListingInfo(). This makes another query on the db and again returns only the first row.
This is much more succinct than writing the entire query each time, but I feel like I may be calling the db too often. Is there a better way to output the data from my class and still be succinct in accessing it (maybe outputting all the rows to an array and returning the array)? If yes, How?
Do you actually have a performance issue?
If your current setup works and doesn't suffer from performance issues, I wouldn't touch it.
This sort of DB access abstraction will likely become a maintenance issue and probably won't help performance.
Also, you're susceptible to SQL injection.
You should be able to store the whole object from the query into a variable and then access the single values from that object:
$object = $listing->getListingInfo('','Books');
$title = $object->title;
$price= $object->price;
But you can also use fetch_assoc() and return the whole assiciative array:
$array = $listing->getListingInfo('','Books');
$title = $object['title'];
$price= $object['price'];
This will give you the same results and also with only one query to the DB.
EDIT: If the getListingInfo() is the only function you should think of the following:
rename the function to prepareListingInfo() and within the function only prepare the query and store it in a class variable.
add a getNextListingInfo() function, which will return an object or associative array with the next row.
Using this new function, you can get every row that matches your query.
Either cache the result in an internal var
Or Comment it with a warning and explain to function users to copy the result in an var instead of calling it again and again with the same params
Yes, that would be calling the db too often.
A couple of solutions
1) put the listing info in a variable
2) cache the results in a hashmap or dictionary (be careful for memory leaks)