I recently ran into a problem with a database class I have been using where my class is having some trouble getting mysqli. There are a few classes at play here so bear with me. There is one class called Manager that connects to the DB and sets it up, it then instantiates a new class called Business and passes in the DB, Then later in code execution one of Manager methods runs that asks Business to save some data to the DB and this is where the problem is. The database class is below, sensitive info redacted:
namespace Lib;
define('_DBHOST', 'localhost');
define('_DBUSER', '***');
define('_DBPASS', '***');
define('_DBNAME', '***');
class DB_Conn {
protected $DB;
function __construct() {
$this->connect();
}
protected function connect() {
$this->DB = new \mysqli(_DBHOST, _DBUSER, _DBPASS, _DBNAME);
if($this->DB == false) {
die(mysqli_connect_error());
}
}
function __destruct() {
$this->DB->close();
}
function getDB() {
if (!isset($this->DB)) { echo "connecting...<br />";
$this->connect();
}
return $this->DB;
}
}
Here is the Manager class:
class Manager {
public $mysqli;
private $businessMan;
public function __construct() {
//Grab database and connect to it
$database = new \Lib\DB_Conn();
$this->mysqli = $database->getDB();
$this->businessMan = new \Lib\Business($this->mysqli);
}
public function submitForm($data) {
//Save Data
if($this->businessMan->addBusiness($data)) {
echo "Yay";
} else {
echo "NO!";
}
}
}
And here is the Business class
namespace Lib;
class Business {
var $mysqli;
var $database;
function __construct($mysqli) {
$this->database = $mysqli;
}
function addBusiness($data)
{
$stmt = $this->database->prepare("INSERT INTO reboot_business(business_name) VALUES (?)");
//Here $stmt is NULL
//Bind the values from the array to the prepared statement
$stmt->bind_param('s', $data['values']['name']);
//Execute the prepared statement and display any error
if (!$stmt->execute()) {
var_dump($stmt->error);
//exit();
return false;
} else {
//Succcess add ID to variable
return true;
}
}
}
I double checked the SQL statement and that was fine and the actual error occurs in the above Business class where I use the mysqli->prepare function. The error is:
Warning: mysqli::prepare(): Couldn't fetch mysqli
Fatal error: Call to a member function bindParam() on a non-object
I also did a check on the $stmt variable and that is NULL so it would seem the issue is in getting mysqli
Have I missed something or am I just doing it wrong?
I was able to get it to work by creating a new instance of the DB_Conn class in the Business constructor but that didn't seem right or should I just do it that way and not have the Manager class take care of the DB at all? Actually thinking of it if the Manager class is doing this DB stuff when it doesn't need it itself is that wrong from an OO point of view?
Hope I made sense and appreciate any help.
After doing some extra debugging I found that in the Business constructor mysqli is all fine output no errors and looks like it is working.
Edit:
However in my addBusiness() method I get some interesting output, I am using var_dump($this->database) and I get about 16 errors: Warning: var_dump(): Property access is not allowed yet.
There is no loop at work in my code anywhere which is what makes it come up 16 times wierd then when it finally works the var_dump reports all null values:
object(mysqli)#12 (19) { ["affected_rows"]=> NULL ["client_info"]=> NULL ["client_version"]=> int(50010) ["connect_errno"]=> int(0) ["connect_error"]=> NULL ["errno"]=> NULL ["error"]=> NULL ["error_list"]=> NULL ["field_count"]=> NULL ["host_info"]=> NULL ["info"]=> NULL ["insert_id"]=> NULL ["server_info"]=> NULL ["server_version"]=> NULL ["stat"]=> NULL ["sqlstate"]=> NULL ["protocol_version"]=> NULL ["thread_id"]=> NULL ["warning_count"]=> NULL }
What is wierd is how the database property is fine in the constructor but then empty in the method. Any ideas why it is getting emptied or set to null rather?