I'm doing a CRUD with PHP in extjs grid.
The following code works fine:
include("conect.php");
$contacts= $_POST['contacts'];
$data = json_decode($contacts);
$nome = $data->name;
$email = $data->email;
$phone = $data->phone;
$state = $data->state;
$sqlQuery = "INSERT INTO contact (name, email, phone,state) values ('%s', '%s', '%s', '%s')";
$sqlRes = $conn->query($sqlQuery);
echo json_encode(array(
"success" => mysql_errno() == 0,
"contatos" => array(
"id" => mysql_insert_id(),
"name" => $name,
"email" => $email,
"phone" => $phone,
"state" => $state
)
));
However, I intend to use prepared statements.
I made the next attempt, without success:
include("conect.php");
$statement = $conn->stmt_init();
$contacts = $_POST['contacts'];
$data = json_decode($contacts);
$name = $data->name;
$email = $data->email;
$phone = $data->phone;
$state = $data->state;
$sqlQuery = "INSERT INTO contact (name, email, phone, state, id) values (?, ?, ?, ?, ?)";
$statement = $conn->prepare($sqlQuery);
$statement->bind_param("ssssi", $name_val, $email_val, $phone_val, $state, $id_val);
$statement->execute();
$statement->bind_result($col1, $col2, $col3, $col4, $col5);
while($statement->fetch()){
$output[] = array($col1, $col2, $col3, $col4, $col5);
};
$arr = array(
'success' => mysql_errno() == 0,
"contact" => array(
"id" => mysql_insert_id(),
"name" => $name,
"email" => $email,
"phone" => $phone,
"state" => $state
)
);
$statement->close();
echo json_encode($output, $arr);
$conn->close();
What am I doing wrong?
The extjs store:
Ext.define('APP.store.StoreAPP', {
extend: 'Ext.data.Store',
model: 'APP.model.ModelAPP',
pageSize: 25,
autoLoad:true,
autoLoad: {start: 0, limit: 25},
autoSync: false,
proxy: {
type: 'ajax',
api: {
create: 'php/createContact.php',
read: 'php/Contact.php',
update: 'php/updateContact.php',
destroy: 'php/deleteContact.php',
},
reader: {
type: 'json',
// root: 'contacts', //Extjs 4
rootProperty: 'contacts', //Extjs 5
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: true,
// root: 'contacts', //Extjs 4
rootProperty: 'contacts' //Extjs 5
}
}
});
Thanks in advance.
EDIT
Thanks for replying.
I've read everything I could find (internet, books) about mysqli and prepared statements.
I could not find an answer so far.
I think the problem is in json_decode and json_encode.
The following code identical to your logic works well:
include("conn.php");
$sqlQuery = "SELECT phone FROM contact WHERE name = ? AND email = ? ";
$statement = $conn->prepare($sqlQuery);
$name = "John";
$email = "email#email.com";
$statement->bind_param("s",$name, $email);
$statement->execute();
$statement->bind_result($col1, $col2);
while($statement->fetch()){
$output[] = array($col1, $col2);
};
echo json_encode($output);
$statement->close();
$conexao->close();
I think the problem is in json_decode and json_encode.
'contacts' like you say it's a array and its extjs store rootProperty config (= name of database).
The data it's provide in textfields form (name, email, phone, state).
Any idea what could be wrong?
EDIT
Next code works, but not quite what I want.
It seems to be a mixture of mysql in json decode and encode with mysqli prepared statements.
mysqli_errno() does not work in json_encode; just mysql_errno().
If you have other ideas, I will be grateful.
Thanks.
include("conect.php");
$contacts= $_POST['contacts'];
$data = json_decode($contacts);
$name = $data->name;
$email = $data->email;
$phone = $data->phone;
$state = $data->state;
$sqlQuery = "INSERT INTO contact (name, email, phone, state) values (?, ?, ?, ?)";
$statement= $conn->prepare($sqlQuery);
$statement -> bind_param ("ssss", $name_val, $email_val, $phone_val, $state_val);
$statement->execute();
echo json_encode(array(
"success" => mysql_errno() == 0,
"contatos" => array(
"name" => $name,
"email" => $email,
"phone" => $phone,
"state" => $state
)
));
From what I can see, There are a number of issues that need addressing with the above code examples.
The top block of code that you have entered would not enter correct information into the database, Your not assigning the values, just '%s'. I just ran the exact same command and got this as the row:
1, %s, %s, %s, %s
Referring to this line: $contacts = $_POST['contacts']; and the plural naming, I would presume that $contacts will contain more than one value, so the variable will be an array of values, so statements such as $name = $data->name; will not work, You would need to work with the array, maybe using a loop. Without knowing the data being provided its difficult to say.
bind_result is used to display results, but an insert statement wont return any results. If you want to see how many results are being returned use $statement->affected_rows or check the boolean result of $statement->execute for success/fail.
The code below works for me:
<?php
$mysqli = new mysqli("localhost", "test_user", "test_pass", "test_db");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$statement = $mysqli->stmt_init();
$data = new stdClass();
$data->name = "Bob";
$data->email = "bob#example.com";
$data->phone = "555-5555";
$data->state = "Some State";
// I use auto increment for the ID field.
$sqlQuery = "INSERT INTO contact (`name`, `email`, `phone`, `state`) values (?, ?, ?, ?)";
$statement = $mysqli->prepare($sqlQuery);
$statement->bind_param("ssss", $data->name, $data->email, $data->phone, $data->state);
$statement->execute();
$arr = array(
'success' => mysqli_errno($mysqli) == 0,
"contact" => array(
"id" => mysqli_insert_id($mysqli),
"name" => $data->name,
"email" => $data->email,
"phone" => $data->phone,
"state" => $data->state
)
);
$statement->close();
echo json_encode($arr);
$mysqli->close();
I would suggest having a read on the Mysqli Docs.
EDIT: To insert multiple entries into the database from an array you would need to use a loop such as this code.
$contacts = json_decode($_POST['contacts']);
foreach ($contacts as $contact) {
// I use auto increment for the ID field.
$sqlQuery = "INSERT INTO contact (`name`, `email`, `phone`, `state`) values (?, ?, ?, ?)";
$statement = $mysqli->prepare($sqlQuery);
$statement->bind_param("ssss", $contact->name, $contact->email, $contact->phone, $contact->state);
$statement->execute();
}
This should be expanded to include additional error checking / reported but it should give you working code that answers your question, giving you a good starting point. Hope it helps.
EDIT 2: This other StackOverflow post shows methods of inserting multiple rows using prepared statements
Related
I have a registration form that use PDO to insert the data into database.
This is my html file;
https://codepen.io/anon/pen/pYOKJx
This is my insert.php file
<?php
//insert.php;
if(isset($_POST["cname"]))
{
$connect = new PDO("mysql:host=localhost;dbname=dbname", "testing", "pass");
for($count = 0; $count < count($_POST["cname"]); $count++)
{
$query = "INSERT INTO guest
(cname, sex, ic, age, nationality, phone, e_phone, address, check_in, check_out,remarks)
VALUES (:cname, :sex, :ic, :age, :nationality, :phone, :e_phone, :address, :check_in, :check_out, :remarks)
";
$statement = $connect->prepare($query);
$statement->execute(
array(
':cname' => $_POST["cname"][$count],
':sex' => $_POST["sex"][$count],
':ic' => $_POST["ic"][$count],
':age' => $_POST["age"][$count],
':nationality' => $_POST["nationality"][$count],
':phone' => $_POST["phone"][$count],
':e_phone' => $_POST["e_phone"][$count],
':address' => $_POST["address"][$count],
':check_in' => $_POST["check_in"][$count],
':check_out' => $_POST["check_out"][$count],
':remarks' => $_POST["remarks"][$count]
)
);
}
$result = $statement->fetchAll();
if(isset($result))
{
echo 'ok';
}
}
?>
I couldn't find any error in error log but when I check my database, the data was not inserted.
What should I change to make it works?
Have you tried changing :
$result = $statement->fetchAll();
if (isset($result)) {
echo 'ok';
}
to
if ($statement->fetchAll()) {
echo 'ok';
}
because it seems that your isset($result) is not executing the command.
I am a beginner when we talk about PHP. SO I have no idea where I made a mistake using PHP.
<?php
require "conn.php";
$name = "yolo";
$surname = "yolo";
$nameOfFee= "asd";
$date = '2012-08-06';
$mysql_query = "(INSERT INTO Relation (Person_ID, Fee_ID, Date_of_fee)
SELECT Person.ID,Fee.ID,'$date'
FROM Person,Fee
WHERE Person.Name = '$name' AND Person.Surname = '$surname' AND Fee.Name_of_fee = '$nameOfFee');";
if($conn->query($mysql_query) === TRUE){
echo "Insert completed";
}
else{
echo "Insert not completed";
}
$conn->close();
?>
It always puts that Insert is not complete...
The Problems
There are a few syntax errors in this piece of code you have provided:
// here it starts, what is this "(" for before insert?
// Take note that your query is vulnerable to SQL attacks
$mysql_query = "(INSERT INTO Relation (Person_ID, Fee_ID, Date_of_fee)
SELECT Person.ID,Fee.ID,'$date'
FROM Person,Fee
WHERE Person.Name = '$name' AND Person.Surname = '$surname' AND Fee.Name_of_fee = '$nameOfFee');";
How to fix it
To fix these things I recommend you use the MySQLi OOP, like you are using now, but add prepared statements. I will walk through the new code with you so you can understand the process.
require "conn.php";
$name = "yolo";
$surname = "yolo";
$nameOfFee= "asd";
$date = '2012-08-06';
$sql = "INSERT INTO Relation (Person_ID, Fee_ID, Date_of_fee) VALUES (?, ?, ?)"; // rewrite your query with a preset number of values to prevent SQL Attacks
if($stmt = $conn->prepare( $sql ))
{ // before we run check to make sure the query worked
$stmt->bind_param('sss', $name, $nameOfFee, $date); // bind your variables so to know what goes where
$stmt->execute(); // execute the query
$stmt->close(); // close connection for safety
// message as an array for the user as feedback.
$message = array(
'is_error' => 'success',
'message' => 'Record was entered into database.'
);
}
else
{
$message = array(
'is_error' => 'danger',
'message' => 'Query Error, please revise the information.'
);
}
I'm using ADODB and MYSQL, trying to execute an INSERT statement.
Though I've read plenty of forum posts and learned that I cannot bind parameters as easily as with oci8, I still have not found an example similiar to what I'm trying to achieve. My code is as follows with oci8:
$street = $branch->getStreet();
$number = $branch->getNumber();
$city = $branch->getCity();
$state = $branch->getState();
$xMap = $branch->getXMap();
$yMap = $branch->getYMap();
$email = $branch->getEmail();
try{
//$this->db->debug = true;
$sql = "INSERT INTO branch ( nombre_branch, street, number, city, state, x_map, y_map, email ) VALUES (:branchName, :street, :number, :city, :state, :xMap, :yMap, :email)";
$sp = $this->db->PrepareSP($sql);
$this->db->InParameter($sp, $branchName, 'branchName');
$this->db->InParameter($sp, $street, 'street');
$this->db->InParameter($sp, $number, 'number');
$this->db->InParameter($sp, $city, 'city');
$this->db->InParameter($sp, $state, 'state');
$this->db->InParameter($sp, $xMap, 'xMap');
$this->db->InParameter($sp, $yMap, 'yMap');
$this->db->InParameter($sp, $email, 'email');
$rs = $this->db->Execute($sp);
} catch(ADODB_Exception $adodb_exception){
$logInfo['exception'] = $adodb_exception->getMessage();
$message = "'[".__CLASS__."] Error al executing ' insert '";
if( !$this->rollbackTransaction()){
if(!is_null($this->log)) $this->log->log("ERROR in DB: ".print_r($logInfo, true), PEAR_LOG_ERR);
$message .= " Error in ROLLBACK.";
throw new DAODatabaseTransactionException ($message, $adodb_exception->getCode());
}
}
return $returnValue;
}
Thanks!
This is how i got it to work with mysql, without having to implement PDO
$sql = "INSERT INTO branch( branch_name, street, number, city, state, x_map, y_map, email) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$rs = $this->db->Execute($sql, array($branchName, $street, $number, $city, $state, $xMap, $yMap, $email));
$rs->Close();
My PHP form I just changed to use PDO. The only thing I can tell is the execute is not working. Am I supposed to pass something with it?
$db = new PDO('mysql:host=localhost;dbname=x;charset=utf8', 'x', 'x');
if ( !$db )
{
die('Could not connect: ' . mysql_error());
}
$ipaddress = $_SERVER['REMOTE_ADDR'];
$mail = $_POST['mail'];
$stmt = $db->prepare("SELECT * FROM ucm_signup WHERE email =? ");
$stmt->bindValue(1, $mail, PDO::PARAM_STR);
$stmt->execute();
if($stmt->rowCount()== 0) {
//if there are no duplicates...insert
$sql = $db->prepare("INSERT INTO ucm_signup (company, address1, address2, city, province, zip, fname, lname, email, phone, session, iama, buyfrom, group1, ipaddress)
VALUES (:company, :address1, :address2, :city, :province, :zip, :fname, :lname, :mail, :phone, :session, :iama, :buyfrom, :group1, :ipaddress)");
$sql->bindParam(":company", $_POST['company'],PDO::PARAM_STR);
$sql->bindParam(":address1", $_POST['address1'],PDO::PARAM_STR);
$sql->bindParam(":city", $_POST['city'],PDO::PARAM_STR);
$sql->bindParam(":province", $_POST['province'],PDO::PARAM_STR);
$sql->bindParam(":zip", $_POST['zip'],PDO::PARAM_STR);
$sql->bindParam(":fname", $_POST['fname'],PDO::PARAM_STR);
$sql->bindParam(":lname", $_POST['lname'],PDO::PARAM_STR);
$sql->bindParam(":email", $_POST['email'],PDO::PARAM_STR);
$sql->bindParam(":phone", $_POST['phone'],PDO::PARAM_STR);
$sql->bindParam(":session", $_POST['session'],PDO::PARAM_STR);
$sql->bindParam(":imea", $_POST['imea'],PDO::PARAM_STR);
$sql->bindParam(":buyfrom", $_POST['buyfrom'],PDO::PARAM_STR);
$sql->bindParam(":imea", $_POST['imea'],PDO::PARAM_STR);
$sql->bindParam(":group1", $_POST['group1'],PDO::PARAM_STR);
$sql->bindParam(":ipaddress", $_POST['ipaddress'],PDO::PARAM_STR);
$sql->execute();
}
My database table has no records. Thank you
You are missing some placeholder in your bind parameters, check them carefully
$sql->bindParam(":address1", $_POST['address1'],PDO::PARAM_STR);
$sql->bindParam(":address2", $_POST['city'],PDO::PARAM_STR);
//address2 was missed, probably error is column doesn't match values
$sql->bindParam(":email", $_POST['email'],PDO::PARAM_STR); //supposed to be mail
$sql->bindParam(":imea", $_POST['imea'],PDO::PARAM_STR); //supposed to be iama
You might want to check for pdo errors, here an example taken from manual
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
With this attribute correctly added pdo will notify you if any error occur
PHP users are so PHP users.
First they're laboring on a WALL of code, consists of constantly repeating nearly hundred variables.
Then they get totally lost.
While everything can be done with short and concise code, writing each field name only ONCE
$allowed = array('company', 'address1', 'address2', 'city', 'province',
'zip', 'fname', 'lname', 'email', 'phone', 'session',
'iama', 'buyfrom', 'group1', 'ipaddress');
$_POST['ipaddress'] = $_SERVER['REMOTE_ADDR'];
$sql = "INSERT INTO ucm_signup SET ".pdoSet($allowed, $values);
$stm = $dbh->prepare($sql);
$stm->execute($values);
where pdoSet() helper function can be stored elsewhere and reused for the every insert or update query
function pdoSet($fields, &$values, $source = array()) {
$set = '';
$values = array();
if (!$source) $source = &$_POST;
foreach ($fields as $field) {
if (isset($source[$field])) {
$set.="`".str_replace("`","``",$field)."`". "=:$field, ";
$values[$field] = $source[$field];
}
}
return substr($set, 0, -2);
}
For a PDO execution statement I am trying to make any static information such as column names and array strings to a dynamic array which contains every column from the MySQL table.
The original code was:
$stmt = $conn->prepare("INSERT into data (`username,` `password`, `email`) VALUES username = :username , password = :password , email = :email ");
$stmt->execute(array(
':username' => $entry_username,
':password' => $entry_password,
':email' => $entry_email
));
So far I have been able to change the sql statement to
$sql = "INSERT into DATA (`" . implode('`,`', $columns) . "`) values (:" . implode(',:', $columns) . ")";
$stmt = $conn->prepare($sql);
but have been unable to do a similar thing to the execution array to make it dynamically variating like the statement.
I have tried adding a for statement in the array
for ($i = 0; $i < count($columns); $i++) {
':'.$columns[$i] => ${'entry_'.$columns[$i]};
}
but this hasn't worked.
Any help would be much appreciated.
Thanks in advance!
This is a perfect situation to make good use of a prepared statement.
Try this:
I am kind of assuming what the varuables will be called in the $columns array here.
$stmt = $conn->prepare("INSERT into data
(username, password, email) VALUES( :username , :password, :email )");
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
foreach ( $columns as $column ) {
$username = $column['username'];
$password = $column['password'];
$email = $column['email'];
$result = $stmt->execute();
if ( ! $result ) {
// add some error checking code here
}
}
Basically, your code would look like this.
$entry = array(
'username' => $_POST['username'], //assuming it's comming from the post data or for instance $row['username'] if from previous select statement
'password' => $_POST['password'],
'email' => $_POST['email']
);
$sth = $dbh->prepare('INSERT into data (`username,` `password`, `email`) VALUES (:username, :password, :email)');
$sth->bindValue(':username', $entry['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $entry['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $entry['email'], PDO::PARAM_STR);
$sth->execute();
If you want the bound variables to be dynamically created, then you need to create with a loop the bindValue rows:
$entry = array(
'username' => $_POST['username'], //assuming it's comming from the post data or for instance $row['username'] if from previous select statement
'password' => $_POST['password'],
'email' => $_POST['email']
);
$sth = $dbh->prepare('INSERT into data (`username,` `password`, `email`) VALUES (:username, :password, :email)');
foreach($entry as $key => $value) {
$sth->bindValue(':'.$key, $entry[$key], PDO::PARAM_STR);
}
$sth->execute();
or inside the foreach
$sth->bindValue(':'.$key, $value, PDO::PARAM_STR);
Since your keys are (username, password, email) their keynames will be initiated to $key variable, and their values to the $value variable. in the first case it will produce:
$sth->bindValue(':username', $entry['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $entry['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $entry['email'], PDO::PARAM_STR);
Which will be evaluated to:
$sth->bindValue(':username', $_POST['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $_POST['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $_POST['email'], PDO::PARAM_STR);
In the second case it will be directly evaluated.
Have in mind it's completely unacceptable to dynamically create the column names in the query. And you have to reason to do it. However, not a full query is also hard to be read from the other developers. It's enough for you to dynamically create the bound values. You can make a method do it for you. For instance, if you column names in the query are the same way aliased, as the names of the input fields, you will have nothing more to do, but to execute the query.
Let's say you have that helper method:
Class DBConnect {
private $_driver = "mysql";
private $_dbname = "xxxx";
private $_host = "xxxx";
private $_user = "xxxx";
private $_password = "xxxx";
private $_port = 3306;
private $_dbh;
public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
$driver = $driver ?: $this->_driver;
$dbname = $dbname ?: $this->_dbname;
$host = $host ?: $this->_host;
$user = $user ?: $this->_user;
$pass = $pass ?: $this->_password;
$port = $port ?: $this->_port;
try {
$this->_dbh = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
$this->_dbh->exec("set names utf8");
} catch(PDOException $e) {
echo $e->getMessage();
}
}
public function query($sql) {
$sth = $this->_dbh->prepare($sql);
foreach ($_REQUEST as $key => $value) {
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
$sth->bindValue(":$key", $value, $param);
}
$sth->execute();
$result = $sth->fetchAll();
return $result;
}
}
So, lets say in another class you have a lot of queries, separated by methods:
public function getFirstQuery() {
$sql = "SELECT
col1, col2
FROM table1
WHERE col3 = :col3;";
$query = $this->_db->query($sql);
return $query;
}
public function inserSecondquery() {
$sql = "INSERT INTO
`table1`
(col1, col2)
VALUES
((SELECT
id
FROM table2
WHERE col8 = :col8), :post_field_5);";
$query = $this->_db->query($sql);
return $query;
}
Assuming you have called these queries the query() method which also fetches the data, the select one you can foreach to retrieve the data, and the insert one you can just call, to insert data. The only rule here is the post fields should be named same way, for example <input name="post_field_5" />
You can also take a look here: PDO Dynamic Query Building
OK, it seems you need to find library for active record like the ones CodeIgniter uses, or... use CodeIgniter.
From the official documentation:
http://ellislab.com/codeigniter/user-guide/database/helpers.html
$this->db->insert_string();
This function simplifies the process of writing database inserts. It
returns a correctly formatted SQL insert string. Example: $data =
array('name' => $name, 'email' => $email, 'url' => $url);
$str = $this->db->insert_string('table_name', $data);
The first parameter is the table name, the second is an associative
array with the data to be inserted. The above example produces: INSERT
INTO table_name (name, email, url) VALUES ('Rick', 'rick#example.com',
'example.com')
So, in your case, you can have something like this:
<form action="" method="post">
<input type="text" name="username" value="testUser123" />
<input type="password" name="password" value="yourPass666" />
<input type="text" name="email" value="email#example.com" />
<input type="submit" value="submit" />
</form>
<?php
//... extending CI
//... opening a method
$table = 'data';
//comming from somewhere, let's dynamically populated array but for testing purpose I will hardcode:
$columns('username', 'password', 'email');
foreach($columns as $column) {
$data[$column] = $_POST[$column]; // this will produce $data=array('username'=>$_POST['username'],password=....);
}
$str = $this->db->insert_string($table, $data);
?>
If you submit the form in the beginning, you will have:
INSERT INTO data (username, password, email) VALUES ('testUser123', 'yourPass666', 'email#example.com');
The whole active record class doc (insert chosen here)
http://ellislab.com/codeigniter/user-guide/database/active_record.html#insert
If you don't have to stick to the for loop, I would suggest a foreach, which should be easier (I know the little problems with for too).
foreach ($element in $array)
{
code execution here
}
Your array element is then stored in the $element (or as you like to name it) and you can execute the command found there.
Is this what you're looking for or did I get you wrong?