Hello I'm trying to make a code to UPDATE or EDIT the survey answers and comments per answer but when I execute the function submiting the form, it did not save any value into the database. What can I do to fix it?
I'm new in PDO.
Thanks in advance.
Database Structure
"Questions" (idquestion, question)
"Surveys" (idsurvey, idquestion, answers, comments_per_question, survey_number)
Update function
public function ModifySurveyMulti($answer = array())
{
if(!empty($answer)) {
foreach($answer as $questi => $value ) {
$this->MyDB->Write("UPDATE survey SET(
`idquestion` = '".$questi."',
`answers` = '".$value[0]."',
`comments_per_answer`= '".$_POST["comment"][$questi]."')");
}
}
}
modify_surveyform.php
<th><?php echo $row["questions"];?></th>
<td>
<input type = "text"
name = "answer[<?php echo $row['idquestion'];?>][]"
value = "<?php echo $row["answers"];?>">
</input>
</td>
<td>
<Textarea type = "text"
name = "comment[<?php echo $row['idquestion'];?>]"
cols = "50" rows = "3"/> <?php echo $row["comment"];?
</textarea>
</td>
</tr><?php } ?>
Mydbconnect.php
<?php
// I'm adding my PDO database because yours is deprecated
class DBConnect
{
public $con;
// Create a default database element
public function __construct($host = '',$db = '',$user = '',$pass = '')
{
try {
$this->con = new PDO("mysql:host=$host;
dbname=$db",$user,
$pass, array(
PDO::ATTR_ERRMODE
=> PDO::ERRMODE_WARNING
)
);
}
catch (Exception $e) {
return 0;
}
}
// Simple fetch and return method
public function Fetch($_sql)
{
$query = $this->con->prepare($_sql);
$query->execute();
if($query->rowCount() > 0) {
while($array = $query->fetch(PDO::FETCH_ASSOC)) {
$rows[] = $array;
}
}
return (isset($rows) && $rows !== 0 && !empty($rows))? $rows: 0;
}
// Simple write to db method
public function Write($_sql)
{
$query = $this->con->prepare($_sql);
$query->execute();
}
}?>
Few things you need to do:
First of all ditch this code, it is useless and expose you to sql
injection
Use PDO directly with prepared statement
The query you need is :
UPDATE survey SET(`answers`= ?,`comments_per_answer`= ?) WHERE idquestion = ?
You will need to adjust your class to only create the connection
class DBConnect
{
public $con;
public function __construct($host = '',$db = '',$user = '',$pass = '')
{
try {
$this->con = new PDO(
"mysql:host=$host;dbname=$db",
$user,$pass,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING)
);
}
catch (Exception $e) {
die($e);
}
}
public function get_connection(){
return $this->con;
}
}
So that you can create it like this:
$db = new DBConnect(/*pass arguments here*/);
$this->MyDB = $db->get_connection();
Modify and use it in your function:
public function ModifySurveyMulti($answer = array(), $comments)
{
$sql = 'UPDATE survey SET(`answers`= ?,`comments_per_answer`= ?)
WHERE idquestion = ?';
$stmt->prepare($sql);
foreach($answer as $questi => $value ) {
$stmt->execute(array($value, $comments[$questi],$questi));
$count = $stmt->rowCount();
echo $count > 0 ? $questi.' updated' : $questi.' did not update';
}
}
Call the function :
if(isset($_POST['answer'], $_POST['comments'])){
$answers = $_POST['answer'];
$comments = $_POST['comments'];
ModifySurveyMulti($answers, $comments);
}
Related
I have been adapting an older abstraction layer to use PDO but I am running into user x has more than 'max_user_connections' active connections SQLSTATE[HY000] [1203] errors when looping through large sets. I have been reading on http://php.net/manual/en/pdo.connections.php but all of my attempts to unset the $dbh from within the loops result in errors from having ended the connection.
Base class looks like
class DB {
public $pdo;
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
public function __construct()
{
$this->connect();
}
private function connect()
{
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try {
$this->pdo = new PDO("mysql:host=$this->host;dbname=$this->dbname;charset=utf8;", $this->user, $this->pass, $options);
} catch(PDOException $e) {
echo $e->getMessage();
}
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
public function __destruct()
{
$this->connection = null;
$this->pdo = null;
unset($this->pdo);
}
// CRUD methods follow including
function retrieve($where, $groupBy='', $order_by='') {
$query = "SELECT * FROM `$this->table` $where $groupBy $order_by";
$q = $this->pdo->prepare($query);
$q->execute();
$result = $q->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,get_class($this));
// was $result = $q->fetchAll(PDO::FETCH_CLASS,get_class($this));
$this->query_log($query);
$q = null;
if ($result == 'NULL') {
return false;
} else {
return $result;
}
} // retrieve()
And an example that has the errors would be
if (in_array($_GET['type'], $types)) {
$type = $_GET['type'];
$rsObj = new ReservedSlug;
if ($type == 'artist') {
$obj = new CalendarArtist;
$slugfield = 'urlSlug';
$namefield = 'name';
} else if ($type == 'event') {
$obj = new CalendarEvent;
$slugfield = 'urlSlug';
$namefield = 'name';
} else if ($type == 'location') {
$obj = new Location;
$slugfield = 'UrlSlug';
$namefield = 'LocationName1';
}
$needslug = $obj->retrieve("TRIM(`$namefield`) != '' AND (`$slugfield` = '' OR `$slugfield` IS NULL) LIMIT 0,400");
if ($needslug) {
foreach ($needslug as $ns) {
$testslug = slugify($ns->$namefield);
list($reserved) = $rsObj->retrieve("`slug` = '$testslug' AND `type` = '$type'");
if (!$reserved) {
list($test) = $obj->retrieve("`$slugfield` = '$testslug'");
if ($test) {
for ($i = 2; $i < 26; $i++) {
list($test) = $obj->retrieve("`$slugfield` = '$testslug-$i'");
if (!$test) {
$slug = $testslug . '-' . $i;
}
}
} else { // not found in table
$slug = $testslug;
}
} else { // was reserved
$slug = false;
}
echo $ns->$namefield . " gets $slug<p>";
} // foreach needslug
} // if needslug
} // type found in array
So I need to understand how to not create new connections when an active connection is available and how to properly __destruct() these child objects. Where am I going wrong?
I make users online page using PHP - OOP - PDO
include_once '../database.php';
$db = new database();
$getRows = $db->getRows('select * from visitors_online');
$gr = $db->rowCount();
$online = '';
$getRow = $db->getRow('select * from user_online');
$gr2 = $db->rowCount();
if(!empty($gr2)) {
try {
while ($getR = $getRow){
$getRow = $db->getRow('select * from users where id = ?',[$getR['session']]);
echo ',   '.$getRow['username'].'   ';
}
} catch (PDOException $e) {
die('Error :'. $e->getMessage());
}
$total = $gr + $gr2;
The problems is:
* Not show any users except Admin, also I got this :
ONLINE
admin
Notice: Undefined index: session in /Applications/MAMP/htdocs/baws/admin/online.php on line 56
,
.Users = 0 ,Member = 2 , Register = 2
Who is online list
Here is the function from Database class
// Get row by id, username, or email etc..
public function getRow($query, $para = []){
try {
$this->stmt = $this->datab->prepare($query);
$this->stmt->execute($para);
return $this->stmt->fetch();
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
}
Any Help
Thanks
I tried to simplify a bit your code as I do not know your class details and it s messy.
The problem is you are not binding stuff properly neither fetching them properly too. Also, you are preparing the second query, each time you loop inside the query 1 results , that is useless. prepare both (withyour class or not) and just bind and execute.
$stmt1 = $db->prepare('select * from user_online where id= ?');
$result1 = getRows($stmt1, "1");
$gr1 = $db->rowCount();
if (!empty($gr1)) {
$stmt2 = $db->prepare('select * from users where id = ?');
foreach ($result1 as $key1 => $h1) {
$stmt2->bindParam(1, $h1['session'], PDO::PARAM_INT);
$stmt2->execute();
$result2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
if (count($result2) !== 0) {
foreach ($result2 as $key2 => $r2) {
echo ',   ' . $r2['username'] . '   ';
}
}
}
}
function getRow($query, $para) {
$stmt1->bindParam(1, $para, PDO::PARAM_INT);
try {
$stmt1->execute($para);
$result1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
return $result1;
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
}
Please find the database class here
class database {
public $isConn;
protected $datab;
private $stmt;
public function __construct() {
$this->connect();
}
// connect to database
private function connect(){
$host = 'localhost';
$db = 'baws';
$user = 'root';
$pass = 'root';
$option = [];
$this->isConn = TRUE;
try {
$this->datab = new PDO('mysql:host='.$host.';dbname='.$db.';charset=utf8', $user, $pass, $option);
$this->datab->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->datab->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo '<h3>Not connected</h3>' . $e->getMessage();
}
}
// Disconnected from database
private function disconnect(){
$this->isConn = NULL;
$this->datab = FALSE;
}
//insert to database
public function insertRow($query, $para = []){
try {
$this->stmt = $this->datab->prepare($query);
$this->stmt->execute($para);
return TRUE;
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
}
//update row to database
public function updateRow($query, $para = []){
$this->insertRow($query, $para);
}
//Delete row from database
public function deleteRow($query, $para = []){
$this->insertRow($query, $para);
}
// Get row by id, username, or email etc..
public function getRow($query, $para = []){
try {
$this->stmt = $this->datab->prepare($query);
$this->stmt->execute($para);
return $this->stmt->fetch();
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
}
}
online.php Page
ob_start();
echo "ONLINE <br>";
include_once '../database.php';
$db = new database();
try {
$session=$_COOKIE['id'];
$time=time();
$time_check=$time-300; //SET TIME 10 Minute
$getRow = $db->getRow("SELECT * FROM user_online WHERE session = ?", [$session]);
$count =$db->rowCount($getRow);
if($count == '0'){
$insertRow = $db->insertRow("INSERT INTO user_online(session, time)VALUES(? , ?)",[$session, $time ]);
}
elseif($count != '0'){
$updateRow = $db->updateRow("UPDATE user_online SET time = ? WHERE session = ?", [$time, $session]);
}else{
$deleteRow = $db->deleteRow("DELETE FROM user_online WHERE time < ? ", [$time_check]);
}
} catch (PDOException $e) {
die('Error :'. $e->getMessage());
}
try {
$ip=$_SERVER['REMOTE_ADDR'];
$session=$ip;
$time=time();
$time_check=$time-300; //SET TIME 10 Minute
$deleteRow = $db->deleteRow("DELETE FROM visitors_online WHERE time < ? ", [$time_check]);
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
$getRows = $db->getRows('select * from visitors_online');
$gr = $db->rowCount();
$online = '';
$getRow = $db->getRow('select * from user_online');
$gr2 = $db->rowCount();
if(!empty($gr2)) {
try {
while ($getR = $getRow){
$getRow = $db->getRow('select * from users where id = ?',[$getR['session']]);
echo ',   '.$getRow['username'].'   ';
}
} catch (PDOException $e) {
die('Error :'. $e->getMessage());
}
$total = $gr + $gr2;
} //end
I created a function to grab data from my database. I want this function to be reusable just by placing correct arguments for different tables. Here's what I've done :
public function selectdata($table, $arguments='*', $where = null){
if($this->isconnect){
//check whether users put column names in the select clause
if(is_array($arguments)){
$new_args = implode(',', $arguments);
$sql = 'SELECT '.$new_args.' FROM '.$table;
} else {
$sql = 'SELECT '.$arguments.' FROM '.$table;
}
//check whether users use the where clause
if($where != null && is_array($where)){
$where = implode(' ', $where);
$sql .= ' WHERE '.$where ;
}
$query = $this->db->query($sql);
$query -> SetFetchMode(PDO::FETCH_NUM);
while($row = $query->fetch()){
print_r($row);
}
} else {
echo 'failed, moron';
}
}
And this is the way to run the function :
$columnname = array('bookname');
$where = array('bookid','=','2');
echo $database-> selectdata('buku', $columnname, $where);
The code worked quite decently so far, but I'm wondering how I want to use $where but without $columnname in the function. How do I pass the arguments in the function?
And could you point to me the better way to create a function to grab data using PDO?
Just use a PDO class which can look like this:
<?php
class DB_Connect{
var $dbh;
function __construct(){
$host = "xxx";
$db = "xxx";
$user = "xxx";
$password = "xxx";
$this -> dbh = $this -> db_connect($host, $db, $user, $password);
}
public function getDBConnection(){
return $this -> dbh;
}
protected function db_connect($host, $db, $user, $password){
//var_dump($host, $db, $user, $password);exit();
try {
$dbh = new PDO("mysql:host=$host;dbname=$db", $user, $password);
}
catch(PDOException $err) {
echo "Error: ".$err->getMessage()."<br/>";
die();
}
return $dbh;
}
public function query($statement){
$keyword = substr(strtoupper($statement), 0, strpos($statement, " "));
$dbh = $this->getDBConnection();
if($dbh){
try{
$sql = $dbh->prepare($statement);
$exe = $sql->execute();
}
catch(PDOException $err){
return $err->getMessage();
}
switch($keyword){
case "SELECT":
$result = array();
while($row = $sql->fetch(PDO::FETCH_ASSOC)){
$result[] = $row;
}
return $result;
break;
default:
return $exe;
break;
}
}
else{
return false;
}
}
}
?>
Now you can include that class and create an object with $dbh = new DB_Connect; and call every statement you want just with the reference on $dbh->query($statement)
This is my prefered way to do this.
EDIT: If you want to use a statement on another Database, just use the __construct($db) method to pass your database name on object creation
I am trying to establish a data connection to the MySql and create prepared statements, where the query_f function takes in any number of parameters, where the first parameter is the sql statement, and the other parameters are the values that would be substituted in the prepared statement.
Here is what I have. The first error I got is when I am trying to bind the values to the statement.
function query_f(/* query, [...] */){
$user = "root";
$pass = "root";
$host = "localhost";
$database = "mcnair";
$conn = mysqli_connect($host,$user,$pass);
if(!$conn)
{
echo "Cannot connect to Database";
}
else
{
mysqli_select_db($conn, $database);
}
// store query
$query = func_get_arg(0);
$parameters = array_slice(func_get_args(), 1);
$param = "'".implode("','",$parameters)."'";
// Prepare the statement
$stmt = mysqli_prepare($conn, $query);
if ($stmt == false)
{
echo "The statement could not be created";
exit;
}
// Bind the parameters
$bind = mysqli_stmt_bind_param($stmt, 's', $param);
echo mysqli_stmt_error($stmt);
if ($bind == false)
{
echo "Could not bind";
}
else
{
echo "Bind successful";
}
// Execute the statement
$execute = mysqli_stmt_execute($stmt);
if ($execute = false)
{
echo "Could not execute";
}
// fetch the data
$fetch = mysqli_stmt_fetch($stmt)
if ($fetch == false)
{
echo "Could not fetch data";
}
else
{
return $fetch;
}
}
And the function call I am using is:
query_f("SELECT Hash FROM alumni WHERE Username = '?'", "zm123");
How about using a class (instead of a function) and using mysqli in the OO way and not in the procedural way?
This is a simplified version of what I use. Not perfect, so if anyone would like to suggest improvements, I'm all ears.
class Connection {
private $connection;
public function __construct()
{
//better yet - move these to a different file
$dbhost = '';
$dbuname = '';
$dbpass = '';
$dbname = '';
$this->connection = new mysqli($dbhost, $dbuname, $dbpass, $dbname);
}
/*
* This is the main function.
*
* #param $arrayParams = array (0 => array('s' => 'Example string'), 1 => array('s' => 'Another string'), 2 => array('i' => 2), 3 => array('d' => 3.5) )
*/
public function executePrepared($sql, $arrayParams)
{
$statement = $this->prepareStatement($sql);
if ($statement) {
$this->bindParameter($statement, $arrayParams);
$this->executePreparedStatement($statement);
$result = $this->getArrayResultFromPreparedStatement($statement);
//only close if you are done with the statement
//$this->closePreparedStatement($statement);
} else {
$result = false;
}
return $result;
}
public function prepareStatement($sql)
{
$statement = $this->connection->prepare($sql) or $this->throwSqlError($this->connection->error);
return $statement;
}
public function bindParameter(&$statement, $arrayTypeValues)
{
$stringTypes = '';
$arrayParameters = array();
$arrayParameters[] = $stringTypes;
foreach ($arrayTypeValues as $currentTypeVale) {
foreach ($currentTypeVale as $type => $value) {
$stringTypes .= $type;
$arrayParameters[] = &$value;
}
}
$arrayParameters[0] = $stringTypes;
call_user_func_array(array($statement, "bind_param"), $arrayParameters);
}
public function getArrayResultFromPreparedStatement(&$statement)
{
$statement->store_result();
$variables = array();
$data = array();
$meta = $statement->result_metadata();
while($field = $meta->fetch_field())
$variables[] = &$data[$field->name]; // pass by reference
call_user_func_array(array($statement, 'bind_result'), $variables);
$i = 0;
$arrayResults = array();
while($statement->fetch())
{
$arrayResults[$i] = array();
foreach($data as $k=>$v)
{
$arrayResults[$i][$k] = $v;
}
$i++;
}
return $arrayResults;
}
public function executePreparedStatement($statement)
{
$result = $statement->execute() or $this->throwSqlError($statement->error);
return $result;
}
public function closePreparedStatement($statement)
{
$statement->close();
}
public function throwSqlError()
{ ... }
}
I've tried disabling emulated prepares in PDO but I cannot get it to work. Everything else works. The query is successful. The reason I believe it's not working is because it does not escape quotes and such so I get syntax errors.
I've tried doing it two different ways.
$this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
and
$insert = $database->$con->prepare($insert, array(PDO::ATTR_EMULATE_PREPARES => false));
I've also noticed that getAttribute does not work.
By doing this...
$emul = $database->$con->getAttribute(PDO::ATTR_EMULATE_PREPARES);
var_dump($emul);
...I get this error
SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute
And here's my database class where the action happens. (I might have left some unneccessary/stupid code in there while I was testing.)
<?php
class Database
{
public $dbh;
public $dbh1;
public $dbh2;
private static $instance;
public $numResults;
private $result = array(); // Results that are returned from the query
public function __construct()
{
try
{
$this->dbh = new PDO(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASS);
$this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh1 = new PDO(DB_TYPE1.':host='.DB_HOST1.';dbname='.DB_NAME1.';charset=utf8', DB_USER1, DB_PASS1);
$this->dbh1->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->dbh1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh2 = new PDO(DB_TYPE2.':host='.DB_HOST2.';dbname='.DB_NAME2.';charset=utf8', DB_USER2, DB_PASS2);
$this->dbh2->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->dbh2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
die("Database Error: ". $e->getMessage() . "<br />");
}
}
public static function getInstance()
{
if (!isset(self::$instance))
{
$object = __CLASS__;
self::$instance = new $object;
}
return self::$instance;
}
private function tableExists($table, $con)
{
switch($con)
{
case 'dbh':
$db_name = DB_NAME;
break;
case 'dbh1':
$db_name = DB_NAME1;
break;
case 'dbh2':
$db_name = DB_NAME2;
break;
}
$database = Database::getInstance();
if(is_array($table))
{
for($i = 0; $i < count($table); $i++)
{
$tablesInDb = $database->$con->prepare('SHOW TABLES FROM '.$db_name.' LIKE "'.$table[$i].'"');
$tablesInDb->execute();
$rowCount = $tablesInDb->rowCount();
if($tablesInDb)
{
if($rowCount <> 1)
{
die('Error: Table does not exist'.$table[$i]);
}
}
}
}else
{
$tablesInDb = $database->$con->prepare('SHOW TABLES FROM '.$db_name.' LIKE "'.$table.'"');
$tablesInDb->execute();
$rowCount = $tablesInDb->rowCount();
if($tablesInDb)
{
if($rowCount <> 1)
{
die('Error: Table does not exist'.$table);
}
}
}
return true;
}
public function insert($con, $table, $values, $cols = null)
{
if($this->tableExists($table, $con))
{
$insert = 'INSERT INTO '.$table;
if($cols != null)
{
$cols = implode(',', $cols);
$insert.= '('.$cols.')';
}
for($i = 0; $i < count($values); $i++)
{
if(is_string($values[$i]))
$values[$i] = "'".$values[$i]."'";
}
$values = implode(',', $values);
$insert .= ' VALUES ('.$values.')';
$database = Database::getInstance();
$insert = $database->$con->prepare($insert, array(PDO::ATTR_EMULATE_PREPARES => false));
$insert->execute();
if($insert)
{
return true;
}else
{
return false;
}
}
}
public function getResult()
{
return $this->result;
}
}
?>
As manual states, getAttribute() don't support ATTR_EMULATE_PREPARES
There shouldn't be no escaping with native prepares at all.
To check if you are in emulation mode or not you can use LIMIT clause with lazy binding. It will raise an error if emulation is on.
Your main problem is whatever "syntax error" you mentioned and you have to solve it first.
As Álvaro G. Vicario noted in comments, you are not using prepared statements. It is apparently the root of the problem. PDO doesn't "escape" your data by itself. It can do it only if you are using placeholders to represent your data in the query. You can read more here