PHP Red Bean MySQL multi-value binding evaluation in getAll() - php

I have an array in php containing strings, which I want to use in a query with Red Bean MySQL in the following manner:
$someString = '\'abc\',\'def\',\'ghi\'';
R::getAll("select * from table where name not in (:list)", array(':list'=> $someString));
The problem is that the list is not being evaluated correctly no matter how I set the values in the array string, and the names abc, def, ghi are returned in the result. I've tried the following:
$someString = '\'abc\',\'def\',\'ghi\''
$someString = 'abc\',\'def\',\'ghi'
$someString = 'abc,def,ghi'
running the query in the SQL server manually works and I don't get those values returned, but running it within the php code with redbean is not working, and it seems that the list is not being interpreted correctly syntax-wise.
Can anyone shed some light on the matter?

Thanks to RyanVincent's comment I managed to solve the issue using positional parameters in the query, or more specifically, the R::genSlots function.
replaced the following:
$someString = '\'abc\',\'def\',\'ghi\'';
R::getAll("select * from table where name not in (:list)", array(':list'=> $someString));
with:
$someArray = array('abc', 'def', 'ghi');
R::getAll("select * from table where name not in (". R::genSlots($someArray) .")", $someArray);
This creates a $someArray length positions for parameters in the query, which are then filled with the values in the second parameter passed to the getAll function.
Notice that in this case I used a set content array (3 variables) but it will work dynamically with any length array you will use.
Furthermore, this can also work for multiple positions in the query, for example:
$surnameArray = array('smith');
$arr1 = array('john', 'pete');
$arr2 = array('lucy', 'debra');
$mergedVarsArray = array_merge($surnameArray,$arr1);
$mergedVarsArray = array_merge($mergedVarsArray,$arr2);
R::getAll("select * from table where surname != ? and name in (." R::genSlots($arr1).") and name not in (". R::genSlots($arr2) .")", $mergedVarsArray);
This code will effectively be translated to:
select * from table where surname != 'smith' and name in ('john','pete') and name not in ('lucy', 'debra')
Each '?' placed in the query (or generated dynamically by genSlots() ) will be replaced by the correlating positioned item in the array passed as parameter to the query.
Hope this clarifies the usage to some people as I had no idea how to do this prior to the help I got here.

Related

PHP, MySQL - Return which value was used when input is an array?

I'm running a PDO query, something like:
$inputArr = array(val1, val2, val3, ...);
$qMarks = str_repeat('?,', count($inputArr) - 1) . '?';
$stmt = $db->prepare("SELECT id, name, type, level
FROM table
WHERE name IN ($qMarks)");
$stmt->execute($inputArr);
... parse the rows that have been returned
And this works exactly as expected, no hang-ups or anything.
My problem is that I need to know which value from $inputArr was used to get each row returned.
I've tried
WHERE name IN ($qMarks) AS inputVal
and
WHERE name IN ($qMarks AS inputVal)
but those crash the query.
How can I determine which input array value was used to return each row in the output?
EDIT 1
Yes, I understand that the input search value would be name, for this particular case, but the query above is only for demonstration purposes of how I am putting the search values into the query.
The actual is much more complex, and returns any name value with is close (but not always identical).
The AS keyword is not going to work as you expect it. It's mainly used for aliasing subqueries. You can't (to my knowledge) use it in a WHERE clause.
The scenario you've outlined should have the 'name' in $row['name']. If it was a different variable that you wanted to see, you'd simply add it in your SELECT clause.
Great question, and simple answer:
The WHERE name IN $qMarks)"); part of your code is only obtaining the values in your database that are matching your array, so what you can do is see which values of name are present in the row you fetched. For example:
$rows_fetched = $stmt->fetchAll(PDO::FETCHASSOC);
$inputArray = array();
foreach($rows_fetched as $value)
{
$inputArray[] = $value['name'];
}
print_r($inputArray);//printing the results
Now you have the array $inputArray with all the values used to return each row in the output. Let me know if that worked for you!

Issues with using implode after pushing the variables into the array

I am currently testing how to use a simple implode for a mysql query after I have pushed the variables into the array. I just can't get around the error, I know it says, invalid arguments, but the array has been set up and I know it worked in another part of my page with an almost identical code.. I guess there are somewhere missing some ' or " or . or but no matter what I change it doesn't work.
I appreciate any help!
Here is the part where I set up the array:
$LFBsubjects = Array();
$LFBsubjects[] = $dataset2['subject1'];
$LFBsubjects[] = $dataset2['subject2'];
And the output I have printed via print_r is:
Array ( [0] => Mathematics [1] => English )
Now comes the query, which uses the implode function:
$SelectTSubjectsQuery = "
SELECT subject_id FROM subjects
WHERE subject IN (".implode(',', $LFBSubjects).")";
$statement = $pdo->query($SelectTSubjectsQuery);
The error is:
Warning: implode(): Invalid arguments passed in /var/www/xxx/html/lfb.php on line 626
Invalid argument error means you need to use quotes between string for MYSQL QUERY like IN ("test")
You can use as like:
$values = implode("','", $LFBsubjects);
$SelectTSubjectsQuery = " SELECT subject_id FROM subjects WHERE subject IN ('".$values."')";
Explanation:
Your array consists on string values when you use IN RANGE in MYSQL for string values than you must need to pass it in quotes.
Basic example:
$SelectTSubjectsQuery = "
SELECT subject_id FROM subjects
WHERE subject IN ('val1','val2')";
Update 1
After checking your comments, you are using wrong variable name in implode
$LFBSubjects
This should be this:
$LFBsubjects // with small s

SQL not returning rows present in table correctly

I have an issue with a table in a database. There are three columns as follows:
Name (VARCHAR(25))
QText (TEXT)
AText (TEXT)
My query is run through PDO as:
SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = '$name' AND `QText` = '$question'
After processing it looks like this and obviously the length of the $question variable will change:
SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = 'ExamServerTestExam' AND `QText` = 'This is the first question'
From what I can see depending on the length of the string in place of $question, sometimes it will return a row, other times it returns nothing.
If the string is short (27 chars) then it returns the 'AText' content for that row, though if the string is long (106 chars) nothing if $question is a long string. I checked the entry in the database and the entire string is present, so the row is there exactly as it is being searched for.
I have also tried using:
SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = '$name' AND `QText` LIKE '%$question%'
Can't understand if this is a database issue or not and if so why? It appears to be a problem with the length of the input string.
Thank you very much.
So after some tests, I discovered that the search doesn't like a string that is over 80 characters long. In order to do this but still get the same result I input the string with a wildcard as shown in the following codeblock:
function grab_ans_given_ques($conn, $question, $examName){
// Split the string here into two parts and join with a wildcard (%)
$ques = substr($question, 0, 20)."%".substr($question, -20, strlen($question));
$sql = $conn->prepare("SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = '$examName' AND `QText` LIKE '%$ques%'");
$sql->execute();
Thank you all who gave some advice or tried to help with this!

Converting exploded array into string

In the project that I am creating, I have a mysql column that is an array of different pieces of data from the database. These pieces of data have info that I want to display. In order to separate these items in the array I used,
$get_query = mysql_query('Select array FROM data');
while($dataRow = mysql_fetch_assoc($getfrnd_query)) {
$array = $dataRow['array'];
if($array != "") {
$data_from_array_column = explode("," $array);
$getdata = mysql_query("SELECT * FROM info WHERE item = $data_from_array_column");
//Then I used a mysql_fetch_assoc to get data based on the item.
}
}
When I run this code, I get an error "Array to string conversion on the line with $getdata".
Is there any way to get this to work?
Thank you.
The problem is that explode returns an array containing the strings in between the character(s) you used as a delimiter (, in your case), not a string.
PHP is getting mad because it doesn't know how to convert your array to a string automatically. So, you will need to convert it yourself. The options are:
You want to select the row where item is equal to the nth element in the array, $data_from_array_column. If this is the case, you need to insert the following line of code after your explode:
$data_from_array_column = $data_from_array_column[0];
If you want to select where it matches any of the elements in the $data_from_array_column array, it will get more complicated. You would need to add this line after the explode:
$data_from_array_column = implode("' OR item='",$data_from_array_column);
and change your query on the next line to:
$getdata = mysql_query("SELECT * FROM info WHERE item='$data_from_array_column'");
This will create a MySQL query that looks some thing like this:
SELECT * FROM info WHERE item='foo' OR item='bar' OR item='bla'

PHP to PostgreSQL insert unnested arrays into multiple rows

I have some data in PHP arrays/variables ready to insert into a PostgreSQL table via an INSERT statement.
For a simple example say I have the following information:
$name= 'someName';
$time = array(1,2,3);
$elevation = array(100,200,300);
(In my real application these are double precision and potentially 1,000+ values)
I also have my postgresql table with columns "name","time","elevation"
I want to insert these in a single INSERT statement, and have been given multiple different ways to do this.
Loop and insert one data point (row) at a time.
Use unnest() on the arrays and do a single insert (fastest)
My question is can I pass a single variable name, and the un-nested arrays and have name repeated every row (ever array element), or do I need to construct a repeated array for name the equivalent count() as the other arrays?
An example statement:
*cr_query is a custom PHP pg_query wrapper we use
cr_query($conn,"INSERT INTO sometable (name,time,elevation) VALUES ({$name},{unnest($time)},{unnest($elevation)}););
This would insert into sometable:
ID name time elevation
1 someName 1 100
2 someName 2 200
3 someName 3 300
Am I correct here or do I need to do something else?
EDIT:
Lets say I also have another variable "surface". Surface can be a double value or can be NULL. So I want to insert into the table to look like so:
ID name time elevation surface
1 someName 1 100 50
2 someName 2 200 NULL
3 someName 3 300 100
In PHP, using the method perscribed by klin below an array for surface in the unnest statement would become unnest(array[50,,100]); This throws an error like so:
(Error from my real data)
ERROR: syntax error at or near "," LINE 3: ...-6,5.75E-6,5.75E-6,5.75E-6,5.75E-6]),unnest(array[,,,,,,,,,]... ^
EDIT 2:
Now that all of the "encoding" is working a new problem has popped up. Say the example column "surface" above is type double precision.
Say I am inserting an array, but for this set all of the data is null.
The essential piece is:
unnest(array[null,null,null,null,null,null,null,null,null,null])
However, this array is of type string. Add a single value to it and it becomes the type of that numeric value, but I need to be able to handle this.
My question is: How do I insert an unnested array of all null values into a double precision column? (I tried to cast ::double precision) but it's not possible.
Assuming your cr_query() function is not doing any magic things, your code is going to raise postgres syntax error. You can use unnest but you must prepare proper query text.
Try your code:
$name= 'someName';
$time = array(1,2,3);
$elevation = array(100,200,300);
echo "INSERT INTO sometable (name,time,elevation) VALUES ".
"({$name},{unnest($time)},{unnest($elevation)})"
echo: INSERT INTO sometable (name,time,elevation) VALUES (someName,{unnest(Array)},{unnest(Array)})
Obviously it is not what we want to send to postgres. How to repair this?
$name= 'someName';
$time = array(1,2,3);
$elevation = array(100,200,300);
$timestr = 'array['. implode(',', $time). ']';
$elevstr = 'array['. implode(',', $elevation). ']';
echo "INSERT INTO sometable (name,time,elevation) ".
"VALUES ('$name',unnest($timestr),unnest($elevstr));"
echo: INSERT INTO sometable (name,time,elevation) VALUES ('someName',unnest(array[1,2,3]),unnest(array[100,200,300]));
I think this is correct query. Note that I enclosed text variable '$name' in single quotes.
If you have nulls in your arrays you have to replace all empty strings to 'null' in prepared text for query.
Probably the simplest way to do it is to use str_replace().
As the conversion is getting more complicated it is handy to write a function (say "pgstr()") for that purpose.
function pgstr($array) {
$str =
str_replace('[,', '[null,',
str_replace(',]', ',null]',
'array['. implode(',', $array). ']'));
while (strpos($str, ',,') > 0) $str = str_replace(',,', ',null,', $str);
return $str;
}
$name= 'someName';
$time = array(1,2,3,4);
$elevation = array(100,null,300,null);
$surface = array(null,null,3.24,null);
$timestr = pgstr($time);
$elevstr = pgstr($elevation);
$surfstr = pgstr($surface);
echo
"INSERT INTO sometable (name,time,elevation,surface) ".
"VALUES ('$name',unnest($timestr),unnest($elevstr),unnest($surfstr));";

Categories