MYSQLI not playing nice with INSERT - mysql

So excuse the coding if it's not totally up to par, but I just got a hang of MYSQL and am switching to MYSQLI (procedural as I find it easier as I haven't learned object oriented yet, i'm new to this)
My problem is I have a simple 'Invoice' page on a small website that worked perfectly with MYSQL. When I switched to MYSQLI (I'm sure I am missing something obvious) I can echo all the variables, have checked for proper DB connection yet it will not INSERT anything into the DB.
This is the function in question, it is called after a "fill invoice" form is submitted, again, all the $_POST variables can be echoed in the function properly.
function createinvoice($billto,$cust,$addr,$desc,$desccost,$labcost,$comment){
$taxrate=".13";
$kaboom=str_replace(array("\r\n","\r","\n"),"<br />",$desccost); //keep original desccost for database
$kaboom=mysqli_real_escape_string(nl2br($kaboom));
$kaboom=nl2br($kaboom);
$lines=explode("<br />",$kaboom);
$matcost=0;
for($i=0;$i < count($lines);$i++)
{
$matcost=$matcost+$lines[$i];
}
$fullcost=$matcost+$labcost;
$taxdue = $fullcost*$taxrate;
$totaldue=$fullcost+$taxdue;
$desc=mysqli_real_escape_string($desc);
mysqli_query($con,"INSERT INTO invoice(customerID,customerName,customerAddr,description,desccost,material,labour,taxdue,totaldue,comment)
VALUES('$billto','$cust','$addr','$desc','$desccost','$matcost','$labcost','$taxdue','$totaldue','$comment')");
mysqli_free_result($result);
mysqli_close($con);
}
Edit: to show connection string
if(include("/../dbinvoice.php")){echo "DB file connected";}
$con = mysqli_connect($dbhostname, $dbuser, $dbpass, $dbname);
if (mysqli_connect_errno($con)){echo "No MYSQL connection: ".mysqli_connect_error();exit();}
Every time the page loads I get a message "DB file connected" showing it read the dbinvoice.php file and I don't get an error message with connect. I have verified with phpinfo() that mysqli is on my machine (webmatrix testing).

Related

Use same mysqli prepared statement for different queries?

Throughout some testings; a little question popped up. When I usually code database updates; I usually do this via callbacks which I code in PHP; to which I simply pass a given mysqli connection object as function argument. Executing all queries of for example three queries across the same single connection proved to be much faster than if closing and reopening a DB connection for each query of a given query sequence. This also works easily with SQL transactions, the connection can be passed along to callbacks without any issues.
My question is; can you also do this with prepared statement objects ? What I mean is, considering we successfully established a $conn object, representing the mysqli connection, is stuff like this legit? :
function select_users( $users_id, $stmt ) {
$sql = "SELECT username FROM users where ID = ?";
mysqli_stmt_prepare( $stmt, $sql );
mysqli_stmt_bind_param( $stmt, "i", $users_id );
mysqli_stmt_execute( $stmt );
return mysqli_stmt_get_result( $stmt );
}
function select_labels( $artist, $stmt ) {
$sql = "SELECT label FROM labels where artist = ?";
mysqli_stmt_prepare( $stmt, $sql );
mysqli_stmt_bind_param( $stmt, "s", $artist );
mysqli_stmt_execute( $stmt );
return mysqli_stmt_get_result( $stmt );
}
$stmt = mysqli_stmt_init( $conn );
$users = select_users( 1, $stmt );
$rappers = select_labels( "rapperxyz", $stmt );
or is it bad practice; and you should rather use:
$stmt_users = mysqli_stmt_init( $conn );
$stmt_rappers = mysqli_stmt_init( $conn );
$users = select_users( 1, $stmt_users );
$rappers = select_labels( "rapperxyz", $stmt_rappers );
During the testing; I noticed that the method by using a single statement object passed along callbacks works for server calls where I call like 4 not too complicated DB queries via the 4 according callbacks in a row.
When I however do a server call with like 10 different queries, sometimes (yes, only sometimes; for pretty much the same data used across the different executions; so this seems to be weird behavior to me) I get the error "Commands out of sync; you can't run this command now" and some other weird errors I've never experienced, like the amount of variables not matching the amount of parameters; although they prefectly do after checking them all. The only way to fix this I found after some research was indeed by using different statement objects for each callback. So, I just wondered; should you actually ALWAYS use ONE prepared statement object for ONE query, which you then may execute N times in a row?
Yes.
The "commands out of sync" error is because MySQL protocol is not like http. You can't send requests any time you want. There is state on the server-side (i.e. mysqld) that is expecting a certain sequence of requests. This is what's known as a stateful protocol.
Compare with a protocol like ftp. You can do an ls in an ftp client, but the list of files you get back depends on the current working directory. If you were sharing that ftp client connection among multiple functions in your app, you don't know that another function hasn't changed the working directory. So you can't be sure the file list you get from ls represents the directory you thought you were in.
In MySQL too, there's state on the server-side. You can only have one transaction open at a time. You can only have one query executing at a time. The MySQL client does not allow you to execute a new query where there are still rows to be fetched from an in-progress query. See Commands out of sync in the MySQL doc on common errors.
So if you pass your statement handle around to some callback functions, how can that function know it's safe to execute the statement?
IMO, the only safe way to use a statement is to use it immediately.

Connecting to a MySQL database using DBI

I am trying to connect to a MySQL database.
I found this script and I am trying to use it on my PC and web host, but it doesn't show any output.
Please have a look at this code. I am running perl at xampp.
#!C:\xampp\perl\bin\perl.exe
print "Content-type: text/html\n\n";
use DBI;
use strict;
my $driver = "localhost";
my $database = "data";
my $dsn = "DBI:$driver:database = $database";
my $userid = "root";
my $password = "";
my $dbh = DBI->connect($dsn, $userid, $password ) or die $DBI::errstr;
I am using the same database with PHP.
but it doesn't show any output.
Judging by the CGI header you're displaying, I assume that you're running this as a CGI program. In which case, it's no surprised that you're not seeing any output - you're not sending any output.
If you ran it as a command line program (and it's often a good idea to get stuff working on the command line before leaping into CGI programming), then you would see the "Content-Type" header. Alternatively, you could add some output to your program and see if that appears in your browser. Something simple like:
print 'It works!';
I'd also like to add, that CGI looks rather outdated these days and there are far better (by which I mean easier and more powerful) ways to write web applications with Perl. You might like to read CGI::Alternatives to get an idea of what is available.
Update:
I've just seen this question asked on Facebook (please don't cross-post without telling people) and I've noticed that your $driver variable is wrong. If you're connecting to MySQL, then $driver should be "mysql" (so that DBI loads "DBD::mysql").
A DSN for the MySQL driver looks like this
DBI:mysql:database=$database;host=$hostname;port=$port
where the host and port fields are optional. (The database is also optional, but you don't want to leave that out.) There are several more esoteric options too, but they're irrelevant here
But you're supplying
DBI:localhost:database = data
Which doesn't even specify a MySQL connection, so I'm not surprised if it doesn't work! I don't know whether the spaces are legal, but I would leave them out to keep in line with the documentation.
You should change that statement to
my $dsn = "DBI:mysql:database=$database;host=$driver"
You may remove ;host=$driver if you wish (why have you called the host name "driver"?) as localhost is the default. A DSN that specifies just a database name and uses the default for all the other fields may be contracted to just
my $dsn = "DBI:mysql:$database"
It may be easier to just write print statements at first to generate some output. You will want to print a MIME content type header of text/plain instead of text/html. Try print "$DBI::errstr\n" for now instead of die, as the latter writes to stderr which won't appear in your browser
you could add:
if ($dbh) {
print 'connect ok';
} else {
print 'connect failed';
}

Warning: mysql_num_rows() But only on webhost, not localhost

On localhost this works great. But when I upload files to server I get this error:
Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /storage/content/04/13fd39104/xxxxx.com/public_html/users/list.php on line 54
My code is:
//load users from database
$users = mysql_query("SELECT id,username FROM ".$sql_table_users." WHERE id!='".$_SESSION['user_id']."'");
if(mysql_num_rows($users) > 0){
while($user = mysql_fetch_assoc($users)){
//ALT tag contains user ID and user name
print '• '.$user['username'].'<br />';
}
}
Are you sure to have the same db strutture on server? Probably some column or table name are different from localhost. Check also if your db connection credentials are correct
Perhaps your database on server is not the same as your localhost.
add echo mysql_error(); after mysql_query to see details.
I would echo the query string before performing the query to see if it really is the string you think it should be. Most likely one of the variables is not defined so the query is failing. If that doesn't help you could also output any mysql errors after the query.
And of course, the obligatory suggestion to get off of the deprecated mysql_* functions! If you don't want to do PDO, check out mysqli and how very similar it is to the mysql functions if you use the procedural functions.

Efficient way to connect to a database when multiple functions are running queries

I'm writing an application that has a functions.php file that a javascript file is accessing via Ajax. Currently I have each function connecting to the database, running queries, then closing the database. I know there has to be a more efficient way of doing this. I'd like to only input the database credentials once and then have all the functions use it. Whats the most efficient way to do this? I've read quite a few of the answers here on this topic but they're all different and I'm lost. Just point me in the right direction :)
Currently my functions are opening the database like this.
$db = new mysqli("hostname", "username", "password");
$db -> select_db("database name");
Or like this
mysql_connect("hostname", "username", "password");
mysql_select_db('database name') or die( "Unable to select database");
The simple answer is connection pooling. A connection pool is a pool of connections that are always connected to the database. You can set a high water mark and a low water mark for the number of connections.
When your application requests a connection from the pool it will then use one of the idle connections and reuse it. This is how you scale database connectivity.
You are using PHP so look at the following:
http://www.oracle.com/technetwork/topics/php/php-scalability-ha-twp-128842.pdf
http://php.net/manual/en/mysqlnd-ms.pooling.php
There is a lot of information around this on the net.
You can just check whether the database connection variable is already set:
if (!isset($db)) {
$db = new mysqli(...);
$db->select_db("database_name");
}
and similarly with mysql_connect (it returns a connection resource, so you can assign it to a variable, even though it's an optional argument to the other functions).
Another way is to use a function with a static variable:
function connect_db() {
static $db = new mysqli(...);
static $selected = $db->select_db("database_name");
return $db;
}
A third options is to connect to the database once at the beginning of the script, instead of in each function. Then either pass $db to each function, or access it with global $db;.

MySQL connection reuse problem

I am trying to reuse mysql connection. Hence I have a global variable in databasemanager.php class that returns a connection.
The problem is somehow on one particular page mysql is executing prior query as well.
Looks like there is some leftover query in connection object that gets executed if same connection is being reused . Is it possible ? how to solve this ..
function getDBConnection(){
global $conn;
if (!empty($conn)){
// echo $conn ;
return $conn;
}
$conn = mysql_connect($GLOBALS['HOSTNAME'],$GLOBALS['DBUSER'],$GLOBALS['DBPASS']);
if (!$conn) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db($GLOBALS['DBNAME'],$conn);
return $conn;
}
This how code lookslike
Have you looked into mysql_pconnect?
According to the documentation:
mysql_pconnect() acts very much like
mysql_connect() with two major
differences.
First, when connecting, the function
would first try to find a (persistent)
link that's already open with the same
host, username and password. If one is
found, an identifier for it will be
returned instead of opening a new
connection.
Second, the connection to the SQL
server will not be closed when the
execution of the script ends. Instead,
the link will remain open for future
use (mysql_close() will not close
links established by
mysql_pconnect()).