I'm just changing my website's MySQL to PDO, and I've got a strange problem when I tried to use PDO in an other class.
class Database {
private $pdo;
public function __construct() {
$this->pdo = new PDO('mysql:host=localhost;dbname=appdora;charset=utf8', 'root', 'root');
}
}
class doClass {
//Variables
private $db;
//PDO
public function __construct(Database $db) {
$this->db = $db;
}
And the code is returns with: the following error:
Catchable fatal error: Argument 1 passed to doClass::__construct() must be an instance of Database, none given, called in .../index.php on line xx and defined in ../classes.php on line xx
The code:
$do = new doClass();
if ($do->loginCheck()) { echo 'loginOk'; } else { 'loginError'; }
loginCheck() is a simle function that works without classes!
Could you help me, what's the problem?
Thanks in advance!
$do = new doClass();
You defined your doClass class to expect a parameter in the constructor:
public function __construct(Database $db)
So you need to supply that parameter of type Database to successfully construct the object.
For example, if you have a database object stored before somewhere inside a variable $database, you can simply pass it to the constructor of doClass like this:
$do = new doClass($database);
Related
Ok,
This is sort of an involved problem, but any help or advice would be incredibly appreciated.
So I'm working with a site that (using .htaccess) redirects all traffic to a load.php. For any sql functionality, I have an abstract class that has a lot of query statements as functions that pass parameters to define the specifics of each query.
e.g.
$table->update("constraints")
I'm trying to figure out how to set the connection to the database on load.php, and then set the connection as a variable ($mysqli) that can then be referenced in my abstract query class without having to pass the parameter to every single query function call.
Again, any help or advice would be appreciated.
Here's an example of a function:
function clearTable (){
$mysqli = dbConnect::connect();
$sql = "TRUNCATE TABLE $this->tablename";
$mysqli->query($sql);
}
If I connect to the database in a construct function and set $this->mysqli and replace $mysqli = dbConnect::connect(); with $mysqli = $this->mysqli, none of the queries work. Though they work with a fresh reconnect on each call.
You should use Dependency Injection for this.
Basically it means that the class that needs the database connection doesn't create the connection, it just receives the already instasiated instance.
Example
In some init file:
// Create the db connection
$db = new Mysqli(......);
// Pass it to the query class that needs it
$queryClass = new QueryClass($db);
Then in your class file:
class QueryClass
{
protected $db;
public function __construct($db)
{
// $this->db will now be the same Mysql instance
$this->db = $db;
}
public function doSomeQuery()
{
$this->db->query(....);
}
}
A bonus for this is that you don't need to touch the QueryClass, if you ever want to start making some unit tests. You only need to pass a DB connection to a test database instead.
After looking through this a bit more, I can also create my db::connect() function to look like this:
class dbConnect {
private static $db;
private $mysqli;
private function __construct() {
$this->mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
}
function __destruct() {
$this->mysqli->close();
}
public static function connect() {
if (self::$db == null) {
self::$db = new dbConnect();
}
return self::$db->mysqli;
}
}
and pass that as $this->mysqli in the query functions file
This question already has answers here:
Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?
(3 answers)
Closed 6 years ago.
I've been working on a databaseHandler php class, which should connect to the database and then be usable in other PHP files, atleast this was the plan. I've come across the problem that it cannot use any PDO related functions in my PHP class, i've tried checking if it was null, or not set at all (but it was) and i've also tried using a dummy function that just echos something which was to test if the class isn't undefined in others.
<?php
class databaseHandler {
private $db;
private static $instance;
function __construct() {
$this->buildDatabaseConnection();
}
public static function getInstance() {
if(!self::$instance) {
self::$instance = new databaseHandler();
}
return self::$instance;
}
private function buildDatabaseConnection() {
require 'dbconfig.php';
try {
$this->db = new PDO("mysql:host=" . HOST . ";dbname=" . DATABASE . ";charset=utf8", USER, PASSWORD);
if(isset($this->db)) {
if(!is_null($this->db)) {
echo "isn't null";
}
}
} catch(PDOException $e) {
$e->getMessage();
}
}
public function getConnection() {
return $this->$db;
}
public function getSomeShit() {
echo "some shit";
}
}
?>
The problem might be with the getConnection() php function, does it actually return the PDO object here? Because the main problem lays with the fact that i get this error when i use my getConnection function in other classes:
Notice: Undefined variable: database in F:\Websites\DevProject\php\functions.php on line 69
Fatal error: Uncaught Error: Call to a member function prepare() on null in F:\Websites\DevProject\php\functions.php:69 Stack trace: #0 F:\Websites\DevProject\php\functions.php(51): register('qwe', 'sdasd', 'asdasd', 'asdas', '01-01-1970') #1 F:\Websites\DevProject\register.php(123): datelessRegister('qwe', 'sdasd', 'asdasd', 'asdas') #2 {main} thrown in F:\Websites\DevProject\php\functions.php on line 69
and line 69 would be this:
$stmnt = $database->prepare("SELECT $username, $email FROM " . USERTABLE);
Where the $database variable is the class instance:
$database = databaseHandler::getInstance();
If i try to var_dump it in my registration php file, it'll tell me this:
object(databaseHandler)#1 (1) { ["db":"databaseHandler":private]=> object(PDO)#2 (0) { } }
However, when i use it inside of my function, it will say it is 'NULL', why is it null in a function but defined globally?
All the errors relate to the object, and in there it tells me the pdo is undefined (i've tried checking if it was null, but it wasn't!)
Any help would be great, thanks in advance.
In the return statement of getConnection method you should write the class variable without $:
return $this->db;
Also, you must do the queries on the PDO connection instead of your database handler class, so $database = databaseHandler::getInstance(); should be
$database = databaseHandler::getInstance()->getConnection();
or you can simply use the __call magic method to keep your code as it is right now:
public function __call($method, $args)
{
return call_user_func_array(array($this->db, $method), $args);
}
Also, to clarify how to use this class, you should call it inside every method you need the database to be used, not only once on the top of your file, because defining it there it will not be available inside your methods/functions unless you don't use the global statement to import the variable. However usage of the global variable is not encouraged and it is considered as a bad practice. An example on how to use the database would be:
public function doSomething()
{
$db = databaseHandler::getInstance()->getConnection();
$db->prepare(....);
}
public function doSomethingElse()
{
$db = databaseHandler::getInstance()->getConnection();
$db->prepare(....);
}
If you know there are many methods inside your class that uses the database then you can define it as a class variable and set the db instance in the constructor.
You seem to be having issues with scopes.
$database = databaseHandler::getInstance();
function doSomething()
{
// $database is not defined in this scope
$database->getConnection()->prepare(/* ... */);
}
You have to declare it as part of the global scope
function doSomething()
{
global $database;
$database->getConnection()->prepare(/* ... */);
}
The problem seems to be in the getConnection() function. Since $db is field you must do.
return $this->db;
However this is a very complex class structure for a simple problem.
You can directly extend your class from PDO
class DatabaseHandler extends PDO {
function __construct() {
parent::__construct('mysql:host=host_name;dbname=db_name', 'user_name', 'password');
parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
}
And create an object of this whenever you want to do database transaction.
$db = new DatabaseHandler();
$stmt = $db->prepare(".....");
$stmt->execute();
I know this is an old question but I am not finding answer. Here is my code:
class SqlConnect implements connectionInterface {
//put your code here
private $datasource=null;
private $credentials = null;
public function __construct() {
$netsConn = new configInit(); // Here where the error is happing
$datasource = $this->$netsConn->getDatabase();
$credentials = $this->$netsConn->getBasicCredentials();
}
public function connect()
{
$conn = mysqli_connect($datasource['servername'], $credentials['username'], $credentials['password']);
if (!$conn)
{
die("Connection failed: " . $conn->connect_error);
} else {
return $conn;
}
}
}
I am then calling the class like
class applicationsController implements Controller {
private $conn = null;
public function __construct() {
$conn = new SqlConnect();
$this->$conn->connect();
}
...
}
However I am getting the following error:
Catchable fatal error: Object of class configInit could not be converted to string
This error happens in SqlConnect. I have looked through about 6 answers on stackoverflow and most all of them were about trying to echo some objects, which is not my case
Ahh, I think I see it.
You are assigning to global variable $netsConn, not object property $netsConn ...
Try this:
private $netsConn;
...
$this->netsConn = new configInit();
... that is, if you want to keep it around. Otherwise, refer directly to the variable not to a (never-declared ...) property.
The reason you get the error is because of the following 2 lines
netsConn = new configInit(); // Here where the error is happing
$datasource = $this->$netsConn->getDatabase();
First line is fine, but on the second line, you are using $netsConn as an attribute name for the SqlConnect class ($this). For this to work, php has to use the string representation of $netsConn by attempting to call it's implementation of the magic method __toString(). Since this probably does not exist in your configInit() class, you end up with that error.
require("classes/controller.class.php");
$db = new mysqli(__DBHOST, __DBUSER, __DBPASS, __DBDATA);
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
$controller = new Controller;
Within the Controller class I want to use the $db MySQLi connection. So within a public function I used:
$result = $db->query("SELECT * FROM colors");
var_dump($result);
But I get this error:
Fatal error: Call to a member function query() on a non-object in /home/cloud/public/teamdresser/controllers/IndexController.php on line 8
Am I doing something wrong? Do I need to pass the $db connect first, or use global or something?
Thanks in advance
If $db is a global variable, you'll need to import it in your function:
public function YourFunction()
{
global $db;
$result = $db->query("SELECT * FROM colors");
..
}
Instead of doing this, you might want to consider encapsulating $db in a database class and create it as a singleton, or, arguably better, pass it to the constructor of Controller. But that remark might lead to new discussions about design, while complete books have been written about this subject. So for now, just import the global like described above. ;)
You could use a class with a singleton instance
class Database {
private static $_instance;
public static function getInstance() {
//If the connection is not initialized, this creates it and store
if (empty(Database::$_instance))
Database::$_instance = new Database();
return Database::$_instance;
}
private $_db;
private function __construct() {
$this->_db = new mysqli(__DBHOST, __DBUSER, __DBPASS, __DBDATA);
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
}
private function __destruct() {
$this->_db->close();
}
public function query($query) {
return $this->_db->query($query);
}
}
You called in this manner
$result = Database::getInstance()->query("SELECT * FROM colors");
You have created a connection and executed with calling a function. Once the script is terminated, the connection will be autorealeased by the destructor.
This should be only a start point. You could create all functionality that you want (e.g. escape parameters, insert, update, delete, and so on...)
I'm trying to create a simple class based on my database PDO class that I can say "get this id" and it will print the info. I'm trying to do this in "qu" but get the following error: "Call to undefined method qu::get()".
There's probably a mixture of problems so any help here would be awesome. Thanks a lot!!
class db {
protected static $conn;
private function __construct(){}
public static function connect() {
if (!isset(self::$conn)) {
self::$conn = new PDO('mysql:host=localhost;dbname=database', DB_USER, DB_PASSWORD);
}
return self::$conn;
}
}
class qu {
private $db;
function quconn (&$db){
$this->db = &$db;
}
private static function getq($id){
$sql="SELECT * FROM table WHERE id=:id";
$stmt = self::quconn()->prepare($sql);
$stmt->execute(array(':id'=> $id));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
//$data = db::connect()->query("SELECT * FROM table")->fetchAll(); // this works
$data = qu::getq("22"); //can i use something like this? this causes the error
print_r($data);
function getq of class qu should be marked with public access modifier.
Otherwise the following row will fail as getq is a private function
$data = qu::getq("22");
Second and issue in this code
function quconn (&$db){
$this->db = &$db;
}
As you enter function quconn from a static content $this is unavailable.
Use self::$db instead.
For class qu follow the same structure of class db wich is a singleton mnagament class.
I also suggest to clarify yourself differences between $this and self, static contest etc..
Php offiacial documentation offers al lot about
Also i don't think you need passing-by-reference method:
try to rewrite the quconn function as follows:
function quconn ($db){
self::$db = $db;
}
By the way i don't thing the class qu is well "engineered"
Even if you correct the passing-by-reference-problem this instruction won't work:
$stmt = self::quconn()->prepare($sql);
You are invoking the prepare function on the result of the invocation to quconn, which doesn't return anything...
I suggest:
$stmt = db::connect()->prepare($sql);
this get the PDP instance and call the prapare method....