Trouble using a reusable database connector - php

I'm new to php. I've been having trouble connecting to and using a data with PHP. I don't really have much information on the issue, maybe I'm using some out of date method, or I did something wrong. I've double checked and looked on this website for information, but I didn't find much. Here's the code below.
The error reads :
Fatal error: Call to a member function query() on boolean in C:\xampp\htdocs\website\Practice\mysqli\pdo.php on line 6
That would mean that there is a problem located near the
$result = $conn->query($sql)or die(mysqli_error());
I entered my username and password correctly. I even created a new username and password just to make sure. I have no other ideas why $conn isn't working, and I would love any thoughts or ideas on the issue!
connection.ini.php
function dbConnect($usertype, $connectiontype = 'pdo') {
$host = 'localhost';
$db = 'student';
if ($usertype == 'read') {
$user = 'user';
$pwd = 'pass';
}
elseif ($usertype == 'write') {
$user = 'root';
$pwd = 'password';
}
else {
exit('Unrecognized connection type');
}
//Connection Code
if ($connectionType ='mysqli') {
return new mysqli($host, $user, $pwd, $db) or die ('Cannot open database');
}
else {
try {
return new PDO('mysql:host=$host;dbname=$db, $user, $pwd');
}
catch(PDOExecption $e) {
echo 'Cannot connect to database';
exit;
}
}
}
?>
mysqli.php
?php
require_once('connection.inc.php');
$conn = dbConnect('read', 'pdo');
$sql = 'SELECT * FROM guestbook';
$result = $conn->query($sql)or die(mysqli_error());
$numRows = $result->num_rows;
?>
<!DOCTYPE html>
<html>
<p> A total of <?php
echo $numRows;
?>
records were found.</p>
</html>

Any time you get the...
"Fatal error: Call to a member function bind_param() on boolean"
...it is likely because there is an issue with your query. The prepare() might return FALSE (a Boolean), but this generic failure message doesn't leave you much in the way of clues. How do you find out what is wrong with your query? You ask!
First of all, make sure error reporting is turned on and visible: add these two lines to the top of your file(s) right after your opening <?php tag:
error_reporting(E_ALL);
ini_set('display_errors', 1);
If your error reporting has been set in the php.ini you won't have to worry about this. Just make sure you handle errors gracefully and never reveal the true cause of any issues to your users. Revealing the true cause to the public can be a gold engraved invitation for those wanting to harm your sites and servers. If you do not want to send errors to the browser you can always monitor your web server error logs. Log locations will vary from server to server e.g., on Ubuntu the error log is typically located at /var/log/apache2/error.log. If you're examining error logs in a Linux environment you can use tail -f /path/to/log in a console window to see errors as they occur in real-time....or as you make them.
Once you're squared away on standard error reporting adding error checking on your database connection and queries will give you much more detail about the problems going on. Have a look at this example where the column name is incorrect. First, the code which returns the generic fatal error message:
$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?";
$query = $mysqli->prepare($sql)); // assuming $mysqli is the connection
$query->bind_param('s', $definition);
$query->execute();
The error is generic and not very helpful to you in solving what is going on.
With a couple of more lines of code you can get very detailed information which you can use to solve the issue immediately. Check the prepare() statement for truthiness and if it is good you can proceed on to binding and executing.
$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?";
if($query = $mysqli->prepare($sql)) { // assuming $mysqli is the connection
$query->bind_param('s', $definition);
$query->execute();
// any additional code you need would go here.
} else {
$error = $mysqli->errno . ' ' . $mysqli->error;
echo $error; // 1054 Unknown column 'foo' in 'field list'
}
If something is wrong you can spit out an error message which takes you directly to the issue. In this case there is no foo column in the table, solving the problem is trivial.
If you choose, you can include this checking in a function or class and extend it by handling the errors gracefully as mentioned previously.

Related

How to display error and load the rest of the page if database-related content is optional?

My .php includes quote.php followed with the rest of the page.
When the connection fails, I see "Fatal error: Uncaught mysqli_sql_exception: ----- include_once('C:\xampp\htdocs...') ----
and the remainder of the page does not load.
What must I do to display an error message, THEN the rest of my page?
Your situation is a rare case when using a try catch is justified.
All you need to do it wrap the include in a try-catch:
try {
require 'quote.php';
} catch(\Throwable $e) {
error_log($e); // for the future inspection
echo "Problem loading this part of page";
}
That's all. The error message will be shown and the rest of the page will be loaded.
But of course this approach should only be used when the content from quote.php is optional. In the every other case there must be no local try-catch but a site-wide error handler.
php / msqli is throwing exceptions. You need to write exception handler code (try { } catch (mysqli_sql_exception $e) { } code in your program to handle errors.
As a quick and sleazy workaroud for the current state of your code you can put this line of code at the top of your page. give this line of code
mysqli_report(MYSQLI_REPORT_OFF):;
This will suppress php exceptions and warnings, and let you rely completely on mysqli_connect_errno() to catch your errors.
Using #O. Jones idea and some nasty GoTO's, this does the job. The warnings and error are still displayed. The rest of the page is able to load now.
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$dbServer = "localhost";
$dbUsername = "root";
$dbPassword = "";
$dbName = "project_01";
$conn = mysqli_connect($dbServer, $dbUsername, $dbPassword, $dbName);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to the MySQL Database: ";
goto end;
}
$sql = "SELECT * FROM tbl_quotes";
if ($result=mysqli_query($conn,$sql))
{
// Return the number of rows in result set
$rowcount=mysqli_num_rows($result);
$rand = random_int(1,$rowcount);
} else {
echo "No records were found";
goto end;
}
$sql = "SELECT quote, credit FROM tbl_quotes where ID = $rand";
if ($result = mysqli_query($conn, $sql)) {
// Fetch one and one row
while ($row = mysqli_fetch_row($result)) {
printf ("%s" . " - " . "(%s)\n", $row[0], $row[1]);
}
// Free result set
mysqli_free_result($result);
}
end:
?>
Thanks to all who looked.

HTTP Error 500 when trying to execucute INSERT INTO sql query

I'm fairly new to php and SQL and just can't figure out the problem. Note that this is a school project, therefore the vulnerability to SQL Injections and saving the blank passwords are nothing to worry about.
After the User filled out the Login-form, he's redirected to this page:
[Some html]
<?php
if(isset($_POST['submit']))
{
ConnectSQL();
}
//Retrieve POSTed Login information
$Username = htmlspecialchars($_POST['RegUsername']);
$Email = htmlspecialchars($_POST['RegEmail']);
$Password = htmlspecialchars($_POST['RegPassword']);
function ConnectSQL() {
// SQL Server Extension Sample Code:
// (ConnectionInfo, obviously it's there in the real file)
$conn = sqlsrv_connect($serverName, $connectionInfo);
// PHP Data Objects(PDO) Sample Code:
try {
$conn = new PDO('sqlsrv:server = tcp:xxx.database.windows.net,1433; Database = userdb', 'arechon', '{NotTheRealPassword}');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Successfully connected to SQL Server and DB";
Register();
}
catch (PDOException $e) {
print('Error connecting to SQL Server.');
die(print_r($e));
}
}
function Register($Username, $Email, $Password) {
$regquery = "INSERT INTO dbo.Users (Username, Email, Password) VALUES ('UsernameTest', 'EmailTest', 'PasswordTest')";
$conn->query($regquery);
echo '<script type="text/javascript">window.open("http://xxx.azurewebsites.net/Login.html", "_self");</script>';
The Code always seems to stop at $conn->query($regquery); and doesn't return any error messages. Sometimes it just stops, when I slightly modify the Code (e.g. replacing $conn->query($regquery); with $conn->exec($regquery); or using " instead of ') I get a HTTP500 error.
I found some similiar questions here on stackoverflow as well as on other plattforms, but none of the provided answers could solve this error. Note that I use SQL and NOT MySQL (though it wouldn't be a lot of work to change that if you think that could solve my problem).

try/catch in php not printing anything out

Hey Everyone it has been awhile wince I've worked with try/catch blocks but I would like to start using them again just for purpose of error handling and proper practices. My code is below,
$email_code = $_REQUEST['code']; //retrive the code from the user clicked link in the email
//database information
$dsn = 'mysql:host=localhost;dbname=primarydb';
$username = 'root';
$password = '';
try {
//option for PDO allows for prepared SQL statements that will mazimize the prevention of sql injections and malicious attacks on the server and databases
$conn = new PDO($dsn, $username, $password); //establish the connection
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //disable the php parse from parsing the statements.
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //allow error mode to be active in order to display any errors which may open up holes to attacks
//if the connection fails the try/catch block will pick it up
if (!$conn) {
throw new PDOException('Fatal error on connection');
} else {
//prepare and exexcute the query to match the codes up
$stmt = $conn->prepare("SELECT email_code, active from primarydb.user WHERE email_code = ?");
$stmt->bindParam(1, $email_code, PDO::PARAM_STR, 32);
//check to make sure that the statment executes properly
if (!$stmt->execute()){
throw new PDOException("PDO ERROR ON EXECUTION:\n" . $stmt->errorInfo());
} else { //statement has not failed
//get the row count
$count = $stmt->rowCount();
//traverse the results
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
//there can only be one!
if ($count != 1 || $row['active'] != 0) {
//generate error message
throw new PDOException("Wrong Code");
} else {
echo "working";
//prepare the update statement
$stmt = $conn->prepare("UPDATE primarydb.user SET active = ? WHERE email_code = ?");
$stmt->brindParam(1, 1, PDO::PARAM_INT);
$stmt->bindParam(2, $email_code, PDO::PARAM_STR, 32);
if (!$stmt->execute()) {
throw new PDOException("We're sorry but we can not update your profile at this time, plesae try again later. If this problem persists please contact customer service.");
} else {
print "Your account has now been activated and it is ready to use!";
}
}
}
}
}
} catch(PDOException $e){
//display error message if the database has failed in some manner
echo $e->getMessage();
}
I would like to know why I am not getting any of the error messages, and then how do I fix this problem so that I can avoid making the same problems again in the future. If there is something that is missing or if more information is needed please let me know. Otherwise I think it is pretty straight forward.
ADDITIONAL INFO: I have putt a message that says working at each block of if/else and the one it finally stops showing up at is when I check if($count != 1 || $row['active'] != 0)
UPDATE
<?php
$email_code = $_REQUEST['code']; //retrive the code from the user clicked link in the email
//database information
$dsn = 'mysql:host=localhost;dbname=primarydb';
$username = 'root';
$password = '';
try{
//option for PDO allows for prepared SQL statements that will mazimize the prevention of sql injections and malicious attacks on the server and databases
$conn = new PDO($dsn, $username, $password); //establish the connection
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //disable the php parse from parsing the statements.
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //allow error mode to be active in order to display any errors which may open up holes to attacks
//prepare the update statement
$stmt = $conn->prepare("UPDATE primarydb.user SET active = ? WHERE email_code = ?");
$stmt->bindParam('is', $a = 1, $email_code);
if($stmt->execute()){
print "Your account has now been activated and it is ready to use!";
}
} catch(PDOException $e){
//display error message if the database has failed in some manner
echo $e->getMessage();
}
?>
Generated new code, I don't want to get off topic, but I would like a complete solution to this problem. I am now getting the following error
Strict Standards: Only variables should be passed by reference in C:\inetpub\wwwroot\mjsite\login\complete_registration.php on line 14
SQLSTATE[HY000]: General error: 2031
Thoughts?
Please read this first line from the PDOException documentation:
Represents an error raised by PDO. You should not throw a PDOException
from your own code.
Just throw and catch regular old Exceptions. This would also catch a PDOException which inherits from it.
This also gives you a much better way to distinguish between actual exception thrown by PDO and your own exceptions. By the way, it would seem you have a number of cases where you are redundantly throwing exception when PDO would have encountered an error and thrown an exception anyway. Only the first exception will be caught, so in many of those cases, your throw would never be executed.
Also why bother with the SELECT before the update at all? YOu are basically just wasting a query because you aren't doing anything with the selected information. Perhaps just go straigth for update and handle cases where email_code doesn't exist.

Fatal Error Call To a member Function query()

I've seen some of the previous posts on here but they really don't explain what it is I'm looking for. maybe someone can point me in the right direction.
All I'm doing is a simple select statement that works on some other pages but not this one.
at the top of my page, I have the connection to my db: include 'myDBconnection.php'; just like any other page that uses it.
I'm using these to tell me what errors I have:
ini_set('display_errors', 'On');
error_reporting(E_ALL);
and they are returning this:
"Fatal error: Call to a member function query() on a non-object in /var/www/vhosts/mydomainname.com/httpdocs/somedirectory/index.php on line 16"
So, this is my simple select statement that I'm trying to just display on the page:
<?php
//just a simple select statement
if($row = $con->query("SELECT * FROM ErrorCodeTable WHERE ErrorCodeID = 100"))//this is line 16 in my code
{
$eCodeId = $row['ErrorCodeID'];
$eCode = $row['ErrorCode'];
echo $eCodeId." = ".$eCode;
}
?>
So, I'm stumped. Why is it telling me that?
Just for clarity's sake, this is my DB connection and I'm reading from an INI file.
function getConnected()
{
$file = "../myConnection.ini";
if (!$settings = parse_ini_file($file, TRUE)) throw new exception('Unable to open ' . $file . '.');
$host = $settings['connection']['default_host'];
$user = $settings['connection']['default_user'];
$paass = $settings['connection']['default_pw'];
$dbName = $settings['connection']['default_db'];
$con = 'mysqli_connect("'.$host.'", "'.$user.'", "'.$paass.'", "'.$dbName.'")';
return $con;
}
//MYSQLI CONNECTION
$con = getConnected();
//CONNECTION CHECK
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
So, why do I get the "Fatal Error" message? Did I overlook or forget something in my query?
Be gentle. :-)
Remove the single quotes around the below statement
$con = 'mysqli_connect("'.$host.'", "'.$user.'", "'.$paass.'", "'.$dbName.'")';
^ ^
By enclosing it in single quotes , your $con behaves like a string instead of a connection resource. The mysqli_connect function will never be executed.
Simply rewrite it like..
$con = mysqli_connect($host,$user,$paass,$dbName);

mysqli_connect Fatal Error: require()

Developing a very simple UPDATE query page for users to change their account password, but have run into a bit of a brick wall with establishing the MySQLi connection (or so it would seem). I'm new to this line of programming and this is my first attempt to perform a dynamic query, so hopefully it's something that one of you can spot easily enough and you'd so kind as to offer some much-needed sage advice.
Here's the page in question: http://www.parochialathleticleague.org/accounts.html
Upon executing the form's PHP script, I was at first receiving nothing but a blank white screen. I scoured through my code and did everything I could think of to diagnose the problem. After eventually adding an "OR die" function to the require command, I am now greeted with this message:
Warning: require(1) [function.require]: failed to open stream: No such file or directory > in /home/pal/public_html/accounts.php on line 10
Fatal error: require() [function.require]: Failed opening required '1'
(include_path='.:/usr/local/php52/pear') in
/home/pal/public_html/accounts.php on line 10
I'm pretty stumped. Here's the script code:
<?php
// Show errors:
ini_set('display_errors', 1);
// Adjust error reporting:
error_reporting(E_ALL);
// Connect to the database:
require ('../mysqli_connect.php') OR die('Error : ' . mysql_error());
// Validate the school:
if (empty($_POST['school'])) {
echo "You forgot to enter your school.<br>";
$validate = 'false';
} else {
$school = mysqli_real_escape_string($db, trim($_POST['school']));
$validate = 'true';
}
// Validate the existing password:
if (empty($_POST['pass'])) {
echo "You forgot to enter your existing password.<br>";
$validate = 'false';
} else {
$pass = mysqli_real_escape_string($db, trim($_POST['pass']));
$validate = 'true';
}
// Validate the new password:
if (empty($_POST['new_pass'])) {
echo "You forgot to enter your new password.<br>";
$validate = 'false';
} elseif (empty($_POST['confirm_pass'])) {
echo "You forgot to confirm your new password.<br>";
$validate = 'false';
} elseif ($_POST['new_pass'] != $_POST['confirm_pass']) {
echo "Sorry, your new password was typed incorrectly.<br>";
$validate = 'false';
} else {
$new_pass = mysqli_real_escape_string($db, trim($_POST['new_pass']));
$validate = 'true';
}
// If all conditions are met, process the form:
if ($validate != 'false') {
// Validate the school/password combination from the database:
$q = "SELECT school_id FROM user_schools WHERE (school_name='$school' AND pass=SHA1('$pass') )";
$r = #mysqli_query($db, $q);
$num = #mysqli_num_rows($r);
if ($num == 1) {
// Get the school_id:
$row = mysqli_fetch_array($r, MYSQLI_NUM);
// Perform an UPDATE query to modify the password:
$q = "UPDATE user_schools SET pass=SHA1('$new_pass') WHERE school_id=$row[0]";
$r = #mysqli_query($db, $q);
if (mysqli_affected_rows($db) == 1) {
header("Location: confirm_accounts.html");
} else {
echo "Your password could not be changed due to a system error. Apologies for the inconvenience. If this problem continues, please contact us directly.";
}
}
}
mysqli_close($db);
exit();
?>
Lastly, here's the code from the connection script that it's requiring (with omitted account values, of course):
<?php
// Set the database access information as constants:
DEFINE ('DB_USER', '***');
DEFINE ('DB_PASSWORD', '***');
DEFINE ('DB_HOST', 'localhost');
DEFINE ('DB_NAME', '***');
// Make the connection:
$db = #mysqli_connect (DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) OR die ('Could not connect to MySQL: ' .mysqli_connect_error() );
// Set the encoding:
mysqli_set_charset($db, 'utf8');
I've been trying for the last couple of hours to troubleshoot this problem on my own. Google couldn't solve it. Looking through archives here couldn't solve it.
Here's what I do know for sure:
The script that it's requiring, mysqli_connect.php, does work on its own. I've tested it extensively to make sure that all of the log-in info is correct.
The script is also definitely in the parent directory that I've requested it from. I've tried moving it to the public directory and calling it from there. Same error message. Tried typing the entire file path. Same message.
Also, most of the script works fine on its own. When I omitted all of the MySQL lines and just left the basic validation code, it ran without a problem and sent me to the confirmation page as requested. It definitely seems to be a problem with making the connection.
Not sure where to go from here. Any assistance would be GREATLY appreciated! Many thanks in advance.
EDIT: #YourCommonSense - Here's the modified script, as per your suggestions. Still getting the blank screen. Am I following your advice incorrectly?
<?php
// Show errors:
ini_set('display_errors', 1);
// Adjust error reporting:
error_reporting(E_ALL);
// Connect to the database:
require ('../mysqli_connect.php');
// Validate the school:
if (empty($_POST['school'])) {
echo "You forgot to enter your school.<br>";
$validate = 'false';
} else {
$school = mysqli_real_escape_string($db, trim($_POST['school']));
$validate = 'true';
}
// Validate the existing password:
if (empty($_POST['pass'])) {
echo "You forgot to enter your existing password.<br>";
$validate = 'false';
} else {
$pass = mysqli_real_escape_string($db, trim($_POST['pass']));
$validate = 'true';
}
// Validate the new password:
if (empty($_POST['new_pass'])) {
echo "You forgot to enter your new password.<br>";
$validate = 'false';
} elseif (empty($_POST['confirm_pass'])) {
echo "You forgot to confirm your new password.<br>";
$validate = 'false';
} elseif ($_POST['new_pass'] != $_POST['confirm_pass']) {
echo "Sorry, your new password was typed incorrectly.<br>";
$validate = 'false';
} else {
$new_pass = mysqli_real_escape_string($db, trim($_POST['new_pass']));
$validate = 'true';
}
// If all conditions are met, process the form:
if ($validate != 'false') {
// Validate the school/password combination from the database:
$q = "SELECT school_id FROM user_schools WHERE (school_name='$school' AND pass=SHA1('$pass') )";
$r = mysqli_query($db, $q);
if (!$r) {
throw new Exception($mysqli->error." [$query]");
}
$num = mysqli_num_rows($r);
if ($num == 1) {
// Get the school_id:
$row = mysqli_fetch_array($r, MYSQLI_NUM);
// Perform an UPDATE query to modify the password:
$q = "UPDATE user_schools SET pass=SHA1('$new_pass') WHERE school_id=$row[0]";
$r = mysqli_query($db, $q);
if (!$r) {
throw new Exception($mysqli->error." [$query]");
}
if (mysqli_affected_rows($db) == 1) {
header("Location: confirm_accounts.html");
} else {
echo "Your password could not be changed due to a system error. Apologies for the inconvenience. If this problem continues, please contact us directly.";
}
}
}
mysqli_close($db);
exit();
?>
Two BIGGEST problems with your code and your "solution":
You have # operator all over the place. For which you have -1 vote to your question. # operator is the evil itself. IT is responsible for the blank page you see.
However, the remedy you choose made the things worse. This "OR die" thing is not a magic chant to solve any error reporting problem. And used improperly will cause errors like one you have. For which you have 1 in the error message.
First of all, your include is all right, so, leave it alone.
While to get an error from mysqli, follow these instructions:
Instead of adding "or die" randomly, you need more robust and helpful error reporting solution.
If you are using mysqli_query() all over the application code without encapsulating it into some helper class, trigger_error() is a good way to raise a PHP error, as it will tell you also the file and the line number where error occurred
$res = mysqli_query($mysqli,$query) or trigger_error(mysqli_error($mysqli)."[$query]");
in all your scripts
and since then you will be notified of the reason, why the object weren't created.
(If you're curious of this or syntax, I've explained it here - it also explains why you have (1) in the error message)
However, if you're encapsulating your query into some class, file and line from trigger error will be quite useless as they will point to the call itself, not the application code that caused certain problem. So, when running mysqli commands encapsulated, another way have to be used:
$result = $mysqli->query($sql);
if (!$result) {
throw new Exception($mysqli->error." [$query]");
}
as Exception will provide you with a stack trace, which will lead you the the place from which an erroneous query were called.
Note that you have to be able to see PHP errors in general. On a live site you have to peek into error logs, so, settings have to be
error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);
while on a local development server it's all right to make errors on screen:
error_reporting(E_ALL);
ini_set('display_errors',1);
and of course you should never ever use error suppression operator (#) in front of your statements.

Categories