i have below query and it work fine.
but if the $where were array it will be fail,what's the solution?
public function update($tbl_name, $data = NULL, $where = NULL)
{
if ($data) {
$data_key = array_keys($data);
$where_key = array_keys($where);
$query = "UPDATE " . $data['db_table'] . " SET ";
foreach ($data_key as $key) {
$query .= "`" . $key . "` = '" . $data[$key] . "' ";
}
//todo fix that for multi where
$query.=" WHERE `".$where."`=".$where[''];
return $this->query($query);
}
return false;
}
You do realize that this is a rather dangerous thing that you are doing? Chances of your database getting nuked by someone entering something unexpected is way too high. As for the where clause, you can get help from is_array
if(is_array($criteria)) {
$query.=" WHERE `".$where." IN (" . join(",", $criteria) . ")";
}
else {
$query.=" WHERE `".$where." = '{$criteria}'";
}
The other issue here is that never ending string concatenation of this nature leads to very hard to trace bugs.
Related
I'm coding my web app in PHP and when I run my script, I've got this error :
array to string conversion
Here is the script where the error fires.
public function insert($table, array $columns, array $values) {
$sql = "INSERT INTO " . $table .
" (" . implode(',' , $columns) . " )
VALUES (" . implode(',',
$values) . ")";
$this->request($sql);
}
Here is the request function :
public function request($sql, $param = null) {
if ($param == null) {
$query = Database::getInstance()->getDb()->query($sql);
}
else {
$query = Database::getInstance()->getDb()->prepare($sql);
$query->execute(array($param));
}
return $query;
}
N.B : I'm using my own MVC framework.
So, any advise or help would be apreciated ?
Regards
YT
I advice to modify your class methods for using parameterized queries:
class Test {
public function insert($table, array $columns, array $values) {
$sql = "INSERT INTO " . $table . " (" . implode(',' , $columns) . ")
VALUES (?" . str_repeat(",?", count($columns) - 1) . ");";
echo $sql;
$this->request($sql, $values);
}
public function request($sql, $param = null) {
if ($param == null) {
$query = Database::getInstance()->getDb()->query($sql);
}
else {
$query = Database::getInstance()->getDb()->prepare($sql);
$query->execute($param);
}
return $query;
}
};
$test = new Test();
$test->insert('tbl', ['id', 'name'], [1, 'first row']);
Online PHP test
So I am trying to make an undetermined amount of bindParam calls within a foreach, but for some reason it fails. I know the $sql variable is working fine, but I am pretty sure it is failing at the bindParam. Is there any reason for this?
$sql = "INSERT INTO " . $row1["rand"] . " (" . $areas . ") VALUES (" . $vals . ")";
echo $sql;
$entry2 = $conn->prepare("'".$sql."'");
//echo "swag";
foreach($splitHeader as $element){
if(strlen($element)>0) {
$thisVal = "':" . $element . "'";
$entry2->bindParam($thisVal,$_POST[$element]);
}
}
$entry2->execute();
The number of parameters that you define in the query must match the number of parameters that you bind.
You would need to loop twice trough your data : once to dynamically construct a sql statement (that you can then prepare), and then a second time to bind the parameters, before finally calling execute.
Here is an adaptation of your code that demonstrates the principle :
$cols = "";
$vals = "";
foreach( $splitHeader as $element ) {
if( strlen($element) > 0 ) {
if ( strlen($cols) > 0 ) {
$cols .= ", ";
$vals .= ", ";
}
$cols .= $element;
$vals .= "?";
}
}
$sql = "INSERT INTO " . $row1["rand"] . " (". $cols . ") VALUES(". $vals . ")";
echo $sql;
$sth = $conn->prepare($sql);
$i = 1;
foreach($splitHeader as $element){
if( strlen($element) > 0 ) {
$sth->bindParam( $i, $_POST[$element] );
$i++;
}
}
$sth->execute();
I have the following code but i am not sure how to check if insert is success. execute returns resource id. I would like to check if success and return all errors on fail.
public function persist()
{
$update = FALSE;
if(!is_array($this->tablePrimaryKey)) {
if(!empty($this->fieldVals[$this->tablePrimaryKey])) {
$update = true;
}
}
if ($update) {
$sql = "UPDATE " . $this->tableName . " SET ";
$binds = [];
foreach ($this->fieldVals as $key=>$val) {
if ($key != $this->tablePrimaryKey) {
if(in_array($key, $this->DATE_IDS)) {
$sql .= '"' . strtoupper($key) . '" = sysdate,';
} else {
$bind = 't_' . $key;
$binds[$bind] = $val;
$sql .= '"' . strtoupper($key) . '" = :' . $bind . ',';
}
}
}
$sql = substr($sql,0,-1);
$sql .= " WHERE " . $this->tablePrimaryKey . " = '" . $this->fieldVals[$this->tablePrimaryKey] ."'";
} else {
$binds = $fields = $date_fields = [];
if(!empty($this->tablePrimaryKey) && !is_array($this->tablePrimaryKey)) {
$this->fieldVals[$this->tablePrimaryKey] = $this->generateNewPrimaryKey();
}
foreach ($this->fieldVals as $key=>$val) {
$bind = ':t_' . $key;
if (in_array($key, $this->DATE_IDS)) {
$date_fields[] = strtoupper($key);
} else {
$binds[$bind] = $val;
$fields[] = strtoupper($key);
}
}
$sql = 'INSERT INTO ' . $this->tableName . '("' . implode('","', $fields);
if(count($date_fields) >0) {
$sql .= '","';
$sql .= implode('","', $date_fields);
}
$sql.='") VALUES (' . implode(',', array_keys($binds));
if(count($date_fields) >0) {
$cnt=0;
foreach($date_fields as $date) {
$cnt++;
if(preg_match('/NULL/i', $this->fieldVals[strtolower($date)], $result)) {
$sql .= ",NULL";
} elseif(isset($this->fieldVals[strtolower($date)])) {
$sql .= ",TO_DATE('" . (new DateTime($this->fieldVals[strtolower($date)]))->format("Y-M-d H:i:s") . "', 'yyyy/mm/dd hh24:mi:ss')";
} else {
$sql .= ",sysdate";
}
}
}
$sql .= ')';
}
$this->oiDb->parse($sql, $binds);
return $this->oiDb->execute();
}
I run $result = $oiRequests->hydrate($reportingRequest)->persist();. $reportingRequest is key,value pair of columns/values. $result contains resource id. $oiRequests is my model.
I have tried
$num_rows = oci_fetch_assoc ($result);
print_r($num_rows);
returns
Warning: oci_fetch_assoc(): ORA-24374: define not done before fetch or execute and fetch in /var/SP/oiadm/docroot/dev/uddins/requestportal/requestportal_ajax.php on line 65
Most of the OCI functions return false on error. This means you can do a simple check on the return value and, if it's false, call oci_error().
For the specific case of checking if an INSERT statement worked you can reference the example code for oci_commit(). The relevant part of that example is duplicated here:
// The OCI_NO_AUTO_COMMIT flag tells Oracle not to commit the INSERT immediately
// Use OCI_DEFAULT as the flag for PHP <= 5.3.1. The two flags are equivalent
$r = oci_execute($stid, OCI_NO_AUTO_COMMIT);
if (!$r) {
$e = oci_error($stid);
trigger_error(htmlentities($e['message']), E_USER_ERROR);
}
I am currently going through a nettuts.com tutorial on building a twitter clone and there they have a function for deleting rows from a database and they are using the query method but i tried converting the function to a prepared statement.However I get the Invalid parameter number: parameter was not defined error.Here is the code for the function
public function delete($table, $arr){
$query = "DELETE FROM " . $table;
$pref = "WHERE ";
foreach ($arr as $key => $value) {
$query .= $pref. $key . " = " . ":" . $key;
$pref = "AND ";
}
$query .= ";";
$result = $this->db->prepare($query);
$result->execute($arr);
}
$connect = new Model();
$connect->delete("ribbits", array("user_id" => 2,
"ribbit" => "trial ribbit"
));
can someone please tell me what I am doing wrong?Thank you!
When you pass your array to ->execute(), the keys need to have the : character before them (just like they appear in the SQL query).
So, in your delete function, build the SQL query like this:
public function delete($table, $arr){
$keys = array();
$values = array();
foreach($arr as $key => $value){
$keys[] = $key . " = :" . $key;
$values[":".$key] = $value;
}
$query = "DELETE FROM " . $table . " WHERE " . implode(" AND ", $keys);
$result = $this->db->prepare($query);
$result->execute($values);
}
Language: PHP and MySQL
I have some rows in a database that have a column with a value of NULL. I have a function that builds the query when it receive a $params array. Here's the relevant piece of code in that function (to build the WHERE clause):
if (isset($params['where'])) {
$query .= "WHERE ";
$count = count($params['where']);
foreach ($params['where'] as $key => $value) {
$count--;
if ($count) {
$query .= "`$key` ".$value['sign']." '".$value['text']."' AND ";
} else {
$query .= "`$key` ".$value['sign']." '".$value['text']."' ";
}
}
}
The problem is that when I set $value['text'] to null, here's the result:
SELECT * FROM `db_profiles` WHERE `committed` IS '' LIMIT 100
If I set it to $value['text'] = 'NULL', then I get the following:
SELECT * FROM `db_profiles` WHERE `committed` IS 'NULL' LIMIT 100
Which of course produces nothing. Any ideas?
ANSWER
if (isset($params['where'])) {
$where_segment = array ();
foreach ($params['where'] as $key => $value) {
if (is_null($value['text'])) {
$where_segment[] = "`".$key."`"." IS NULL";
} else {
$where_segment[] = "`$key` ".$value['sign']." '".$value['text']."' ";
}
}
$query .= " WHERE ".implode('AND', $where_segment);
}
$string_array = array();
foreach($params['where'] as $field => $value) {
if(is_null($value)) {
$string_array[] = "`$field` IS NULL";
}
else {
$string_array[] = "`$field`='$value'";
}
}
$where_string = "WHERE ".implode(" AND ", $string_array);
$sql = "SELECT * FROM `db_profiles` $where_string";
Notice that if the $value is NULL I omit the '' marks around the NULL phrase.
Please use this query.
SELECT * FROM db_profiles WHERE committed IS NULL LIMIT 100.
Remove the single quotes.
When populating the values to the query, you'll need an explicit check for something like:
if(is_null($value)) {
$query . ' WHERE something IS NULL';
} else {
$query . ' WHERE something \'' . $value . '\'';
}
Note that when you are new to MySQL and PHP you should start to use prepared statements as soon as possible. They are most secure against SQL injection vulnerabilities and easy to use. You can start here to learn to use them.
this should help you without single quotes
SELECT * FROM `db_profiles` WHERE `committed` IS NULL LIMIT 100
you could set your variable like that to null
$value['text'] = NULL;
and then in your query
SELECT * FROM `db_profiles` WHERE `committed` IS $value['text'] LIMIT 100