Executing multiple update statements in PHP - php

I have three update statements to be executed in PHP, i am getting the values of all these as return parameters. How to execute each statement independely and finally show the end user the result that it has been successfully updated.
<?php
public function name($parameter1,$parameter2.... $parametern) {
}
?>
Then how finally we can get the result in my row object.

Ah i think i see, well looks to me from your update statements that you want to update 3 different tables which all depend on 'tycodashboard'.
In that case i advise you use transactions to retain a bit of data integrity, otherwise say if one fails? you'll have lost some data. As a general rule, if you need to do more than 1 update simultaneously use transactions.
Heres a great article on the subject: http://dev.mysql.com/doc/refman/5.0/en/commit.html
Its quite easy to do, just make you sure your tables are using the INNODB, then all you have to do is append START TRANSACTION to the top of your sql script and then COMMIT at the end.
You might be trying to combine too much into a single function, whenever i'm updating multiple tables, it's easier to just handle each one in turn, rather than trying to stuff them all into one return. So try making a function that saves it, returning success or failure, then call it from your main function for each one of your sql scripts passing in the values.
//This is the function that gets called from your page.
public function my_called_function() {
//your sql script (using "" means you can put variables in without having to remove the quotes)
$sql = "UPDATE....SET 'col' = $_POST['myvalue']";
//Run your script and get result
$result = $this->save_my_stuff($sql);
//if not null means success!
if($result) {
echo 'success!'; // your success message
}
else {
echo 'something bad happened'; //your failure message
}
}
//this is the function that does the saving!
private function save_my_stuff($sql_script) {
//Make connection
$conn = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
//Check connection
if(!$conn) {
//connection failed
die('Could not connect: '.mysql_error());
}
//Select your database using your connection object
mysql_select_db(DB_NAME, $conn);
//try and save
try {
//run the query
$result = mysql_query($sql_script, $conn);
//return the result
return mysql_result($result);
}
catch (Exception $e) {
//deal with exception
return null;
}
//close connection
mysql_close();
}

Related

Grabbing things from database using functions. Is this safe?

I have a simple question. I'm not too good at programming yet but is this safe and correct?
Currently I am using functions to grab the username, avatars, etc.
Looks like this:
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
config.php ^^
function getUsername($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT username FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$name = $stmt->fetch();
return $name["username"];
}
function getProfilePicture($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$image = $stmt->fetch();
return $image["profilepicture"];
}
Is this correct and even more important, is this safe?
Yes, it's safe with respect to SQL injections.
Some other answers are getting off topic into XSS protection, but the code you show doesn't echo anything, it just fetches from the database and returns values from functions. I recommend against pre-escaping values as you return them from functions, because it's not certain that you'll be calling that function with the intention of echoing the result to an HTML response.
It's unnecessary to use is_int() because MySQL will automatically cast to an integer when you use a parameter in a numeric context. A non-numeric string is interpreted as zero. In other words, the following predicates give the same results.
WHERE id = 0
WHERE id = '0'
WHERE id = 'banana'
I recommend against connecting to the database in every function. MySQL's connection code is fairly quick (especially compared to some other RDBMS), but it's still wasteful to make a new connection for every SQL query. Instead, connect to the database once and pass the connection to the function.
When you connect to your database, you catch the exception and echo an error, but then your code is allowed to continue as if the connection succeeded. Instead, you should make your script die if there's a problem. Also, don't output the system error message to users, since they can't do anything with that information and it might reveal too much about your code. Log the error for your own troubleshooting, but output something more general.
You may also consider defining a function for your connection, and a class for your user. Here's an example, although I have not tested it:
function dbConnect() {
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
error_log("PDO connection failed: " . $e->getMessage());
die("Application failure, please contact administrator");
}
}
class User {
protected $row;
public function __construct($userid) {
global $conn;
if (!isset($conn)) {
$conn = dbConnect();
}
$stmt = $conn->prepare("SELECT username, profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$this->row = $stmt->fetch(PDO::FETCH_ASSOC);
}
function getUsername() {
return $this->row["username"]
}
function getProfilePicture() {
return $this->row["profilepicture"]
}
}
Usage:
$user = new User(123);
$username = $user->getUsername();
$profilePicture = $user->getProfilePicture();
That looks like it would work assuming that your config file is correct. Because it is a prepared statement it looks fine as far as security.
They are only passing in the id. One thing you could do to add some security is ensure that the $userid that is passed in is the proper type. (I am assuming an int).
For example if you are expecting an integer ID coming in and you get a string that might be phishy (possible SQL injection), but if you can confirm that it is an int (perhaps throw an error if it isn't) then you can be sure you are getting what you want.
You can use:
is_int($userid);
To ensure it is an int
More details for is_int() at http://php.net/manual/en/function.is-int.php
Hope this helps.
It is safe (at least this part of the code, I have no idea about the database connection part as pointed out by #icecub), but some things you should pay attention to are:
You only need to require your config.php once on the start of the file
You only need to prepare the statement once then call it on the function, preparing it every time might slow down your script:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. - PHP Docs
(Not an error but I personally recommend it) Use Object Orientation to help organize your code better and make easier to mantain/understand
As stated by #BHinkson, you could use is_int to validate the ID of the user (if you are using the IDs as numbers)
Regarding HTML escaping, I'd recommend that you already register your username and etc. HTML escaped.

I have this error: Couldn't fetch mysqli, with no database errors

I am posting a form to insert values into a database using mysqli, I am getting the following error:
Warning: mysqli::real_escape_string() [mysqli.real-escape-string]: Couldn't fetch mysqli in /home/richa161/public_html/chat/chat.class.php
I have tried wrapping it in an if statement to check for errors coming back from the DB but there are none. Here is my code:
require_once('config.php');
class Chat {
private $mysqli;
//open database connection
function __construct(){
$this->mysqli = new mysqli(DB_HOST,DB_USER,DB_PASS,DATABASE);
if($this->mysqli->connect_error){
die('error');
} else {
die('ok');
}
}
//insert message to database
public function postMessage($username, $message){
if ($this->mysqli->connect_error) {
die('Connect Error: ' . $this->mysqli->connect_error);
} else {
//make data safe for database
$username = $this->mysqli->real_escape_string($username);
$message = $this->mysqli->real_escape_string($message);
//build query
$query = "INSERT INTO chat (post_date, username, message) VALUES(NOW(),'".$username."','".$message."')";
//execute query and store in $result
$result = $this->mysqli->query($query);
echo $query;
}
}
//close database connection
function __destruct(){
$this->mysqli->close();
}
}
I am grabbing the form data using jQuery and sending it to another file which then uses the classes to call the function required. I do not think the problem is in these files however.. If you think I need to post them I will. Quite sure the error is in the above however.
Connection details are 100% correct..
The jQuery posts values username and message to this page which then calls the class:
require_once('chat.class.php');
session_start();
if(!isset($_SESSION['chat'])){
$_SESSION['chat'] = new chat();
}
$chat = $_SESSION['chat'];
$username = $_POST['username'];
$message = $_POST['message'];
//run function
$chat->postMessage($username, $message);
Starting to think it is the way in which I am posting to my file ajaxRouter.php which is above this text.
index.php contents:
<script type="text/javascript">
$("#chatForm").submit(function(e){
e.preventDefault();
var username = $("input[name='username']").val();
var message = $("input[name='message']").val();
charCount = username.length;
if(!/[^a-zA-Z0-9]/.test(username) && charCount > 2) {
$.ajax({
url: 'ajaxRouter.php',
type: 'post',
data: { 'username' : username, 'message' : message },
success:function(result){
console.log(result);
}
});
} else {
alert("Username must be more than 2 charcters, no special charcters allowed");
}
});
</script>
You are not constructing a mysqli object, the class mysqli_connect does not exist.
You need to change your constructor to:
function __construct(){
$this->mysqli = new mysqli(DB_HOST,DB_USER,DB_PASS,DATABASE);
^^^^^^ You need to construct a `mysqli` object
}
This is also wrong:
$query = "INSERT INTO chat (post_date, username, message) VALUES(NOW(),".$username.",".$message.")";
Assuming that $username and $message are strings, you need to quote them:
$query = "INSERT INTO chat (post_date, username, message)
VALUES(NOW(),'{$username}','{$message}')";
^ ^ ^ ^ here
Edit: You don't have any error handling in your constructor. To see if all mysqli calls execute without problems, you can setup mysqli to throw exceptions when something goes wrong so that you don't have to check manually on each call. To do that, add this to the top of your script:
ini_set('display_errors',1);
error_reporting(E_ALL | E_STRICT);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Edit 2: You cannot persist your database connection in your session like that. You need to start a new database connection every time the script is started. The most logical solution would be to separate the database operation from the chat class and instantiate that always.
In postMessage(...) you check $this->mysqli->error, which isn't necessarily a connection error (what else is happening between the time the constructor is called and this function is called?). Try checking $this->mysqli->connect_error in __construct and if the connection failed, set $this->mysqli to null. Then you can then check whether or not $this->mysqli is instantiated before you try to use it in other places.
http://php.net/manual/en/mysqli.connect-error.php
http://php.net/manual/en/mysqli.error.php
What you have to check is your DB_HOST,DB_USER,DB_PASS,DATABASE constants.
This error could happen when some of these don't have appropriate values.
Also make sure you quote your values as Fred -ii- pointed:
$query = "INSERT INTO chat (post_date, username, message) VALUES(NOW(),'".$username."','".$message."')";
EDIT:
This is from the manual:
The cryptic "Couldn't fetch mysqli" error message can mean any number
of things, including:
You're trying to use a database object that you've already closed. Reopen your database connection,
or find the call to mysqli_close($db); or $db->close();
and remove it.
Your MySQLi object has been serialized and unserialized for some reason. Define a wakeup function to re-create your database
connection. http://php.net/__wakeup
Something besides you closed your mysqli connection (in particular, see http://bugs.php.net/bug.php?id=33772)
You mixed OOP and functional calls to the database object. (So, you have $db->query() in the same program as
mysqli_query($db)).
This happened to me. The problem occured because I have included two php files ; one for the database connection and another for users' authentication. The users' authentication file itself has the database connection file included. In effect two connections in one php file

PHP constant SQL query

I need to constantly read from my database every 1 second to get the latest values. Here is my code:
<?php
// connect to the "tests" database
$conn = new mysqli('localhost', 'root','','Test');
// check connection
if (mysqli_connect_errno()) {
exit('Connect failed: '. mysqli_connect_error());
}
// SELECT sql query
$sql = "SELECT * FROM `Value`";
// perform the query and store the result
$result = $conn->query($sql);
if (!$result)
print 'Error!';
// if the $result contains at least one row
if ($result->num_rows > 0) {
// output data of each row from $result
while($row = $result->fetch_assoc()) {
$output=$row;
print_r($output);
}
}
else {
print '0 results';
}
$conn->close();
?>
My HTML code refreshes every 1 second as follows:
function reload (){
setInterval(getData,1000);
}
function getData()
{
$.get('test.php', function(data) {
var output = data;
document.getElementById("output").innerHTML = "Info: " + output;
});
}
....
<body onload="reload();">
<p id="output"></p>
</body>
Everything works fine but after around 5-10 mins the MYSQL server crashes. I'm assuming it is being overloaded. My thoughts are that I keep running the php script every time which connects each second. Am I doing this incorrectly? Anyone have any suggestions on a better implementation?
I think you are looking for something to have the database "unclosed" when the script has ended.
In mysqli you can prepend the hostname by adding p: to use a so called persistant database connection
// connect to the "tests" database
$conn = new mysqli('p:localhost', 'root','','Test');
Read more about persistant connections here:
http://php.net/manual/en/features.persistent-connections.php
You might try having it not start the next request until 1 second after the last one finishes by calling setTimeout() in the callback like so:
function getData()
{
$.get('test.php', function(data) {
var output = data;
document.getElementById("output").innerHTML = "Info: " + output;
setTimeout(getData, 1000);
});
}
....
<body onload="getData();">
This is generally a better approach than using setInterval(), cuz you may end up having two concurrent connections and request A may start before request B, but may end after B, because something happened and it took more than a second to finish the request. This could cause some weird behavior.
This may also fix your issue, because maybe it fails because it ends up having several concurrent connections open from the same IP, etc.
Yes it can be implement in a much better way.
As you are using same Database connection configuration every-time, there is no need to connect and close database on page refresh.Connecting to database server every-second is very expensive call.
Why don't you just reload/refresh the query statement?
The idea is:
Use Persistent Database Connection
Refer BlaM answer in following post to know why persistent connections is optimal.
Put the queries in a separate div say #load.
echo '<div id="load">';
// SELECT sql query
$sql = "SELECT * FROM `Value`";
// perform the query and store the result
$result = $conn->query($sql);
if (!$result)
print 'Error!';
// if the $result contains at least one row
if ($result->num_rows > 0) {
// output data of each row from $result
while($row = $result->fetch_assoc()) {
$output=$row;
print_r($output);
}
}
else {
print '0 results';
}
echo '</div>';
Use jquery function to refresh only #load div
<script type="text/javascript">
var auto_refresh = setInterval(
function ()
{
$("#load").load("filename.php #load");
}15000); // refresh every 1 second
</script>
I had implemented this for auto-refresh leaderboard page.It worked perfectly and server didn't crash even in 50 hrs.

Trying to execute a SELECT statement in MYSQL but it is not working

I believe I have the syntax correct, at least according to my textbook. This is just a piece of the file as the other info is irrelevant to my problem. The table name is user, as well as the column name is user. I don't believe this to be the problem, as other sql statements work. Though it isn't the smartest thing to do I know :) Anyone see an error?
try {
$db=new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user,$db_pass);
} catch (PDOException $e) {
exit("Error connecting to database: " . $e->getMessage());
}
$user=$_SESSION["user"];
$pickselect = "SELECT game1 FROM user WHERE user='$user' ";
$pickedyet = $db->prepare($pickselect);
$pickedyet->execute();
echo $pickselect;
if ($pickedyet == "0")
{
echo '<form method="post" action="makepicks.php">
<h2>Game 1</h2>......'
Since you're seemingly using prepared statements, I'd recommend using them to their fullest extent so that you can avoid traditional problems like SQL injection (this is when someone passes malicious SQL code to your application, it's partially avoided by cleansing user inputs and/or using bound prepared statements).
Beyond that, you've got to actually fetch the results of your query in order to display them (assuming that's your goal). PHP has very strong documentation with good examples. Here are some links: fetchAll; prepare; bindParam.
Here is an example:
try
{
$db = new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user, $db_pass);
}
catch (PDOException $e)
{
exit('Error connecting to database: ' . $e->getMessage());
}
$user = $_SESSION['user'];
$pickedyet = $db->prepare('SELECT game1 FROM user WHERE user = :user');
/* Bind the parameter :user using bindParam - no need for quotes */
$pickedyet->bindParam(':user', $user);
$pickedyet->execute();
/* fetchAll used for example, you may want to just fetch one row (see fetch) */
$results = $pickedyet->fetchAll(PDO::FETCH_ASSOC);
/* Dump the $results variable, which should be a multi-dimensional array */
var_dump($results);
EDIT - I'm also assuming that there is a table called 'user' with a column called 'user' and another column called 'game1' (i.e. that your SQL statement is correct aside from the usage of bound parameters).
<?php
session_start();
$db_user = 'example';
$db_pass = 'xxxxx';
try
{
// nothing was wrong here - using braces is better since it remove any confusion as to what the variable name is
$db=new PDO( "mysql:host={$db_host}dbname={$db_name}", $db_user, $db_pass);
}
catch ( Exception $e ) // catch all exceptions here just in case
{
exit( "Error connecting to database: " . $e->getMessage() );
}
// this line is unecessary unless you're using it later.
//$user = $_SESSION["user"];
// no need for a new variable here, just send it directly to the prepare method
// $pickselect = '...';
// also, I changed it to a * to get the entire record.
$statement = $db->prepare( "SELECT * FROM user WHERE user=:user" );
// http://www.php.net/manual/en/pdostatement.bindvalue.php
$statement->bindValue( ':user', $_SESSION['user'], PDO::PARAM_STR );
$statement->execute();
// http://www.php.net/manual/en/pdostatement.fetch.php
// fetches an object representing the db row.
// PDO::FETCH_ASSOC is another possibility
$userRow = $statement->fetch( PDO::FETCH_OBJ );
var_dump( $userRow );
echo $userRow->game1;
Change this user=$user with this user='$user'. Please, note the single quotes.
Moreover, you are executing the query $pickedyet->execute(); but then you do echo $pickselect; which is nothing different from the string that contains the query.
Little hints:
You've to retrieve the result of the query execution.
You're using prepared statement which are very good but you're not really using they because you're not doing any binding.

How can I implement commit/rollback for MySQL in PHP?

Well basically I have this script that takes a long time to execute and occasionally times out and leaves semi-complete data floating around my database. (Yes I know in a perfect world I would fix THAT instead of implementing commits and rollbacks but I am forced to not do that)
Here is my basic code (dumbed down for simplicity):
$database = new PDO("mysql:host=host;dbname=mysql_db","username","password");
while (notDone())
{
$add_row = $database->prepare("INSERT INTO table (columns) VALUES (?)");
$add_row->execute(array('values'));
//PROCESSING STUFF THAT TAKES A LONG TIME GOES HERE
}
$database = null;
So my problem is that if that if the entire process within that while loop isn't complete then I don't want the row inserted to remain there. I think that somehow I could use commits/rollbacks at the beginning and end of the while loop to do this but don't know how.
Take a look at this tutorial on transactions with PDO.
Basically wrap the long running code in:
$dbh->beginTransaction();
...
$dbh->commit();
And according to this PDO document page:
"When the script ends or when a connection is about to be closed, if you have an outstanding transaction, PDO will automatically roll it back. "
So you will lose the transaction that was pending when the script timed out.
But really, you ought to redesign this so that it doesn't depend on the scriipt staying alive.
You need to use InnoDB based tables for transactions then use any library like PDO or MySQLi that supports them.
try
{
$mysqli->autocommit(FALSE);
$mysqli->query("insert into tblbook (id,cid,book) values('','3','book3.1')");
echo $q_ins=$mysqli->affected_rows."<br>";
$mysqli->query("update tblbook set book='book3' where cid='3'");
echo $q_upd=$mysqli->affected_rows."<br>";
$mysqli->commit();
}
catch(PDOException $e)
{
$mysqli->rollback();
echo $sql . '<br />' . $e->getMessage();
}
<?php
//This may help someone....This code commit the transactions
//only if both queries insert and update successfully runs
$mysqli=new mysqli("localhost","user_name","password","db_name");
if(mysqli_connect_errno())
{
echo "Connection failed: ".mysqli_connect_error();
}
else
{
$mysqli->autocommit(FALSE);
$mysqli->query("insert into tblbook (id,cid,book) values('','3','book3.1')");
echo $q_ins=$mysqli->affected_rows."<br>";
$mysqli->query("update tblbook set book='book3' where cid='3'");
echo $q_upd=$mysqli->affected_rows."<br>";
if($q_ins==1 && $q_upd==1)
{
$mysqli->commit();
echo "Commit<br>";
}
else
{
$mysqli->rollback();
echo "Rollback<br>";
}
}
?>

Categories