php Array to string conversion error on query concatenation - php

//Laravel code
This is my php code I am not getting what is the error and where,please any one help me out
static function getall($input) {
$sql = "SELECT * FROM radio_city";
$where = [];
$params = [];
if ($input['city']) {
$where[] = "city = ?";
$params[] = $input['city'];
} else {
$where = '';
}
$sql .= $where;
$sql .= "\nGROUP BY city";
//echo $sql;
return DB::select($sql, $params);
}

$input and $where are both arrays and you're attempting to coerce string concatenation.
The lines in question are
$sql = "SELECT * FROM radio_city WHERE city=".$input."";
and
$sql .= $where;
I'm not sure what you're trying to do, but it appears to me that you should remove everything after "WHERE" in your stub SQL query.
Also, you'll have to make up your mind with respect to $where's datatype, in either case you don't need that else block that sets $where to an empty string. So either initialize $where to an empty string and concatenate each condition with AND/OR, or initialize to an array and push either AND or OR conditions and then implode before concatenating to your stub.
Edit: just a shot in the dark of what you're looking for...
static function getall($input) {
$where = [];
$params = [];
$sql = 'SELECT * FROM radio_city';
if (isset($input['city']) && $input['city']) {
$where[] = ' city = ?'; // Subsequent additions to $where should specify AND/OR conditional
$params[] = $input['city'];
}
$sql .= implode(',', $where);
$sql .= " GROUP BY city";
return DB::select($sql, $params);
}
Untested. Don't just copy & paste though. If it works, great, but see what's changed and try to really understand why it changed, or ask here if you don't know.

This:
$sql = "SELECT * FROM radio_city WHERE city=".$input."";
Contradicts this:
if ($input['city']) { ....
What is $input? Is it an array? Is it a string? If it is an array, as I suspect and as the second line suggests, the error will be with the first, and you probably want:
$sql = "SELECT * FROM radio_city WHERE city=" . $input['city'];
...though the second line suggest you aren't sure if $input['city'] exists. Incidentally, better use empty() there:
if ( ! empty($input['city'])) { ....
As what you're doing is trying to evaluate what it appears you intend to be a string as a boolean value.
As Utkanos comments, though, Whoa! Format the code, consider the logic more fully. Not much point worrying about whether $input['city'] exists after you've concatenated it onto a string...

Related

How do I re-write this SQL statement to accept the array variable?

I am making an API call to retrieve user_name's from my database.
My first step is to make a call to retrieve all the player_id's. They are stored in $communityPlayersIds and currently output as below:
["2","31","31","32"]
I now want to make a second call to the database to fetch the user_name's of the id's that match.
$communityPlayerNames = array();
$communityPlayerNames = $dao->getPlayerNames($communityPlayersIds);
I have looked into it and seen I should use an IN command something like this:
public function getPlayerNames($player_ids)
{
$returnValue = array();
$sql = "SELECT user_name\n"
. "FROM users\n"
. "WHERE id IN ( '".$player_ids."')";
$result = $this->conn->query($sql);
if($result != null && (mysqli_num_rows($result) >= 1)){
while($row = $result -> fetch_array(MYSQLI_ASSOC)){
if(!empty($row)){
$returnValue[] = $row;
}
}
}
return $returnValue;
}
}
However this isn't working and returns this:
[{"user_name":null}]
If I echo ($sql) I get this:
SELECT user_name FROM users WHERE id IN ( '2,31,31,32')
Which looks correct does it not?
Where am I going wrong?
You essentially want your final query to look like this
Select user_name from users where id in (2,31,31,32) -- dupe 31 does no harm
Make sure your series of IDs are inside parentheses IN ($player_ids) and not just a single quote IN '$player_ids'
You can try building the IN-part of the SQL like this:
$returnValue = array();
$in_statement = "(";
foreach($player_ids as $player_id)
{
$in_statement = $in_statement.$player_id->player_id.",";
}
rtrim($in_statement, ",");
$in_statement = $in_statement.")";
$sql = "SELECT community_players.player_id\n"
. "from community_players\n"
. "where community_players.community_id in ".$in_statement."";
So just the middle-part is new, where the $in_statement gets build. And in your SQL you have to change the "=" to "IN". You can generate the IN-part shorter, but this way you can easier see how it's done, so you can fit it to your needs.
in your code you put ' after in which shows syntax error.
You can try
Assuming your
$communityPlayersIds has below value as array:
["2","31","31","32"]
if its not an array then convert it using json_decode()
and then try below query
$sql = "SELECT community_players.player_id\n"
. "from community_players\n"
. "where community_players.community_id IN (".join(",",$communityPlayersIds).")";

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.

PHP form sending multiple inputs as SQL queries

I'm trying to create a PHP script that takes based on which input fields are filled in out of the total, uses those fields as SQL parameter to create a SQL query. But if none of the fields are filled out, then query would just retrieve all data.
Example: if fields "Name" and "City" are entered, then the query will have to concatenate "AND name = X_INPUT AND city = Y_INPUT" at the end.
I tried to instantiate $POST variables for the sake of testing but returns nothing. I'm not even sure if this is the best way to tackle the problem but any help would be greatly appreciated!
$_POST['name']="Linda";
$_POST['city']="";
$query = "select * from customers where gender = 'F'";
if (empty($_POST)) {
$query = "select * from customers where gender ='F'";
}
else{
foreach($_POST as $key => $v) {
if (!empty($_POST[$key])) {
$cond = " and ".$key."='".$v."'";
$query = $query.$cond;
The code:
$query = $query.$cond;
every appends unnecessary query to the SQL. Get all your conditions in an array and simple concatenate them as a string. Everything should work this way.
$conditions = array();
foreach($POST as $key => $v) {
if (!empty($_POST[$key])) {
$conditions = " $key = '$v'";
}
}
if (! empty($conditions)) {
$sql .= implode(' AND ', $conditions);
}
You have a typo in your foreach loop, Use this
$_POST
instead of
$POST

creating a flexible update query with Php and pdo - problems with bindparam

I'm updating my mysql functions to use PDO. I've got the hang of most of it but struggling with an update function to update multiple fields in a records.
The function is in a class and I'm trying to keep it flexible to reuse with other tables etc.
Here's my function so far:
public function dbUpdateRecord($table, $values, $where)
{
$this->conn();
$fieldNames = array_keys($values);
var_dump($fieldNames);
$set="";
foreach ($fieldNames as $field) {
$set .= " $field = :$field,";
}
//strip last comma
$set = substr($set, 0, strlen($set) - 1);
$wherefields = array_keys($where);
$whereCondition="";
foreach ($wherefields as $field) {
$whereCondition .= " $field = :$field AND";
}
//strip last AND
$whereCondition = substr($whereCondition, 0, strlen($whereCondition) - 3);
$sql = "UPDATE $table SET $set WHERE $whereCondition";
var_dump($sql);
$stmt = $this->db->prepare($sql);
foreach ($values as $field => $value) {
$stmt->bindParam(':$field', $value);
}
foreach ($where as $field => $value) {
$stmt->bindParam(':$field', $value);
}
return $stmt->execute();
}
The problem is all the fields in the record are being updated by the id of the record which is contained in the $where variable.
$values contains an array of (fieldname=>value).
I think the problem lies around the bindparam and trying to make the fieldnames/placeholders dynamic
I thought I needed to use bindparam as best practice - is this correct or can I just go to execute()?
ANy help appreciated
You are lifting this log from the wrong end.
Your approach is potentially insecure yet inflexible at the same time.
What if you need a JOIN based update? What if you need OR in the WHERE (or IN)?
What you really need is a conventional query where only SET statement values have to be generated.
So, you need a helper function to produce such a statement out of data array, returning both correctly formatted SET statement and array with variables to be bound:
$fields = array("name","email");
$sql = "UPDATE users SET ".pdoSet($fields,$values,$data)." WHERE id = :id"
// now we have $values array to be passed into query
$stmt = $dbh->prepare();
$values["id"] = $_POST['id'];
$stmt->execute($values);
With this code you'll be able to make updates for the arbitrary query. And make it safe.
As a further step you will need to start using type-hinted placeholders, to make whole code like this:
$db->query("UPDATE ?n SET ?u WHERE id IN(?a)",$table,$data,$ids);
Getting back to your problem, ONe is right - you need to use bindValue instead of bindParam (as it mentioned in the tag wiki)
I believe the problem is that you are using a foreach to bind the params to the query. Why is this a problem? Because when you bind a variable, you bind a reference to that variable, so if that variable changes, the value in the query will change too. Since you are using a foreach loop, the value for all the parameters will be the latest value that the variable $value referenced to.
You can read more about this foreach behavior here and here. So basically, you have 2 options:
Use a reference to the actual value, instead of using a reference to $value (which can change its value in the next iteration)
Use an auxiliar variable that references another memory position that won't change during the loop
I came here because I was having the same problems, and YCS's solution was what I needed. For anyone else in this situation, here's the helper function I ended up using:
function commit_table($record_id, $changed_values)
{
$db = open_database();
$query = 'UPDATE table SET ';
$query_arguments = array();
$is_first = TRUE;
foreach(array_keys($changed_values) as $key)
{
if($is_first)
{
$is_first = FALSE;
}
else
{
$query .= ', ';
}
$value_var = ':' . $key;
$query .= $key;
$query .= ' = ';
$query .= $value_var;
$query_arguments[$value_var] = $changed_values[$key];
}
$query .= ' WHERE record_id = :record_id';
$query_arguments[':record_id'] = $record_id;
$stmt = $db->prepare($query);
$stmt->execute($query_arguments);
close_database($db);
}

Build SQL Select a better way ? (Oracle)

i have the following code part in one of my classes:
$l = new Location();
$result = $l->getLocIdsbyCity($city); // returns csv
$ids = explode(',', $result);
$where = 'LOC_ID = ' . $ids[0];
unset($ids[0]);
foreach ($ids as $id) {
$where .= ' OR LOC_ID = ' . $id;
}
$select->where($where);
Is there an more "elegant" way to build the select stmt? I need all records with one of the provided ids..
Assuming your csv is injection safe (contains trusted values and no user-provided input):
$l = new Location();
$result = $l->getLocIdsbyCity($city); // returns csv
$where = "LOC_ID IN ($result)";
$select->where($where);
If it's not, you should explode it, mysql_real_escape_string each value and implode back.
You can use the in operator to form a condition like:
where LOC_ID in (1,2,3,4,5)
If you are sure that $result can't contain anything harmful, you should be able to use it directly without having to split it and loop.

Categories