How to execute a PostgreSQL PREPARE query with IN () parameters - php

I'm trying to prepare a query from PHP like:
pg_prepare($con, "prep", "select * from test where tid in ($1)");
and then execute it with:
$strpar = "3,4,6,8,10";
pg_execute($con, "prep", array($strpars));
The problem is that I cannot pass a series of values built as prepare expects a fixed number of parameters. Is there any way to make the parameters dynamic?

Use an array to represent the series of values:
pg_prepare($con, "prep", "select * from test where tid=ANY($1)");
$strpar = "{3,4,6,8,10}";
pg_execute($con, "prep", array($strpars));
You can also create a PHP function to receive a PHP array and set it as a valid array for a Postgres prepared statement as in:
function php_array_to_pg ($array) {
$values = "";
foreach ($array as $value) {
if ($values=="") {
$values = $value;
} else {
$values = $values.",".$value;
}
}
return "{".$values."}";
}
Then you make a statement such as:
pg_prepare($con, "prep", "select * from test where tid=ANY($1)");
$array = array(1,2,3,4);
pg_execute($con, "prep", array(php_array_to_pg ($array)));

Related

PHP changing fetch_field() to mysqli

My php knowledge is fairly limited but I've recently needed to update a number of web pages from an older version of php 5.2 to php 7.3.
I've managed to update most of the mysql references to mysqli etc and get things working correctly, however there is one page that makes use of a calendar and I'm really struggling with this section and the fetch_field part in particular as any examples I have found don't seem to be in a similar format.
The code I need to update is below;
require_once('Connections/connAsh.php');
mysql_select_db($database_connAsh, $connAsh);
function selectonerow($fieldsarray, $table, $uniquefield, $uniquevalue)
{
//The required fields can be passed as an array with the field names or as a comma separated value string
if (is_array($fieldsarray)) {
$fields = implode(", ", $fieldsarray);
} else {
$fields = $fieldsarray;
}
//performs the query
$result = mysql_query("SELECT $fields FROM $table WHERE $uniquefield = '$uniquevalue'") or die("Could not perform select query - " . mysql_error());
$num_rows = mysql_num_rows($result);
//if query result is empty, returns NULL, otherwise, returns an array containing the selected fields and their values
if ($num_rows == NULL) {
return NULL;
} else {
$queryresult = array();
$num_fields = mysql_num_fields($result);
$i = 0;
while ($i < $num_fields) {
$currfield = mysql_fetch_field($result, $i);
$queryresult[$currfield->name] = mysql_result($result, 0, $currfield->name);
$i++;
}
return $queryresult;
}
}
My attempts at editing this are;
require_once('../Connections/connAsh.php')
$connAsh->select_db($database_connAsh);
function selectonerow($fieldsarray, $table, $uniquefield, $uniquevalue)
{
//The required fields can be passed as an array with the field names or as a comma separated value string
if (is_array($fieldsarray)) {
$fields = implode(", ", $fieldsarray);
} else {
$fields = $fieldsarray;
}
//performs the query
$result = $connAsh->query("SELECT $fields FROM $table WHERE $uniquefield = '$uniquevalue'") or die("Could not perform select query - " . mysqli_error());
$num_rows = mysqli_num_rows($result);
//if query result is empty, returns NULL, otherwise, returns an array containing the selected fields and their values
if ($num_rows == NULL) {
return NULL;
} else {
$queryresult = array();
$num_fields = mysqli_num_fields($result);
$i = 0;
while ($i < $num_fields) {
$currfield = mysqli_fetch_field($result);
$queryresult[$currfield->name] = mysqli_fetch_array($result, MYSQLI_BOTH);
$i++;
}
return $queryresult;
}
}
The original function is wrong on so many levels. And there is no point in recreating its functionality.
Basically all you are bargaining for here is just a few SQL keywords. But these keywords contribute for readability.
For some reason you decided to outsmart several generations of programmers who are pretty happy with SQL syntax, and make unreadable gibberish
$row = selectonerow("some, foo, bar", "baz", "id", [$uniquevalue]);
instead of almost natural English
$row = selectonerow("SELECT some, foo, bar FROM baz WHERE id=?", [$uniquevalue]);
Come on. It doesn't worth.
Make your function accept a regular SQL query, not a limited unintelligible mess.
function selectonerow(mysqli $conn, string $sql, array $params = []): array
{
if ($params) {
$stmt = $conn->prepare($sql);
$stmt = $mysqli->prepare($sql);
$stmt->bind_param(str_repeat("s", count($params), ...$params);
$stmt->execute();
$result = $stmt->get_result()
} else {
$result = $conn->query($sql);
}
return $result->fetch_assoc();
}
This function will let you to use any query. For example, need a row with max price?
$row = selectonerow("SELECT * FROM baz ORDER BY price DESC LIMIT 1");
Need a more complex condition? No problem
$sql = "SELECT * FROM baz WHERE email=? AND activated > ?";
$row = selectonerow($sql, [$email, $date]);
and so on. Any SQL. Any condition.
I would recommend to get rid of this function or replace it with a function suggested by YCS.
If you really want to continue using this function consider the following fixes. You made the code inside extremely complicated and you forgot to pass the connection variable into the function. I have simplified it:
// open the DB connection properly inside Connections/connAsh.php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$connAsh = new mysqli('host', 'user', 'pass', $database_connAsh);
$connAsh->set_charset('utf8mb4');
// your function:
function selectonerow(mysqli $connAsh, $fieldsarray, $table, $uniquefield, $uniquevalue): array
{
//The required fields can be passed as an array with the field names or as a comma separated value string
if (is_array($fieldsarray)) {
$fields = implode(", ", $fieldsarray);
} else {
$fields = $fieldsarray;
}
//performs the query
$stmt = $connAsh->prepare("SELECT $fields FROM $table WHERE $uniquefield = ?");
$stmt->bind_param('s', $uniquevalue);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
This is your function, but with a lot of noise removed. I added $connAsh in the function's signature, so you must pass it in every time you call this function. The function will always return an array; if no records are fetched the array will be empty. This is the recommended way. Also remember to always use prepared statements!

How to execute prepare statement using if statement in PHP PDO?

I am fetching some data from MySQL database using PHP PDO prepared statement. I have to use if statement inside the execution of the prepared statement. See my codes below for better understanding
$query = "SELECT * FROM my_table WHERE 1=1";
if(isset($_GET['one'])){
$query .= " AND one = :one";
}
if(isset($_GET['two'])){
$query .= " AND two = :two";
}
if(isset($_GET['three'])){
$query .= " AND three = :three";
}
$result = $db->prepare($query);
$result->execute([
/* ------------------------------------
How to declare the above parameters here
as it will show error if any of the if statement is not true?
----------------------------------------*/
]);
I want to know how to declare the prepared array parameter using if statement inside the $result->execute(......]) block?
You need to create an empty $params array, and inside each if block you can push the appropriate value to it. For example:
if(isset($_GET['one'])){
$query .= " AND one = :one";
$params[':one'] = $_GET['one'];
}
Then you can simply do
$result->execute($params);
Note that you can based on what you've written, you could simplify your code with an outer foreach on a list of parameter names e.g.
$names= array('one', 'two', 'three');
$params = array();
foreach ($names as $name) {
if (isset($_GET[$name])) {
$query .= " AND $name = :$name";
$params[":$name"] = $_GET[$name];
}
}
$result->execute($params);

Passing array in where condition in sql query using php

I am trying to pass a array in sql query.
Array contains coloumn names as index they are assigned to their respective values which i got using GET method.
for example iam trying to compile this code :
$a='email';
$b=array($a => $_GET['x']);
$sql="SELECT * FROM users WHERE $b";
echo $sql;
The output that i need is:
SELECT * FROM users WHERE email='/*value of $_GET['x']*/'
the output that i am getting is:
SELECT * FROM users where Array
can some one help me how to make it work.
You need to manipulate the $b array to make it into the string your after, at the moment it's just dumping the content in it's own format.
This version will do what your after...
$b=array($a => $_GET['x']);
$columns = [];
foreach ( $b as $name => $value ) {
$columns[] = "$name = '$value'";
}
$sql="SELECT * FROM users WHERE ".implode(" and ", $columns);
echo $sql.PHP_EOL;
I've made it use and as the condition linking multiple columns, you can change this depending on your requirement.
This version instead uses bind parameters, the place holder is inserted instead of the value in the query and then you will need to bind the $data array to the prepared statement (how depends in the API your using). This is safer and more flexible (and recommended)...
$b=array($a => $_GET['x']);
$columns = [];
$data = [];
foreach ( $b as $name => $value ) {
$columns[] = "$name = ?";
$data[] = $value;
}
$sql="SELECT * FROM users WHERE ".implode(" and ", $columns);
echo $sql.PHP_EOL;

PHP - add new WHERE clause to SQL statement within foreach loop

I've got a checkbox filter where multiple options can be 'checked'. Once they are checked they are stored in a JavaScript array and passed to the php file via ajax. From there, I'm trying to do a foreach loop to get each element in the array and add a new where condition to the SQL statement for each element, and run the query.
JavaScript
var vendors = [];
function filterResults($this)
{
var vendor = $($this).attr('data-id');
if($($this).prop('checked'))
{
var action = 'add';
vendors.push(vendor);
}
else
{
var action = 'remove';
var index = vendors.indexOf(vendor);
if(index >= 0)
{
vendors.splice(index, 1);
}
}
PHP Script that is run (filter-results.php)
if(is_array($_POST['vendors']))
{
$collaterals = $vendor->updateResults($_POST['vendors']);
var_dump($collaterals);
foreach($collaterals as $col)
{
include '../parts/item.php';
}
}
PHP Function containing foreach loop
public function updateResults($vendors)
{
try
{
$items = array();
$sql = "SELECT * FROM collaterals WHERE ";
foreach ($vendors as $ven)
{
echo $ven;
$sql .= "vendor = ".$ven." OR ";
}
$stmt = $this->db->prepare($sql);
$stmt->execute();
while($row = $stmt->fetchObject())
{
$items[] = $row;
}
return $items;
}
catch(Exception $e)
{
$e->getMessage();
}
}
The 'echo' within the PHP function is working, but the var_dump() is turning 'NULL' which means there is an error within the SQL statement somewhere.
Any help would be greatly appreciated. Thanks!
You can this run query without foreach loop as follows
$sql = "SELECT * FROM collaterals WHERE vendor IN ('".implode("','",$vendors)."')";
Your query looks like
SELECT * FROM collaterals WHERE vendor = x OR vendor = x OR
You must remove the last OR.
Also i would suggest using the IN clause with implode() php function.
it will produce "SELECT * FROM collaterals WHERE vendor = 1 OR vendor = 2 OR "
use "Select * FROM collaterals where vendor in(1,2,3)" instead,
Problems:
You're using vendor = item1 OR vendor = item2 OR (notice the hanging OR)
Using IN achieves the same result
You should be using prepared statements
Do this:
$items = array();
$sql = "SELECT * FROM collaterals WHERE vendor IN (".
implode(",",array_fill(0, count($vendors), "?"))
.")";
// $sql would look like e.g. SELECT * FROM collaterals WHERE vendor IN (?,?,?)
$stmt = $this->db->prepare($sql);
$stmt->execute($vendors);
Note: All $vendors will be treated as strings in the above code, if you need to bind them as a different type you should call bindParam or bindValue on each array entry

Array to comma separated strings

This is the code (I'm using Codeigniter):
$sql = 'SELECT * FROM foo WHERE bar IN (?)';
$query = $this->db->query($sql, array($values));
So $values is an array of strings that I want to add in the SQL statement where the "?" is. When I try this I get an "Array to string conversion" error. Is there any way I can add the values of the $values array as comma separated strings into the SQL statement?
Why don't you use simple codeigniter way
$this->db->from('foo');
$this->db->where_in('bar',$values);
$query=$this->db->get();
This will produce what you exactly want
Update
If you are strict with your way you need to produce the $sql this way
$sql = 'SELECT * FROM foo';
if(is_array($values)&&sizeof($values)>0)
{
$sql.=' WHERE bar IN (';
foreach($values as $key=>$value)
{
if($key==0)
{
$sql.='?';
}
else
{
$sql.=',?';
}
}
$sql.=')';
}
$query=$this->db->query($sql,$values);
You should pass string with comma separated in query. for that use implode function of php.
Do like this:
$values = array('bar1', 'bar2', 'bar3');
$string = "'".implode("',", $values)."'";
Then pass string in the query,
$sql = 'SELECT * FROM foo WHERE bar IN ($string)';
$query = $this->db->query($sql);
echo '<pre>'; print_r($query->result_array());
You will data in $query variable.
Let me know for further help if needed.

Categories