mysqli_multi_query array issue - php

There's something weird going on.
I have I database which could look something like this:
table name: dm
|id|receiver|sender|msg |
|1 |John |Emma |Hey John! |
|2 |Emma |John |Hey! |
|3 |John |Emma |Whats up |
|4 |Emma |John |Not too much |
|5 |John |Keira |Have you got...|
I have an html page with a on it and for now what I want is for the messages that either
Emma sent to John => receiver = "John", sender = "Emma" or
John sent to Emma => receiver = "Emma", sender = "John"
to be displayed in the console.
I can do that with JQuery using the console.log() function.
My PHP looks like this:
$user1 = "John";
$user2 = "Emma";
$sql = "SELECT * FROM dm WHERE receiver = '$user1' AND sender = '$user2';SELECT * FROM dm WHERE receiver = '$user2' AND sender = '$user1'";
// Execute multi query
if (mysqli_multi_query($link,$sql))
{
do
{
$i = 0;
$msg = array();
if ($result=mysqli_store_result($link)) {
while ($row=mysqli_fetch_row($result))
{
printf("%s\n",$row[0]);
$msg[$i] = $row[0];
$i++;
}
mysqli_free_result($result);
}
}
while (mysqli_next_result($link));
}
echo json_encode($msg);
exit();
mysqli_close($link);
You will notice, that I have "printf" in there, because I wanted to see what the databse would give back to me. It correctly gave back the id's: 1,3,2,4.
However, I normally would like to do the request using JQuery ajax. I know how to do that also. Because of that I want to have an array which holds all the id's of the posts like this:
["1","2","3","4"]
Unfortunately the way I do it as written in the code what it returns to me is this:
["2","4"]
So what's going on is that he only puts what was in the first query into the array.
So what exactly is my question?
I want to fix the array to hold all the id's of the respective messages which would be 1,2,3,4. Preferably in this order as well and not like this 1,3,2,4.
I hope I made the problem clear and thank you for any advice!

You reset $i and $msg inside the outer loop. That means you will only see results from the second query in your array. Move the $i = 0; and $msg = array(); lines outside that loop.
That said, there’s no reason to do 2 queries here. Just use an OR in your WHERE clause to get both results at once. This will be faster and easier.
Also, this is very important: you are wide open to SQL injection. You need to use prepared statements, rather than concatenating variables into your query. See How can I prevent SQL injection in PHP?.

Related

PHP- Multiple variables in mysql query

I want to get the value from the Epic[2] column.
The mysql table looks like that:
ID | Epic[0] | Epic[1] | Epic[2] | Epic[3]
-----------------------------------------------
440 xy xy xy xy
I have three variables where the informations are stored.
$qualitybudget = "Epic"
$budgetType = "2"
$itemlevel = "440"
I tried the following:
$sql = "SELECT '$qualitybudget'['$budgetType'] FROM `randproppoints` WHERE id = '$itemlevel'";
Output looks like that:
SELECT 'Epic'['2'] FROM `randproppoints` WHERE id = '440'
As you see 'Epic'['2'] has the wrong syntaxing. The output for the working query should be like: Epic[2]
What is the right syntax handling in a mysql query like that?
Use
$sql = "SELECT `${qualitybudget}[$budgetType]` FROM `randproppoints` WHERE id = '$itemlevel'";
instead. This way, the column name is exactly formatted as you wish and encapsulated.
Note that the syntax ${xyz} has to be used to make it clear that only xyz is the name of the variable and that this is all to be printed here. Otherwise, PHP assumes it is an array and evaluates the following squared brackets for the same string insertion. Another example where this syntax has to be used is if for instance you had a variable $a = "thing"; and wanted
$b = "there are three $as";
to get "there are three things". It would not work as PHP would assume you address a variable $as, but the fix would seem like this:
$b = "there are three ${a}s";

In php how do I execute code stored in a mysql field as php code?

I plan to store some code, possibly mixed with simple html in a database field:
MariaDB [mysql]> select id,code, script from articles where id=117;
+-----+-----------------------------------------+----------------+
| id | code | script |
+-----+-----------------------------------------+----------------+
| 117 | <?php echo "Good Golly Miss Molly<br />"; ?> | code/hello.php |
+-----+-----------------------------------------+----------------+
1 row in set (0.00 sec)
Looking at some other posts eval() is typically the way to go, but eval does not seem to work when you include php tags or possibly raw html.
$query = "
select
code,
script
from articles
where articles.id = 117
";
$result = $mysqli->query($query);
$row = mysqli_fetch_array($result);
$code = $row["code"];
$script = $row["script"];
eval($code);
eval("$code");
Both work with raw code (no ) tags, but fail with the tags and plain html. Another way to get the job done is to place the script or html in a file and use include().
Is there a way to use eval() to execute mixed code with tags and raw html?
-------------------- Note added: Friday, Oct 18, 2019 --------------
Here's a hacky way to solve the problem:
$rand = substr(md5(rand()), 0, 24);
$fpi = fopen("$some_folder/$rand.php", "w");
fwrite($fpi, "$code");
fclose($fpi);
include ("$some_folder/$rand.php");
unlink ("$some_folder/$rand.php");
No comment regarding security, but this does get you from point A to point B

PHP array that outputs field names and values as variables

I am struggling a little bit with a tricky PHP array. I am trying to retrieve data from a database (a single row) and I want to plug this data in a bunch of dynamically generated fields on the page (PHP).
My DB is organised as follows
____________________________
| cats | dogs | birds | cows |
_____________________________
| 30 | 40 | 22 | 34 |
______________________________
I would like to build an array like this:
array(
$cats => $cats_value
$dogs => $dogs_value
etc...
)
Importantly: I want the array to ouput variables, where in the above example $cats outputs "cats" and $cats_value outputs "30". I am guessing once this is done that I can use the variable names directly, so I won't have to go nuts trying to pull them out of the array...
I have tried to put various bits of code but have failed miserably (i.e. nothing to show/embarrass myself with on here.)
Any help would be much appreciated.
OK, the code that provides the answer is as follows:
$query = "SELECT * FROM animals";
$result = mysqli_query($dbc, $query);
$data_array = array();
$row = mysqli_fetch_assoc($result);
print_r($row);
foreach($row as $key=>$value){ echo $key; echo $value;
${$key}=$key;
${$key."_value"}=$value;
}
echo "<br><br><br>";
echo $Cats." = ".$Cats_value."<br>";
echo $Dogs." = ".$Dogs_value."<br>";
echo ${"Cows"}." = ".$Cows_value."<br>";
echo ${"Birds"}." = ".$Birds_value."<br>";
I appreciate all the answers that helped me find the answer to this. As an aside, the whole reason I am doing this is because I need to populate a dynamically generated PHP page with a bunch of variables, and that I will likely need to populate these variables dynamically as well.
If you think I am approaching this problem the wrong way, then please let me know (i.e. is it dumb to convert an associative array into a bunch of $variables? Does that make sense, and/or could it really slow down my page?)

Save multiple value in database, use row in PHP

I have a question about how I can save different value in order if I GET 1 row in php.
For example, if I have like:
*Feder|100|50|10|5|9|0|0|0|0|0|0 PHP LINE
I need to save this row in the table like:
----------------------------------------------
name | score | status | point | level | bla | bla | bla....
----------------------------------------------
Feder| 100 | 50 | 10 | 5 | 0 | 0......
-------------------------------------------------
Now, I use easy method to get something in the database like:
$sql="INSERT INTO user (name, score, status)
VALUES
('$name','$score','$status')";
mysqli_query($con,$sql);
With this, when I get the value, I use like:
save.php?name=feder&score=100&status=50
But if I have to insert 40 values, will this be very hard? I think is possible to make easy, but I don't have any idea how I can do that... Someone know the best method to do this?
If I can use like: save.php?userdata=(all row)* is better...
What you ask for is not recommended for security reasons. It's one of the biggest no-nos to trust GET contents and put it straight into an SQL query.
But.
Of course you can foreach the variable $_GET like this:
$x="";
foreach($_GET as $key=>$val) {
$x.=" $key = '$val', ";
}
$sql = "insert into myTable set $x";
This is just the principle of it. You should ALWAYS check for the field names and values to avoid injection attacks. So a better approach would be like:
$isValid = array("name"=>1,"score"=>1,"status"=>1);
$x="";
foreach($_GET as $key=>$val) {
if(!$isValid[$key]) continue; // skip unknown fields!
$val = stripslashes($val); // remove magic quote junk
$val = mysql_real_escape_string($val); // protect mysql from attacks
$x.=" $key = '$val', "; // build the query
}
$sql = "insert into myTable set $x";
UPDATE
If you get all the values in one string like "aaa|bbb|ccc", you can use explode() to parse them into one array. But then you rely on the order of fields which is not a good practice. I'd recommend to always prefer "field1=aaa&field2=bbb" style.
Hope this helps.
Think about the risks and find your own way.
You said 40 row. You have to remember that the limitation of length of an URL. So the suitable way is to use POST method through a HTML form. Taking care in multible fields naming by adding [] to the field name:
<form method="post" action="some.php">
<input type="text" name="name[]" />
<input type="text" name="score[]" />
...
</form>
and from your PHP
for ($i = 0; $i < count($_POST['name']); $i++){
$name = $_POST['name'][$i];
$score = $_POST['score'][$i];
$status = $_POST['status'][$i];
$sql="INSERT INTO user (name, score, status)
VALUES
('$name','$score','$status')";
mysqli_query($con,$sql);
}
Notice: This answer is about the concept of inserting multiple records. It does not meant by the security of receiving data.

zend framework: how to prepare and execute WHERE IN clause?

I want to prepare a statement for use inside a loop. When I try to execute the statement I see an error in the logs saying "Invalid parameter number: no parameters were bound'".
What's wrong with my code?
$itemSelectSql = "SELECT * FROM `tblItems` WHERE `itemID` IN (?)";
$itemSelectStmt = new Zend_Db_Statement_Mysqli($this->db_ro, $itemSelectSql);
while () {
...
$itemIds = array();
// populate $itemIds array
...
$itemSelectStmt->execute(array($itemIds));
}
EDIT:
I think I may have a bug in my set up which explains why whatever I try fails. I'm seeing this:
PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback,
class 'PDOStatement' does not have a method 'bind_param' in
/var/www/lib/Zend/Db/Statement/Mysqli.php on line 204
EDIT:
I was using the wrong adapter. Should have been Zend_Db_Statement_Pdo :-)
Thanks for the replies.
? can't be replaced by an array, it has to be replaced by a scalar (thanks to comment for pointing out that this does not always mean string... brain-fart on my end). Let me know if this works better:
$itemSelectSql = "SELECT * FROM `tblItems` WHERE `itemID` IN ";
while () {
...
$itemIds = array();
// populate $itemIds array
...
// we need to have the same number of "?,"'s as there are items in the array.
// and then remove final comma.
$qs = rtrim(str_repeat("?,", count($itemIds)),',');
// create a statement based on the result
$itemSelectStmt =
new Zend_Db_Statement_Mysqli($this->db_ro, "$itemSelectSql ($qs)");
// bind to each of those commas.
$itemSelectStmt->execute($itemIds);
}
Have you tried doing this:
while () {
...
$itemIds = array();
// populate $itemIds array
$itemIds = implode(',' $itemIds);
$itemSelectStmt->execute(array($itemIds));
}
I'm not an expert of Zend_framework, but when you use statements, to the execute method you must
If you use positional parameters, or
those that are marked with a question
mark symbol ('?'), pass the bind
values in a plain array.
So i think you need to pass an array with one value and that value replace the "?" in the statement. In this case you need a comma separated string (if you ids are int) to replace (?) in the statement.
What you do if you do not implode the values is passing an array containing an array.
You might use FIND_IN_SET(str,strlist) instead of IN ():
mysql> select id, name from customer where find_in_set(id, '10,15,20');
+----+---------+
| id | name |
+----+---------+
| 10 | ten |
| 15 | fifteen |
| 20 | twelve |
+----+---------+
This way, you don't have to bind array with multiple values to IN(), you can pass list of IDs as a single comma-separated string. You can safely use PHP function implode() to generate string from array of IDs.
Though, I'm not sure if it has any impact on performance.
I took a look at output of explain, and it looks like find_in_set() is not able to use indexes, so generating queries with variable number of parameters should perform better.

Categories