Mysql query generation? - php

I have several different filters and search functions that I need to generate mysql queries for. I am wondering if there is a class or library I can use.
For example if they input there email with a date I need to add WHERE email='email' AND date`='date' in the middle of the sql query. But if they also enter a city then I need to add that.
I was thinking put everything I need to search by in an array and then imploding it by AND ? Does anyone have any better suggestion?

I use Zend_Db for that sort of thing. Quick example, using Zend_Db_Select:
$select = $db->select()->from("users");
if($email) {
$select->where('email = ?', $email);
}
if($date) {
$select->where('date = ?', $date);
}
// etc
// show query
// will output something like SELECT * from `users` WHERE email = 'email' AND date = 'date'
print_r($select->__toString());
// execute
$results = $db->fetchAll($select);
print_r($results);

I use array solution very often as it is most flexible solution for query conditionals
$a[] = "email = 'email'";
$a[] = "firstname LIKE '%firstname%'";
$a[] = "date BETWEEN 'date_a' AND 'date_d'";
$a[] = "id > 123";
$query = ... " WHERE " implode(' AND ', $a);

I'd go for adding all data that is given into an array like this:
$args = array(
'email' => 'test#test.com',
'date' => '2011-01-05',
'city' => 'MyTown'
);
Then just foreach through it adding the key and value to the search
$SQL = "WHERE ";
foreach($args as $key => $val) {
$SQL .= $key."='".$val."'";
//And add the AND or OR where needed
}

Common approach is to create an array that will contain different query parts and just add elements to them, depending on what you need to filter. For example:
<?php
$sql_parts = array(
'select' => array(),
'from' => array(),
'where' => array()
);
if ($filter_by_name != ''){
$sql_parts['select'][] = 'u.*';
$sql_parts['from'][] = 'users AS u';
$sql_parts['where'][] = "u.name = '".mysql_real_escape_string($filter_by_name)."'";
}
if ($filter_by_surname != ''){
$sql_parts['select'][] = 'u.*';
$sql_parts['from'][] = 'users AS u';
$sql_parts['where'][] = "u.surname = '".mysql_real_escape_string($filter_by_surname)."'";
}
//filter by data from another table
if ($filter_by_city_name != ''){
$sql_parts['select'][] = 'u.*, c.*';
$sql_parts['from'][] = 'cities AS c';
$sql_parts['from'][] = 'users AS u';
$sql_parts['where'][] = "c.cityname = '".mysql_real_escape_string($filter_by_city_name)."'";
$sql_parts['where'][] = "c.id = u.cityid";
}
$sql_parts['select'] = array_unique($sql_parts['select']);
$sql_parts['from'] = array_unique($sql_parts['from']);
$sql_parts['where'] = array_unique($sql_parts['where']);
$sql_query = "SELECT ".implode(", ", $sql_parts['select']).
"FROM ".implode(", ", $sql_parts['from']).
"WHERE ".implode(" AND ", $sql_parts['where']);
?>

Related

php update to mysql with array not updating

I have a function that should be updating a row, no errors what so ever in the logs. From what I see it should be working. I took the function from a update user function and tried to mimic it for the new feature.
Here is the data array posting to it.
$data = array('id' => $vid, 'name' => $vname, 'logo' => $vlogo, 'info' => $vinfo, 'site' => $vsite, 'est' => $vest);
The post works, I am doing a dump on the updatecompany page. So they do get set. I think it may be with the function. Any insight would be wonderful!
public static function updateCompany($toUpdate = array(), $company = null){
self::construct();
if( is_array($toUpdate) && !isset($toUpdate['id']) ){
if($company == null){
echo "No company ID set!";
}
$columns = "";
foreach($toUpdate as $k => $v){
$columns .= "`$k` = :$k, ";
}
$sql = self::$dbh->prepare("UPDATE companys SET {$columns} WHERE `id` = :id");
$sql->bindValue(":id", $company);
foreach($toUpdate as $key => $value){
$value = htmlspecialchars($value);
$sql->bindValue(":$key", $value);
}
$sql->execute();
}else{
return false;
}
}
$vid = $_POST["idnum"];
$vname = $_POST["name"];
$vlogo = $_POST["logo"];
$vinfo = $_POST["info"];
$vsite = $_POST["site"];
$vest = $_POST["est"];
I would maybe try using the bind array into your execute() method since you are just binding the values (I assume this is PDO). Another feature is to use an array to assemble the column portions and implode at the time of use.
public static function updateCompany($toUpdate = array(), $company = null)
{
# Also this may supposed to be: self::__construct(); ?? Notice the "__" before "construct"
self::construct();
if(is_array($toUpdate) && !isset($toUpdate['id'])) {
if(empty($company)){
# Throw exception, catch it in a parent wrapper
throw new \Exception("No company ID set!");
# Stop, no sense in continuing if an important part is missing
return;
}
foreach($toUpdate as $k => $v){
$bKey = ":{$k}";
# I would create a bind array here
$bind[$bKey] = $value;
# I generally save to an array here to implode later
$columns[] = "`{$k}` = {$bKey}";
}
# Add the id here
$bind[":id"] = $company;
# I would use a try here for troubleshooting PDO errors
try {
# Create sql with imploded columns
$sql = self::$dbh->prepare("UPDATE companys SET ".implode(",",$columns)." WHERE `id` = :id");
# Throw the bind array into the execute here
$sql->execute($bind);
}
catch(\PDOException $e) {
# I would only die here to see if there are any errors for troubleshooting purposes
die($e->getMessage());
}
} else {
return false;
}
}
Your update SQL could not work because you have comma in update value set.
See, you attached comma without any consideration:
$columns = "";
foreach($toUpdate as $k => $v){
$columns .= "`$k` = :$k, ";
}
Then the final SQL will look something like this:
UPDATE companys SET `name`=:name, `logo`=:logo, WHERE `id`=:id
Do you notice the comma just before WHERE? it should not be there!
So you should update the code like following:
$columns = "";
foreach($toUpdate as $k => $v){
if ($columns != "") $columns .= ",";
$columns .= "`$k` = :$k ";
}
This should be working.
or to no need to be aware of last comma try this:
$columns = array();
foreach($toUpdate as $k => $v){
$columns[] = "`$k` = :$k";
}
$sql = self::$dbh->prepare("UPDATE `companys` SET ".implode(',', $columns)." WHERE `id` = :id");

PHP update statement with arrays

Hi so I have an insert statement which works well, but need to create a separate update function which uses array keys and array values, which would be quite like the insert function but updates.
I have this for my insert
$sql = "INSERT INTO $tablename (".implode(",", array_keys($DATA).")" . " DATA ('".implode("','",array_values($DATA))."')";
connect()->query($sql);
This is what I have for my update so far but am stuck with it,
<?php
function updatethis (array $id, array $values, $tablename)
{
$sql = "UPDATE $tablename SET (".implode(",", array_keys($DATA)).")" . " DATA ('".implode("','",array_values($DATA))."')";
dbconnect()->query($sql);
}
?>
Therefore I would like help on the update feature please .
So I am getting an error with the UPDATE syntax
This is the part i am struggling with, i cna give further explanation, but i must have put in the wrong syntax to update the database after i click edit on the index page it calls the function just the syntax is incorrect.
also its php to mySQL
index page for PHP updatee fucntion
{
$values = array();
$idValues = array($idColumn => $id);
foreach($_POST as $key => $value)
{
if(!empty($value) && ($value != "Submit"))
{
$values[$key] = $value;
}
}
$result = update($idValues, $values, $tableName);
}
Edit: Error I am getting
edit has not been successfull from below
if(isset($_POST['Submit']))
{
if($result>0)
{
echo 'Edit has been successful. Return to index page';
}
else
{
echo 'Edit has not been successful.';
}
}
My code
function updateAll(array $id, array $values, $tablename)
{
$sIDColumn = key($id);
$sIDValue = current($id);
$arrayValues = $values;
array_walk($values, function(&$value, $key){
$value = "{$key} = '{$value}'";
});
$sUpdate = implode(", ", array_values($values));
$sql = "UPDATE {$tablename} SET {$sUpdate} WHERE {$sIDColumn} = '{$sIDValue}'";
connect()->query($sql);
}
My aim: takes the input of the unique identifier of the row to be edited as an array of 1 then the value plus the name of the column representing the primary key, an array containing the values indexed by the column names as well as a string representing the table name useing array_keys and array_vaules like th insert but to update
You cannot UPDATE in the same way of INSERT. It should be like this :
$valueSets = array();
foreach($values as $key => $value) {
$valueSets[] = $key . " = '" . $value . "'";
}
$conditionSets = array();
foreach($id as $key => $value) {
$conditionSets[] = $key . " = '" . $value . "'";
}
$sql = "UPDATE $tablename SET ". join(",",$valueSets) . " WHERE " . join(" AND ", $conditionSets);
See details here http://dev.mysql.com/doc/refman/5.7/en/update.html
I believe the pattern you are using is incorrect?
UPDATE table SET (rows) DATA ('values');
I think updates look more like this:
UPDATE table SET row1 = 'value1', row2 = 'value2';
In which case, this may be closer to what you are looking for.
function updatethis(array $id, array $values, $tablename)
{
$sIDColumn = key($id);
$sIDValue = current($id);
$arrayValues = $values;
array_walk($values, function(&$value, $key){
$value = "{$key} = '{$value}'";
});
$sUpdate = implode(", ", array_values($values));
$sql = "UPDATE {$tablename} SET {$sUpdate} WHERE {$sIDColumn} = '{$sIDValue}'";
dbconnect()->query($sql);
}
Using it, I get this query:
$testArray = array(
"id" => 19,
"username" => "test"
);
updatethis(array("id" => 9), $testArray, "users");
UPDATE users SET id = '19', username = 'test' WHERE id = '9'
I hope this at least helps but when it comes to databases, I only know MySQL and it is possible you are using another language.
I think you can try something like this :
$champs : Array of fields to update
$valeurs : Array of value to update fields
$conditions : Array of conditions
protected function modify($table,$champs,$valeurs,$conditions){
$Requete = "UPDATE ".$table." SET ";
$nbChamps = count($champs);
$nbValeurs = count($valeurs);
if($nbChamps == $nbValeurs){
for($i = 0; $i < $nbChamps ; $i++){
if($i < ($nbChamps - 1)){
if(is_numeric($valeurs[$i]))
$Requete = $Requete.$champs[$i]." = ".$valeurs[$i].",";
else
$Requete = $Requete.$champs[$i]." = '".$valeurs[$i]."',";
}
else
if(is_numeric($valeurs[$i]))
$Requete = $Requete.$champs[$i]." = ".$valeurs[$i]." ";
else
$Requete = $Requete.$champs[$i]." = '".$valeurs[$i]."' ";
}
$Requete = $Requete.$this->genereConditions($conditions);
$this->db->query($Requete);
}
else
throw new Exception("Le nombre de champs n'est pas identique au nombre de valeurs", 1);
}
private function genereConditions($conditions){
$condition = "WHERE ";
for($i = 0 ; $i < count($conditions); $i++){
if($i < (count($conditions)) - 1)
$condition = $condition.$conditions[$i]." AND ";
else
$condition = $condition.$conditions[$i];
}
return $condition;
}

php arrray groups by multiple sets

i have data in set of groups
each group contains 3 Values As name , mobile , message.
How to store these multiple values in array and get echo of separate group .??
<?php
$full_name = array( );
$full_name["name"] = "john1";
$full_name["mobile"] = "923456812536";
$full_name["message"] = "message1";
$full_name["name"] = "john2";
$full_name["mobile"] = "565656565656";
$full_name["message"] = "message2";
$full_name["name"] = "john3";
$full_name["mobile"] = "444442222222222";
$full_name["message"] = "message3";
$full_name["name"] = "john4";
$full_name["mobile"] = "2222";
$full_name["message"] = "2222222222";
echo $full_name["name"]."</br>".
$full_name["mobile"]."</br>".
$full_name["message"]."</br></br>"
?>
Do your inserts into the array like:
$full_name[] = array(
"name" => "john1",
"mobile" => "923456812536",
"message" => "message1",
);
etc
to give yourself a multi-dimensional array
then loop using
foreach($full_name as $name) {
echo $name['name'], ' ', $name['mobile'], ' ', $name['message'], PHP_EOL;
}
You could use multi dimensional arrays like this
$full_name["name"][0] = "john1";
$full_name["mobile"][0] = "923456812536";
$full_name["message"][0] = "message1";
$full_name["name"][1] = "john2";
$full_name["mobile"][1] = "565656565656";
$full_name["message"][1] = "message2";
And echo a group like this
echo implode(", ", $full_name["name"]);
However, you need to make sure that ["name"][x] corresponds with ["mobile"][x] as these sub arrays are independent of each other. If you use Mark Baker's answer, you know that [x]["name"] belongs to the same person as [x]["mobile"]
This should work for you: With the [] it's going to insert the data into the next field of the array
<?php
$full_name = array( );
$full_name["name"][] = "john1";
$full_name["mobile"][] = "923456812536";
$full_name["message"][] = "message1";
$full_name["name"][] = "john2";
$full_name["mobile"][] = "565656565656";
$full_name["message"][] = "message2";
$full_name["name"][] = "john3";
$full_name["mobile"][] = "444442222222222";
$full_name["message"][] = "message3";
$full_name["name"][] = "john4";
$full_name["mobile"][] = "2222";
$full_name["message"][] = "2222222222";
print_r($full_name["name"]);
echo "</br>";
print_r($full_name["mobile"]);
echo "</br>";
print_r($full_name["message"]);
?>

mysqli : bind param where search parameters are conditional

I would need a good structure for building queries where search parameters are conditional using mysqli prepared statement. $query -> bind_param('sss',$date,$time,$place);
I dont know how to apply 'sss' and '$date,$time,$place' parameters in order later. Can you pass them as variable?
Old MySQL way:
<?php
// date is obligatory
$date = mysql_real_escape_string($_GET["date"]);
$query="SELECT * FROM dbase WHERE date='$date'";
// time field is custom
if(!empty($_GET["time"])) {
$time= mysql_real_escape_string($_GET["time"]);
$buildQuery[] = "time='$time'";
}
// place field is also custom
if(!empty($_GET["place"])) {
$place= mysql_real_escape_string($_GET["place"]);
$buildQuery[] = "place='$place'";
}
// building query
if(!empty($build)) {
$query .= ' AND '.implode(' AND ',$build).' ORDER BY date';
}
?>
This is a good case where PDO is far easier than MySQLi:
$query="SELECT * FROM dbase";
$terms = array("date" => $date);
$params = array();
// time field is custom
if(isset($_GET["time"])) {
$terms["sType"] = $time;
}
// place field is also custom
if(isset($_GET["place"])) {
$terms["place"] = $place;
}
// building query
if(!empty($terms)) {
$query .= "WHERE " . implode(" AND ",
array_map(function($term) { return "$term = ?"; }, array_keys($terms));
$params = array_values($terms);
}
$query .= "ORDER BY date";
$stmt = $pdo->pepare($query);
$stmt->execute($params);
PS: I have to question whether you meant to have your sType column contain both time and place. Seems like you're breaking relational database best practices. Unless it's just a typo.
untested, but you should be able to do something like this
$types = array();
$vals = array();
if(isset($_GET["time"])) {
$types[] = 's';
$vals[] = $_GET["time"];
$buildQuery[] = "sType = ?";
}
//...etc...
$args = array_merge(array(join($types)), $vals);
$callable = array($mysqli, 'bind_param');
call_user_func_array($callable, $args));
http://php.net/manual/en/language.types.callable.php
but, there's another approach. Just use logic in the sql:
select *
from tbl
where (date = ? or ? = '')
and (time = ? or ? = '')
and (place = ? or ? = '')
The above assumes you'll bind each arg twice, and bind them as strings, but binding an empty string if the query string param wasnt set... You could bind them as null if needed too via something like (date = ? or ? is null).
$mysqli->bind_param('ssssss', $date,$date, $time,$time, $place,$place);
ps, the mysql optimizer will make short work of that simple logic.
Based on goat's reply, here's a full and tested answer with an UPDATE statement where the fields to be updated are conditional. I have used a very simple table structure with 3 fields: ID (auto increment), Varchar1 (varchar255) and Varchar2 (varchar255). In this script, I want to update the two varchar fields for the first three records. Based on this script, it's very easy to conditionally add or remove fields to be updated.
$mysqli = new mysqli(...);
$types = array();
$vals = array();
$query = array();
// varchar1
$types[] = 's';
$vals[] = 'foo1';
$query[] = "varchar1=?";
// varchar2
$types[] = 's';
$vals[] = 'foo2';
$query[] = "varchar2=?";
$sql = "UPDATE test SET ".implode(",", $query)." WHERE id IN (1,2,3)";
$stmt = $mysqli->prepare($sql);
$args = array_merge(array(implode($types)), $vals);
$callable = array($stmt, 'bind_param');
call_user_func_array($callable, refValues($args));
$stmt->execute();
function refValues($arr) {
if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}

Searching Array in PHP and return results

Can't find quite the right answer so hope someone can help. Basically want to create an array and then return the results from a search e.g.
$tsql = "SELECT date, staffid, ID,status, eventid, auditid from maincalendar";
$params = array();
$options = array( "Scrollable" => SQLSRV_CURSOR_KEYSET );
$stmt = sqlsrv_query( $conn, $tsql , $params, $options);
$calarray=array();
while($row = sqlsrv_fetch_array($stmt)) {
$rowresult = array();
$rowresult["status"] = $row['status'];
$rowresult["eventid"] = $row['eventid'];
$rowresult["caldate"] = $row['date'];
$rowresult["staffid"] = $row['staffid'];
$rowresult["ID"] = $row['ID'];
$rowresult["auditid"] = $row['auditid'];
$calarray[] = $rowresult;
}
I would then like to search for values matching 'caldate' and 'staffid' and return the associated entry in $calarray
I suggest the following,
Fetch all data needed for the current month you are showing, using col BETWEEN x AND y
Add them to a array in PHP, with staffid and caldate as key
Something like so;
$calarray[$row['staffid'] . '-' . $row['date']][] = $row;
Not sure if a single staffid/date combination can have one or more events per day, if not you can remove the []
To check if we have information for a specific staffid/date combination, use isset
if (isset($calarray[$staffid . '-' . $mydate]) { ... }
Add indexes to the fields you're going to query, and then move the search to the sql query. You can also make simple filtering inside the loop. So you'll be populating several arrays instead of one, based on the search you need.
try this:
$matches = array();
$caldate = //your desired date;
$staffid = //your desired id;
foreach($calarray as $k => $v){
if(in_array($caldate, $v['caldate']) && in_array($staffid, $v['staffid'])){
$matches[] = $calarray[$k];
}
}
$matches should be and array with all the results you wanted.
also:
while($row = sqlsrv_fetch_array($stmt)) {
$rowresult = array();
$rowresult["status"] = $row['status'];
$rowresult["eventid"] = $row['eventid'];
$rowresult["caldate"] = $row['date'];
$rowresult["staffid"] = $row['staffid'];
$rowresult["ID"] = $row['ID'];
$rowresult["auditid"] = $row['auditid'];
$calarray[] = $rowresult;
}
can be shortened into:
while($row = sqlsrv_fetch_array($stmt)) {
$calarray[] = $row;
}
Maybe this code snipplet solves your problem.
I am not a PHP programmer, so no warrenty.
function searchInArray($array, $keyword) {
for($i=0;$i<array.length();$i++) {
if(stristr($array[$i], $keyword) === FALSE) {
return "Found ".$keyword." in array[".$i."]";
}
}
}

Categories