Fatal Error with fetch_assoc inside a function - php

I truly need your help. I have seen answers and even followed advice as previously posted but NO SOLUTIONS SHOW how to use fetch associated array using PREPARED STATEMENTS so I am not trying to submit an already answered question. I have followed suggestions to others questions but I am still getting:
Fatal error: Call to a member function fetch_assoc() on a non-object in /xxx/xxxxxx.php on line 75
I am showing you the old code using MySQL and how I have changed it to MySQLi using prepared statements, but I am still getting the same Fatal Error. Can someone please help me, I am going crazy and I truly need to find out what I am doing wrong. Thanks for your help.
//*******************************************************************
// OLD CODE:
// Called by: $theme=$log->get_theme();
//*******************************************************************
class redirect
{
function __construct()
{
}
function get_theme()
{
$rs=mysql_query("select * from theme where status='yes'");
if(mysql_num_rows($rs)>0)
{
$data=mysql_fetch_array($rs);
return $data['theme_name'];
}
}
}
//*********************************************************************
// OLD CODE:
// Called by: $theme=$log->get_theme($cn);
//*********************************************************************
class redirect
{
public $cn;
function __construct()
{
}
function get_theme($cn)
{
$themeStatus = 'yes';
if ($stmt = $cn->prepare("SELECT * FROM theme WHERE status = ? "))
{
$stmt->bind_param("s", $themeStatus);
$result = $stmt->execute();
$stmt->store_result();
if ($stmt->num_rows >= "1")
{
$data = $result->fetch_assoc(); // ERROR LINE
return $data['theme_name'];
}
}
else
{
echo "Failed to execute prepared statement: " . mysqli_connect_error();
}
}
}

The mysqli_stmt::execute method returns only bool by definition. So calling $result->any_method_name() will fail because $result is a boolean value.
To get the values from a prepared statement using the MySQLi library you bind your target variables with $stmt->bind_result(...) and then use $stmt->fetch() in a while loop to get the result of your query in your bound variables. And after that you switch from MySQLi to PDO because it has a better API regarding this…

Related

Trying to get property 'num_rows' of non-object even though var_dump returns an object

So I am new to the OOP concept. I decided to make a call to my database, but in OO way. The error I am getting is:
Trying to get property 'num_rows' of non-object (at line 83 *reference to line 83)
I understand the error message, but fail to find out what is wrong regarding it. I have tried the following links, but unfortunately none of them have helped me really further, or I failed to understand what they meant.
Notice: Trying to get property 'num_rows' of non-object in line 35
Error - Trying to get property 'num_rows' of non-object
Get property num_rows of non-object
Trying to get property 'num_rows' of non-object
This is the reason I am knowingly making a duplicate question, hoping my problem would be something that has not (yet) been addressed in the other posts.
require 'connection.php';
//class DatabaseQueries handles all the queries required regarding CRUD.
class DatabaseQueries
{
//the SQL string
private $sql;
// The connection -> completegallery
private $conn;
public function __construct($conn)
{
$this->conn = $conn;
}
// function will check whether email already exists or not.
protected function getEmailExistance(string $email)
{
//create the SQL
$this->sql = $this->conn->prepare("SELECT * FROM userinfo WHERE email = ?");
//bind the parameter to it (preventing sql injection this way)
$this->sql->bind_param('s', $email);
// $result = the execution of the SQL.
$result = $this->sql->execute();
$resultCheck = $result->num_rows; //* line 83
var_dump($result); // returns boolean true.
var_dump($this->sql); // returns a mysqli stmt object
//check whether $resultCheck > 0
//if yes, that would mean the userName already exists.
if (!empty($result) && $resultCheck > 0)
{
exit('should show something');
} else
{
exit('always fails here');
}
}
} // ending class DatabaseQueries
How I call the class DatabaseQueries:
class Base extends DatabaseQueries
{
private $email;
private $userName;
private $name;
private $lastName;
private $pwd;
private $pwdConfirm;
// here is the code where I check and assign the user input to the variable $email etc.
//this method is for test purposes only and will be removed after the website is 'done'.
public function getEverything()
{
//link to check whether email is being used or not
$this->getEmailExistance($this->email);
}
}
How I invoke the objects etc.
$userInformation = new base($conn);
$userInformation->setEmail($_POST['registerEmail']);
//some other info, but not relevant to the problem.
I have already checked whether I misspelled anything, but this wasn't the case. The connection in connection.php has been declared correct aswell.
As mentioned in the comments, execute() does not return the result, you have to fetch() it. Here is the code that should allow you to do what you are asking.
// function will check whether email already exists or not.
protected function getEmailExistance(string $email)
{
//create the SQL
$this->sql = $this->conn->prepare("SELECT * FROM userinfo WHERE email = ?");
//bind the parameter to it (preventing sql injection this way)
$this->sql->bind_param('s', $email);
// $result = the execution of the SQL.
$this->sql->execute(); <---- No need for variable here, its boolean
$result = $this->sql->store_result(); <---- The result
$num_rows = $this->sql->num_rows; <---- This will contain your row count
if (!empty($result))
{
// fetch your results here
} else
{
exit('always fails here');
}
}

Call to a member function fetch() on a non-object

I'm getting the error:
Call to a member function fetch() on a non-object
The line this refers to is:
$getProjectIdResult = $stmt->fetch();
Now, I think from this error that there must be something wrong with my database query, since the documentation says PDO query returns false on failure. I'm having trouble identifying what is causing the issue.
I've tried wrapping the fetch in a try/catch, with
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
However the catch isn't triggered and I just get the original fatal error so I haven't been able to get a more specific error.
classes.php
class Query extends Connection {
public function getProjectID($surveyID) {
$query_getProjectID = "SELECT projectID FROM test WHERE surveyID = :surveyID";
$query_getProjectID_params = array(
':surveyID' => $surveyID
);
try {
$stmt = $this->db->prepare($query_getProjectID);
$stmt = $stmt->execute($query_getProjectID_params);
}
catch (PDOException $ex) {
die("Failed to get project ID: " . $ex->getMessage());
}
$getProjectIdResult = $stmt->fetch();
$getProjectID = $getProjectIdResult['projectID'];
return $getProjectID;
}
}
test.php
include_once("includes/classes.php");
include_once("includes/functions.php");
// Bind $_GET data
// localhost/panel/test.php?surveyID=3&status=1&respondentID=666
// Expected result: 111
$surveyID = sanitise($_GET['surveyID']);
$status = sanitise($_GET['status']);
$respondentID = sanitise($_GET['respondentID']);
$con = new Connection();
$query = new Query();
$query->getProjectID($surveyID);
$con->closeConnection();
I've ruled out the sanitise function causing an issue by testing with and without it.
I apologise as I know this is probably just another amateur making another amateur mistake judging by how many posts there are by the same title.
When you call
$stmt = $stmt->execute($query_getProjectID_params);
You assign the return-value of execute() to $stmt, overwriting the variable, making it a boolean instead of an object. When you continue, $stmt no longer holds the PDOStatement object, but is now a boolean.
The solution is simply to remove the overwrite of your object, like this (remove $stmt = in front).
$stmt->execute($query_getProjectID_params);
http://php.net/pdostatement.execute

MYSQLI Error : Call to a member function execute() on a non-object [duplicate]

Warning: mysqli::query(): Couldn't fetch mysqli in C:\Program Files (x86)\EasyPHP-DevServer-13.1VC9\data\localweb\my portable files\class_EventCalendar.php on line 43
The following is my connection file:
<?php
if(!isset($_SESSION))
{
session_start();
}
// Create array to hold error messages (if any)
$ErrorMsgs = array();
// Create new mysql connection object
$DBConnect = #new mysqli("localhost","root#localhost",
NULL,"Ladle");
// Check to see if connection errno data member is not 0 (indicating an error)
if ($DBConnect->connect_errno) {
// Add error to errors array
$ErrorMsgs[]="The database server is not available.".
" Connect Error is ".$DBConnect->connect_errno." ".
$DBConnect->connect_error.".";
}
?>
This is my class:
<?php
class EventCalendar {
private $DBConnect = NULL;
function __construct() {
// Include the database connection data
include("inc_LadleDB.php");
$this->DBConnect = $DBConnect;
}
function __destruct() {
if (!$this->DBConnect->connect_error) {
$this->DBConnect->close();
}
}
function __wakeup() {
// Include the database connection data
include("inc_LadleDB.php");
$this->DBConnect = $DBConnect;
}
// Function to add events to Zodiac calendar
public function addEvent($Date, $Title, $Description) {
// Check to see if the required fields of Date and Title have been entered
if ((!empty($Date)) && (!empty($Title))) {
/* if all fields are complete then they are
inserted into the Zodiac event_calendar table */
$SQLString = "INSERT INTO tblSignUps".
" (EventDate, Title, Description) ".
" VALUES('$Date', '$Title', '".
$Description."')";
// Store query results in a variable
$QueryResult = $this->DBConnect->query($SQLString);
I'm not great with OOP PHP and I'm not sure why this error is being raised. I pulled this code from elsewhere and the only thing I changed was the #new mysqli parameters. Can anyone help me to understand what is going wrong?
Probably somewhere you have DBconnection->close(); and then some queries try to execute .
Hint: It's sometimes mistake to insert ...->close(); in __destruct() (because __destruct is event, after which there will be a need for execution of queries)
Reason of the error is wrong initialization of the mysqli object. True construction would be like this:
$DBConnect = new mysqli("localhost","root","","Ladle");
I had the same problem. I changed the localhost parameter in the mysqli object to '127.0.0.1' instead of writing 'localhost'. It worked; I’m not sure how or why.
$db_connection = new mysqli("127.0.0.1","root","","db_name");
Check if db name do not have "_" or "-"
that helps in my case

I'm struggling to upgrade login script with PDO

I have a custom query() function in my functions. file. I created a login.php file, but when I make a SQL query, the query() function returns a PDO object, instead of an associative array I desire. I need help to pass parameters to be bound to a stored procedure/prepared statement.
The following is the login.php file:
<?php
// configuration
require("../../includes/config.php");
// if form was submitted
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
// validate submission
if (empty($_POST["username"]))
{
adminapologize("You must provide your username.");
}
else if (empty($_POST["password"]))
{
adminapologize("You must provide your password.");
}
$username = $_POST["username"];
// query database for user
$sql = "SELECT * FROM admin WHERE username = '$username'";
$result = query($sql,array($username));
//var_dump($result);
//exit;
if($sql != false)
{
if($result->rowCount() == 0)
{
printf("No admin yet.");
}
// if we found user, check password
if($result->rowCount() == 1)
{
// first (and only) row
$row = $result->fetch();
// compare hash of user's input against hash that's in database
if ($_POST["username"] == $row["username"] && crypt($_POST["password"], $row["hash"]) == $row["hash"])
{
// remember that user is now logged in by storing user's ID in session
$_SESSION["admin_id"] = $row["admin_id"];
// redirect to admin home
redirect("index.php");
}
}
}
else
{
// else apologize
adminapologize("Invalid username and/or password.");
}
}
else
{
// else render form
adminrender("login_form.php", ["title" => "Admin Log In"]);
}
?>
Be advised that the config.php includes the functions.php file. And the following is the portion of the functions.php file:
/**
* Executes SQL statement, possibly with parameters, returning
* a pdo statement object on success, handling and halting execution on error.
*/
function query($sql, $parameters = null)
{
static $pdo; // define the var as static so that it will persist between function calls
try
{
// if no db connection, make one
if (!isset($pdo))
{
// connect to database
// you should set the character encoding for the connection
$pdo = new PDO("mysql:dbname=" . DB_NAME . ";host=" . DB_SERVER, DB_USERNAME, DB_PASSWORD);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // set the error mode to exceptions
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); // turn emulated prepares off
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); // set default fetch mode to assoc so that you don't have to explicitly list the fetch mode every place
}
if(empty($parameters))
{
// no bound inputs
$stmt = $pdo->query($sql);
} else {
// has bound inputs
$stmt = $pdo->prepare($sql);
// you should use explicit bindValue() statements to bind any inputs, instead of supplying them as a parameter to the ->execute() method. the comments posted in your thread lists the reasons why.
$stmt->execute($parameters);
}
}
catch (Exception $e)
{
// all errors with the connection, query, prepare, and execute will be handled here
// you should also use the line, file, and backtrace information to produce a detailed error message
// if the error is due to a query, you should also include the $sql statement as part of the error message
// if $pdo ($handle in your code) is set, it means that the connection was successful and the error is due to a query. you can use this to include the $sql in the error message.
trigger_error($e->getMessage(), E_USER_ERROR);
//exit; // note: E_USER_ERROR causes an exit, so you don't need an exit; here.
}
return $stmt; // if the query ran without any errors, return the pdo statement object to the calling code
}
Your help would be much appreciated.
You've got an excellent function, no need to spoil it.
the query() function returns a PDO object, instead of an associative array I desire.
It's actually an object that you want to be returned. As for the array, you can simply get it by chaining fetch to the call:
$result = query($sql,array($username))->fetch(); // voila!
Look, with function returning an object you can get not only single row but dozens different kinds of results. Like single column value with fetchColumn() or many formats supported by fetchAll(). Not to mention you can get numRows() from the object while from array you can't.
With this function in its current form you can run DML queries as well, while returning fetch it will end up with error. Returning an object is a really really cool thing!
The only bad thing about your function is that you are catching an exception and converting it into an error manually, while PHP is already doing it for you.
Just get rid of this try catch block and you will have exactly the same (actually, even better) error reporting.
// all errors with the connection, query, prepare, and execute will be handled here
// you should also use the line, file, and backtrace information to produce a detailed error message
// if the error is due to a query, you should also include the $sql statement as part of the error message
// if $pdo ($handle in your code) is set, it means that the connection was successful and the error is due to a query. you can use this to include the $sql in the error message.
ALL these things PHP is already doing for you, if you simply don't catch an exception.
(save for storing an $sql variable which is not needed actually, as you can find a query following a back trace)
As of the code, it should be five times shorter:
$sql = "SELECT * FROM admin WHERE username = ?";
$row = query($sql,array($username))->fetch();
if($row && crypt($_POST["password"], $row["hash"]) == $row["hash"])
{
// remember that user is now logged in by storing user's ID in session
$_SESSION["admin_id"] = $row["admin_id"];
// redirect to admin home
redirect("index.php");
//this is essential as otherwise anyone will be able to proceed with this page
exit;
}
BTW, I just noticed that you are using your function wrong, sending $username right into the query. I fixed it too.
Edit according to #Your Common Sense's answer who's absolutley right:
Call your function 'query' and do directly on that result a fetch.
For example as mentioned in the comments below:
$rows = query($sql, $params)->fetch();
If you want rows as associative array do
$rows = query($sql, $params)->fetch(PDO::FETCH_ASSOC);
This explicitly returns an associative array.
You have to fetch the result after executing.
$stmt->execute($parameters);
return $stmt->fetch(PDO::FETCH_ASSOC);
This should return an associative array.
See also: http://php.net/manual/de/pdostatement.fetch.php
/**
* Executes SQL statement, possibly with parameters, returning
* a pdo statement object on success, handling and halting execution on error.
*/
function query($sql, $parameters = null)
{
static $pdo; // define the var as static so that it will persist between function calls
$return = false;
try {
// if no db connection, make one
if (!isset($pdo)) {
// connect to database
// you should set the character encoding for the connection
$pdo = new PDO("mysql:dbname=" . DB_NAME . ";host=" . DB_SERVER, DB_USERNAME, DB_PASSWORD);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // set the error mode to exceptions
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); // turn emulated prepares off
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); // set default fetch mode to assoc so that you don't have to explicitly list the fetch mode every place
}
if(empty($parameters)){
// no bound inputs
$stmt = $pdo->query($sql);
} else {
// has bound inputs
$stmt = $pdo->prepare($sql);
// you should use explicit bindValue() statements to bind any inputs, instead of supplying them as a parameter to the ->execute() method. the comments posted in your thread lists the reasons why.
$stmt->execute($parameters);
$return = $stmt->fetch(PDO::FETCH_ASSOC);
}
} catch (Exception $e)
{
// all errors with the connection, query, prepare, and execute will be handled here
// you should also use the line, file, and backtrace information to produce a detailed error message
// if the error is due to a query, you should also include the $sql statement as part of the error message
// if $pdo ($handle in your code) is set, it means that the connection was successful and the error is due to a query. you can use this to include the $sql in the error message.
trigger_error($e->getMessage(), E_USER_ERROR);
//exit; // note: E_USER_ERROR causes an exit, so you don't need an exit; here.
}
return $return; // if the query ran without any errors, return the pdo statement object to the calling code

PHP prepared statement: Why is this throwing a fatal error?

Have no idea whats going wrong here. Keeps throwing...
Fatal error: Call to a member function prepare() on a non-object
...every time it gets to the $select = $dbcon->prepare('SELECT * FROM tester1');part. Can somebody shed some light as to what I'm doing wrong?
function selectall() //returns array $client[][]. first brace indicates the row. second indicates the field
{
global $dbcon;
$select = $dbcon->prepare('SELECT * FROM tester1');
if ($select->execute(array()))
{
$query = $select->fetchall();
$i = 0;
foreach ($query as $row)
{
$client[$i][0] = $row['id'];
$client[$i][1] = $row['name'];
$client[$i][2] = $row['age'];
$i++;
}
}
return $client;
}
$client = selectall();
echo $client[0][0];
The obvious answer is that $dbcon hasn't been initialized at all or is initialized after this function is called.
What code is initializing $dbcon? Where and when is it run? You also realize that you will need to initialize it on every invocation of a script that accesses the database? The last is just to make sure that you understand what the global scope in PHP is. It means scoped to that single request. The term global is a little misleading.
make sure you define $dbcon properly. If you are using mysqli, see how the connection is setup in the doc. you can also pass the connection object to the function
function selectall($dbcon){
....
}

Categories