I'm updating a site from MySQL to MySQLi, using OOP.
For the most part things are going well, but this line is giving me divine trouble:
$pager_total = mysql_num_rows(mysql_query($MySQLctr,$MyDB));
I've tried
$pager_total = $MyDB->query($MySQLctr)->num_rows;
and
$pager_total = ($MyDB->query($MySQLctr))->num_rows;
and
$new_object = $MyDB->query($MySQLctr);
$pager_total = $new_object->num_rows;
but no avail.
Any thoughts?
OOP mysqli is very simple :) try this example
$DBH=new mysql('location of database','username','password','database');
$get=$DBH->prepare('SELECT COUNT(*) FROM table');//notice the count(*) in the query, it's not the same as mysql_num_row() but works in the same way
//prepare is also a more secure way of processing query, please look up the difference between prepare and query though.
//$DBH->prepare('SELECT * FROM table WHERE ID=2'); will not work.
$get->execute();//execute the above prepared statement
$get->bind_result($count);//get the result of the query, should be whatever COUNT(*) returns
$get->close();//don't forget to close your connection
The mysqli of mysql_num_row() is $query->num_rows().
I added a little bit extra to get you started with OOP mysqli :)
Notice though that I didn't use $get->num_rows() but COUNT(*) instead for a more simple example. Here is another method you may be more familiar with:
$counter=$DBH->query('SELECT * FROM table');
echo$counter->num_rows();
Also see here for more examples.
Thank you for your help everyone. It turns out that the db connection was being closed prematurely by one of the included files. I've noticed, during this project where I'm transitioning the code from procedural MySql to OOP MySQLi that the db closures didn't affect the functionality of the site before, but definitely do once OOP MySqli is in place. I'm curious why.
Related
In my php.Mysql ($sql) result should be 1.Sysum should not be empty in another word, mysql_num_rows($sel) > 0 should be true.
But actually,mycode can not work.I don't know why.Who can help me?
$conn = new PDO('mysql:host=localhost;port=3306;dbname=hpc' , 'root' , 'Yd');
$Name=$_COOKIE['PName'];
$sql = "select sysnum from hpc where handler='".$Name."' and stat='N';";
$sel=$conn->query($sql);
if(mysql_num_rows($sel) > 0)
{
mycode;
}
Oh boy that went quite fast with your comment, even before mine :P
So, the answer is simple: You can't use mysql_num_rows on a PDO connection. That are two different drivers. Thats like you try to start the car of your wife with your own keys. Principally, both are keys, but they don't work with any car.
Its the same here in your case. mysql_num_rows comes from the OUTDATED mysql driver. (Don't use mysql_* at all, its not longer supported in PHP7 and deprecated). To do it with PDO is the right way, but you have to adapt your code a bit.
$Name=$_COOKIE['PName'];
$sql = "select count(sysnum) from hpc where handler='".$Name."' and stat='N';";
$sel=$conn->query($sql);
$rows = $sel->rowCount();
echo $rows;
Hope that work, if not, let me know. I know I had some troubles the last time I tried to do a rowCount with PDO.
IMPORTANT - DANGER:
Also I really recommend you to take a look at http://bobby-tables.com and learn something about SQL injection. Your code actually is not save at all and your database can be hacked quite easy. Since you're using PDO, nothing stops you from using prepared statements, what would make your code much better.
Hope I could help you. If you have any other questions or something shouldn't work, please let me know.
fetch result into an array and count items using count function, like this:
$Name=$_COOKIE['PName'];
$sql = "select sysnum from hpc where handler='".$Name."' and stat='N';";
$sel = $conn->query($sql)->fetchall();
if(count($sel) > 0){
mycode;
}
So, I'm working with PHP and prepared statements sent to a MySQL database. I've ran into a problem that I can't quite debug. Here is my code:
// Check if the input username is in the database
$stmtQuery = "SELECT * FROM updatedplayers WHERE Player=?;";
$preparedStmt = $dbc->prepare($stmtQuery);
$preparedStmt->bind_param("s", $setUsername);
$preparedStmt->execute();
$preparedStmt->bind_result($resultUUID, $resultUsername);
$preparedStmt->fetch();
// If it's not, kill the page.
if ($resultUUID == null) {
incorrect();
}
$stmtQuery = "SELECT Password, Salt FROM logins WHERE UUID=?;";
echo 'flag1 ';
$preparedStmt = $dbc->prepare($stmtQuery);
echo 'flag2 ';
$preparedStmt->bind_param("s", $resultUUID);
echo 'flag3 ';
The fist prepared statement works fine, it's at the line $preparedStmt->bind_param("s", $resultUUID);. There are also a couple other prepared statements before these, so I know I'm doing this correctly, but I'm not too sure about the last statement.
The code just seems to stop running after echo 'flag2 ';, which I put there to find the specific line. I don't get any error messages, it just doesn't print out flag3.
I've tried replacing $resultUUID with a static string, yet I get the same outcome. Also, I know my SQL statement is correctly formatted, I've tested within the console manually.
That's pretty much it, I'd love to hear some criticism, as I am new to PHP. Also, is there any way to get a better idea about the errors I get, instead of trying to pinpoint the error myself? Thanks!
So, adding ini_set('display_error', 1);, suggested by #user2182349, gave me a little more insight, I got "Fatal error: Call to a member function bind_param() on boolean".
After some research, I tried adding mysqli_report(MYSQLI_REPORT_ALL);, which ended up throwing "No index used in query/prepared statement".
I did some research on that to realize that it wasn't a problem, just MySQLI reporting unnecessary errors (which is what I asked it to do lol). In order to get a better, more insightful stack trace, I used mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);.
This threw "Commands out of sync; you can't run this command now". Again, more research taught me to use $preparedStmt->store_result();, in order to allow for another prepared statement to run.
Big thanks to all y'alls' help, hope this can help someone too.
You should be able to use a single select statement similar to this:
SELECT u.UUID, u.Username, l.Password, l.Salt
FROM updatedplayers AS u
JOIN logins AS l ON (u.UUID = l.UUID)
WHERE u.Player = ?
Check the case of the field names to be sure they match the database.
At the top of the file, add ini_set('display_errors',1);. If you have any PHP errors, they will be displayed. Also check the return values from the database calls and use the error display functions.
I think you need to close the prepared statement before you use the variable for another query:
$preparedStmt->close();
Or use another variable name like $preparedStmt2 for the second query.
I would suggest you should start using PDO... I have issues encountered with mysqli prepared statement years ago. Since then, PDO gives me no headaches when it comes to multiple queries at a time.
You should try PDO.. :-) it's more efficient.
http://php.net/manual/en/intro.pdo.php
http://php.net/manual/en/class.pdostatement.php
Or you can do the following "if you want alternative solution"..
//Close connection
$preparedStmt->close();
//AND OPEN YOUR CONNECTION AGAIN TO PREPARE NEW QUERIES..
$stmtQuery = "SELECT Password, Salt FROM logins WHERE UUID=?;";
echo 'flag1 ';
$preparedStmt = $dbc->prepare($stmtQuery);
echo 'flag2 ';
$preparedStmt->bind_param("s", $resultUUID);
echo 'flag3 ';
This question already has answers here:
Getting raw SQL query string from PDO prepared statements
(16 answers)
Closed 6 years ago.
In PHP, when accessing MySQL database with PDO with parametrized query, how can you check the final query (after having replaced all tokens)?
Is there a way to check what gets really executed by the database?
So I think I'll finally answer my own question in order to have a full solution for the record. But have to thank Ben James and Kailash Badu which provided the clues for this.
Short Answer
As mentioned by Ben James: NO.
The full SQL query does not exist on the PHP side, because the query-with-tokens and the parameters are sent separately to the database.
Only on the database side the full query exists.
Even trying to create a function to replace tokens on the PHP side would not guarantee the replacement process is the same as the SQL one (tricky stuff like token-type, bindValue vs bindParam, ...)
Workaround
This is where I elaborate on Kailash Badu's answer.
By logging all SQL queries, we can see what is really run on the server.
With mySQL, this can be done by updating the my.cnf (or my.ini in my case with Wamp server), and adding a line like:
log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]
Just do not run this in production!!!
You might be able to use PDOStatement->debugDumpParams. See the PHP documentation .
Using prepared statements with parametrised values is not simply another way to dynamically create a string of SQL. You create a prepared statement at the database, and then send the parameter values alone.
So what is probably sent to the database will be a PREPARE ..., then SET ... and finally EXECUTE ....
You won't be able to get some SQL string like SELECT * FROM ..., even if it would produce equivalent results, because no such query was ever actually sent to the database.
I check Query Log to see the exact query that was executed as prepared statement.
I initially avoided turning on logging to monitor PDO because I thought that it would be a hassle but it is not hard at all. You don't need to reboot MySQL (after 5.1.9):
Execute this SQL in phpMyAdmin or any other environment where you may have high db privileges:
SET GLOBAL general_log = 'ON';
In a terminal, tail your log file. Mine was here:
>sudo tail -f /usr/local/mysql/data/myMacComputerName.log
You can search for your mysql files with this terminal command:
>ps auxww|grep [m]ysqld
I found that PDO escapes everything, so you can't write
$dynamicField = 'userName';
$sql = "SELECT * FROM `example` WHERE `:field` = :value";
$this->statement = $this->db->prepare($sql);
$this->statement->bindValue(':field', $dynamicField);
$this->statement->bindValue(':value', 'mick');
$this->statement->execute();
Because it creates:
SELECT * FROM `example` WHERE `'userName'` = 'mick' ;
Which did not create an error, just an empty result. Instead I needed to use
$sql = "SELECT * FROM `example` WHERE `$dynamicField` = :value";
to get
SELECT * FROM `example` WHERE `userName` = 'mick' ;
When you are done execute:
SET GLOBAL general_log = 'OFF';
or else your logs will get huge.
What I did to print that actual query is a bit complicated but it works :)
In method that assigns variables to my statement I have another variable that looks a bit like this:
$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\\'', $param) . '\'', $this->fullStmt);
Where:
$column is my token
$param is the actual value being assigned to token
$this->fullStmt is my print only statement with replaced tokens
What it does is a simply replace tokens with values when the real PDO assignment happens.
I hope I did not confuse you and at least pointed you in right direction.
The easiest way it can be done is by reading mysql execution log file and you can do that in runtime.
There is a nice explanation here:
How to show the last queries executed on MySQL?
I don't believe you can, though I hope that someone will prove me wrong.
I know you can print the query and its toString method will show you the sql without the replacements. That can be handy if you're building complex query strings, but it doesn't give you the full query with values.
I think easiest way to see final query text when you use pdo is to make special error and look error message. I don't know how to do that, but when i make sql error in yii framework that use pdo i could see query text
I have used mysql_query() throughout my project; but I've just learned that mysql_ was deprecated as of PHP 5.5, has been removed in PHP 7.
So, I would like to know if I can replace all mysql_ functions with mysqli_ in my project blindly? For example, just replacing mysql_query() with mysqli_query(). Is there any adverse effect?
The short answer is no, the functions are not equivalent.
The good news is there is a converter tool that will help you if you've got a lot of calls/projects to change. This will allow your scripts to work right away.
https://github.com/philip/MySQLConverterTool
It's a forked version of the Oracle original version, and it's kosher.
That said, it's not too difficult to update your code, and you might want to migrate to an object orientated methodology anyway ...
1) The Connection
For all intents and purposes, you need a new connection function that saves the connection as a PHP variable, for example;
$mysqli = new mysqli($host, $username, $password, $database);
Notice I've saved the connection to $mysqli. You can save to $db or whatever you like, but you should use this throughout your code to reference the connection.
Remember to enable error reporting for mysqli before opening the connection;
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
2) The Query
Note: You should protect against SQL injection with prepared statements, which are available in MySQLi. Take a look at How can I prevent SQL injection in PHP?, but I'm just going to cover the basics here.
You now have to include the connection as an argument in your query, and other mysqli_ functions. In procedural code it's the first argument, in OO you write it like a class method.
Procedural:
$result = mysqli_query($mysqli, $sql);
OO:
$result = $mysqli->query($sql);
3) Fetch Result
The fetching of the result is similar to the old mysql_ function in procedural;
while ($row = mysqli_fetch_assoc($result))
but as $result is now an object in mysqli, you can use the object function call;
while ($row = $result->fetch_assoc())
4) Close Connection
So as before, you need to include the connection in the close function; as an argument in procedural;
mysqli_close($mysqli);
and as the object that you run the function on in OO;
$mysqli->close();
I would be here forever if I went through them all, but you get the idea. Take a look at the documentation for more information. Don't forget to convert any connection close, result release, or error and row counting functions you have.
The basic rule of thumb is for functions that use the database connection, you need to include it in the function now (either as the first argument in procedural, or the object you use to call the function in OO), or for a result set you can just change the function to mysqli_ or use the result set as the object.
If you cannot convert all calls to the mysqli functions on a old project, you could install and include the library php7-mysql-shim.
It will try to create a transparent replacement for mysql on PHP 7 using mysqli.
Obviously the performance is slower, but it's a solution to get around the problem in a couple of minutes.
You may safely include the library in projects working with PHP 5.6 (it will be ignored).
if (defined('PHP_VERSION_ID') && (PHP_VERSION_ID >= 50600)) { require_once "mysql-shim.php"; }
You can't. some of the functions of mysql and mysqli require different parameters. So you should know which will use the same parameters.
This question already has answers here:
Getting raw SQL query string from PDO prepared statements
(16 answers)
Closed 6 years ago.
In PHP, when accessing MySQL database with PDO with parametrized query, how can you check the final query (after having replaced all tokens)?
Is there a way to check what gets really executed by the database?
So I think I'll finally answer my own question in order to have a full solution for the record. But have to thank Ben James and Kailash Badu which provided the clues for this.
Short Answer
As mentioned by Ben James: NO.
The full SQL query does not exist on the PHP side, because the query-with-tokens and the parameters are sent separately to the database.
Only on the database side the full query exists.
Even trying to create a function to replace tokens on the PHP side would not guarantee the replacement process is the same as the SQL one (tricky stuff like token-type, bindValue vs bindParam, ...)
Workaround
This is where I elaborate on Kailash Badu's answer.
By logging all SQL queries, we can see what is really run on the server.
With mySQL, this can be done by updating the my.cnf (or my.ini in my case with Wamp server), and adding a line like:
log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]
Just do not run this in production!!!
You might be able to use PDOStatement->debugDumpParams. See the PHP documentation .
Using prepared statements with parametrised values is not simply another way to dynamically create a string of SQL. You create a prepared statement at the database, and then send the parameter values alone.
So what is probably sent to the database will be a PREPARE ..., then SET ... and finally EXECUTE ....
You won't be able to get some SQL string like SELECT * FROM ..., even if it would produce equivalent results, because no such query was ever actually sent to the database.
I check Query Log to see the exact query that was executed as prepared statement.
I initially avoided turning on logging to monitor PDO because I thought that it would be a hassle but it is not hard at all. You don't need to reboot MySQL (after 5.1.9):
Execute this SQL in phpMyAdmin or any other environment where you may have high db privileges:
SET GLOBAL general_log = 'ON';
In a terminal, tail your log file. Mine was here:
>sudo tail -f /usr/local/mysql/data/myMacComputerName.log
You can search for your mysql files with this terminal command:
>ps auxww|grep [m]ysqld
I found that PDO escapes everything, so you can't write
$dynamicField = 'userName';
$sql = "SELECT * FROM `example` WHERE `:field` = :value";
$this->statement = $this->db->prepare($sql);
$this->statement->bindValue(':field', $dynamicField);
$this->statement->bindValue(':value', 'mick');
$this->statement->execute();
Because it creates:
SELECT * FROM `example` WHERE `'userName'` = 'mick' ;
Which did not create an error, just an empty result. Instead I needed to use
$sql = "SELECT * FROM `example` WHERE `$dynamicField` = :value";
to get
SELECT * FROM `example` WHERE `userName` = 'mick' ;
When you are done execute:
SET GLOBAL general_log = 'OFF';
or else your logs will get huge.
What I did to print that actual query is a bit complicated but it works :)
In method that assigns variables to my statement I have another variable that looks a bit like this:
$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\\'', $param) . '\'', $this->fullStmt);
Where:
$column is my token
$param is the actual value being assigned to token
$this->fullStmt is my print only statement with replaced tokens
What it does is a simply replace tokens with values when the real PDO assignment happens.
I hope I did not confuse you and at least pointed you in right direction.
The easiest way it can be done is by reading mysql execution log file and you can do that in runtime.
There is a nice explanation here:
How to show the last queries executed on MySQL?
I don't believe you can, though I hope that someone will prove me wrong.
I know you can print the query and its toString method will show you the sql without the replacements. That can be handy if you're building complex query strings, but it doesn't give you the full query with values.
I think easiest way to see final query text when you use pdo is to make special error and look error message. I don't know how to do that, but when i make sql error in yii framework that use pdo i could see query text