I'm attempting to create a mysql query using OOP in PHP. In the code below the class "database_disconnection" does not toss any errors or notices, however the last class "database_query" gives me a notice that $database_handle is undefined. I have no idea what's causing this as I created the database_query class as a derivative class of database_connection, which include the $database_handle variable as private. Any help would be greatly appreciated!
Instantiating the objects:
include("includes/database_classes.php");
new database_connection;
new database_query('SELECT * FROM users');
and the classes:
<?php
/*----------------------------------------------------------------------------------------------------*/
class database_connection
{
private $username = 'root';
private $password = '';
private $hostname = 'localhost';
private $database = 'assistant';
private $database_handle;
function connect()
{
try
{
$database_handle = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
}
catch (PDOException $e)
{
print "Error!: " . $e ->getMessage() . "<br/>";
die();
}
}
}
/*----------------------------------------------------------------------------------------------------*/
class database_disconnection extends database_connection
{
function disconnect()
{
$database_handle = null;
}
}
/*----------------------------------------------------------------------------------------------------*/
class database_query extends database_connection
{
private $mysql_statement;
function __construct( $mysql_statement )
{
$this->mysql_statement = $mysql_statement;
foreach($database_handle->query("$mysql_statement") as $row) {
print_r($row);
}
}
}
/*----------------------------------------------------------------------------------------------------*/
?>
In your database_query constructor, you're attempting to use $database_handle before initializing it. If you notice, you only initialize in the connect function of your parent class (database_connection).
Either call connect before trying to refer to it, or initialize it in the parent's constructor, and call it (parent::__construct();).
Related
I tried to create a connection class in PHP to connect with the DB data, but one error appears on the lines:
const USER = "{$value['user_DB']}";
const PASS = "{$value['password_DB']}";
Fatal error: Constant expression contains invalid operations in
C:\xampp\htdocs\dev\davinci\classes\Conexao_Teste.class.php on line 21
<?php
require_once"../classes/configDB.class.php";
abstract class conection extends configDB{
private $valor;
private $instanceConfigDB;
public function listDB(){
$valor = $instanceConfigDB->listconfigDB();
foreach($valor as $value){
echo "Banco: ID:{$value['id_db']} - Hostname:{$value['hostname']} - DBNAME:{$value['dbname']} - User:{$value['user_DB']} - PASS:{$value['password_DB']}<br>";
}
}
const USER = "{$value['user_DB']}";
const PASS = "{$value['password_DB']}";
private static $instance = null;
private static function conect(){
try {
if(self:: $instance==null):
$dsn = "mysql:host={$value['hostname']};dbname={$value['dbname']};charset=utf8";
self::$instance = new PDO($dsn, self::USER, self::PASS);
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
endif;
} catch (PDOException $e) {
echo "Erro: " . $e->getMessage();
}
return self::$instance;
}
protected static function getDB() {
return self::conect();
}
}
?>
You should use
define('USER', "{$value['user_DB']}");
As const would be evaluated at compile time where as define would be evaluated at run time.
You are trying to use $value[] outside it's defined scope, and that is why you are getting those errors.
$value[] is declared in method listDB(). If you want to use that value outside of the method you'd have to declare variables outside the method.
//Declaring variables and constants
private $valor;
private $instanceConfigDB;
private $username;
private $pass;
private $hostname;
private $dbname;
public function listDB(){
$valor = $instanceConfigDB->listconfigDB();
foreach($valor as $value){
echo "Banco: ID:{$value['id_db']} - Hostname:{$value['hostname']} - DBNAME: {$value['dbname']} - User:{$value['user_DB']} - PASS:{$value['password_DB']}<br>";
//Initialize your data
$username = $value[user_DB];
$pass = $value[password_DB];
....
}
}
At least this way, your data is then accessible outside your method
Your connect method would then look like this:
private static function conect(){
try {
if(self:: $instance==null):
$dsn = "mysql:host={$hostname};dbname={$dbname};charset=utf8";
self::$instance = new PDO($dsn, self::$username, self::$pass);
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
endif;
} catch (PDOException $e) {
echo "Erro: " . $e->getMessage();
}
I have a class that I am passing a query to, but the fatal error
function query on null'
occurs when attempting to run the query.
I echoed $mysql_statement and got
select * from users
which is the intended query, but in the context of the query statement it keeps telling returning the fatal error function query on null.
Any ideas on why the "select * from users" that is legitimately stored in $mysql_statement is being interpreted as null? (the properties used and not defined here are defined in a parent class):
The page.php:
<?php
include("includes/database_classes.php");
new database_connection;
new database_query("SELECT * FROM users");
?>
...and the database_classes.php:
<?php
/*----------------------------------------------------------------------------------------------------*/
class database_connection
{
protected $username = 'root';
protected $password = '';
protected $hostname = 'localhost';
protected $database = 'assistant';
protected $database_handle;
function connect()
{
try
{
$database_handle = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
}
catch (PDOException $e)
{
print "Error!: " . $e ->getMessage() . "<br/>";
die();
}
}
}
/*----------------------------------------------------------------------------------------------------*/
class database_disconnection extends database_connection
{
function disconnect()
{
$database_handle = null;
}
}
/*----------------------------------------------------------------------------------------------------*/
class database_query extends database_connection
{
protected $mysql_statement;
function __construct( $mysql_statement )
{
$this->mysql_statement = $mysql_statement;
echo $mysql_statement;
foreach($this->database_handle->query("$mysql_statement")->fetch_assoc() as $row) {
print_r($row);
}
}
}
/*----------------------------------------------------------------------------------------------------*/
I think you are having problem when trying to loop through the result of your SQL query, this happened because, you didn't include method "fetch_assoc()"
Instead of:
foreach($this->database_handle->query("$mysql_statement") as $row);
Why not?
foreach($this->database_handle->query("$mysql_statement")->fetch_assoc() as $row)
I have one DB class in which I am calling mysqli connect in constructor, I want to use this connection in another class. How I can do that, Do i have to reinitialize class first inside the class II ?? Or do I have to Inherit DB Class to class 2 ??
appreciate any guidance.
Thanks in advance,
Sambhav
Below are Rough outline of both the classes.
CLASS I - DB Class
class Db {
private $dbHost = "";
private $dbUser = "";
private $dbPass = "";
private $dbDatabase = "";
function __construct() {
$mysqli = new mysqli($this->dbHost, $this->dbUser, $this->dbPass, $this->dbDatabase);
if ($mysqli->connect_errno) {
echo "Error in connecting to database" . $mysqli->connect_error;
}
//echo "connected to database";
}
}
class II - The Class trying to use db connection
class MyClass {
private $details = array();
public function getDetails() {
$query = "SELECT `user` FROM `db`.`table`";
$result = $mysqli->query($query);
while ($row == $result->fetch_assoc()) {
//.........
}
return $details;
}
}
You can use a protected property within the class that is trying to use Db, for example;
class MyClass {
protected $objDb;
public function connectToDb() {
$this->objDb = new Db();
}
Then, within your getDetails method, use $this-> to "access" the Db class.
$result = $this->objDb->query($query);
And usage;
$objMyClass = new MyClass();
$objMyClass->connectToDb();
$objMyClass->getDetails();
Alternatively, you could put connectToDb method within your __construct()
Here is the full code: http://harrydenley.com/stackoverflow-25112589/ (Tested on my server and all works. I had to make a few changes, which you can see in the post)
I already have a database file that connects to a database when I include it
class-database.php
class dbFactory {
private static $host = 'some.host.com';
private static $name = 'someDB';
private static $user = 'someUser';
private static $pass = 'somePassword';
public function __construct() { }
public static function pdo() {
try {
# MySQL with PDO_MYSQL
return new PDO("mysql:host=$host;dbname=$name", $user, $pass);
}
catch(PDOException $e) {
echo $e->getMessage();
return null;
exit;
}
} // End: pdo()
} //End class
I usually access this by:
require( 'some-file-path' . 'class-database.php' );
$db = dbFactory::pdo();
Here is the question:
How can I access $db from within another class?
For instance, if I have a class file called class-html.php and within that class (AKA, as part of the class code) I need something like...:
class-html.php
class html {
...some code...
$db->query('SELECT * FROM tbl_head');
...some more code...
} //End: html
What I've been doing without success is:
require( 'some-file-path' . 'class-database.php' );
$db = dbFactory::pdo();
require( 'some-file-path' . 'class-html.php' );
I am getting error messages and am not sure what to do from here
You can use a Singleton class
class dbFactory {
//...
private static $pdo_instance = null;
private static function getPDOinstance() {
if (self::$pdo_instance === null) {
try {
self::$pdo_instance = new PDO("...");
} catch (PDOException $e) {
//...
}
}
return self::$pdo_instance;
}
}
When you now access dbFactory::getPDOinstance() you'll only have one PDO instance of creating new ones inside each class using the DB
Your class inside class-html.php can be modified a bit, along the following lines:
require( 'some-file-path' . 'class-database.php' );
class SomeClass {
public $db;
def __construct() {
$db = dbFactory::getPDOinstance();
// existing code ..
}
// other code
}
Then, you can require the class as usual and:
require( 'some-file-path' . 'class-html.php' );
$obj = new SomeClass();
$obj->db->query('SELECT * FROM tbl_head')
UPDATE: This will create a new PDO instance if you instantiate SomeClass more than once.
UPDATE: Made use of kingkero's answer to use existing dbFactory instance, instead.
I am new to php oop , so struggling a bit .
i have a database connection class viz :
class config{
protected $HOST = "localhost";
protected $USERNAME = "something" ;
protected $PASSWORD = "something";
protected $DATABASE = "something";
// Constructor - open DB connection
function __construct() {
try {
$this->db = new mysqli($this->HOST, $this->USERNAME, $this->PASSWORD, $this-
>DATABASE);
$this->db->autocommit(FALSE);
}
catch(Exception $e)
{
if($this->db->connect_errno > 0){
echo 'Caught exception: ', $e->getMessage(), "\n";
}
}
}
// Destructor - close DB connection
function __destruct() {
$this->db->close();
}
}
$api = new Config();
Now i have another class from which i need to perform some tasks ...but i get FATAL error .
second class :
class Myclass extends config {
function __construct(){}
public function myfunction()
{
try{
$stmt = $this->db->stmt_init(); /* Error here : Fatal error: Call to a member
function stmt_init() on a non-object */
$query = "SELECT ABC FROM table " ;
$stmt = $this->db->prepare($query); /* Error here : Fatal error: Call to a member
function prepare() on a non-object */
}
catch(){}
}
}
Please guide me with proper remedial code snippet
In your child class, you need to call the parent constructor. PHP won't automatically call parent constructor's when a child class is instantiated.
class Myclass extends config {
function __construct($h, $u, $p, $d){ parent::__construct($h, $u, $p, $d); }
Also, you don't have a $db property in the parent class, so add that
class config{
protected $db;
protected $HOST = "localhost";
protected $USERNAME = "something" ;
protected $PASSWORD = "something";
protected $DATABASE = "something";
Edit: Dependency Injection approach:
class config{
public $HOST = "localhost";
public $USERNAME = "something" ;
public $PASSWORD = "something";
public $DATABASE = "something";
}
class Myclass
{
protected $db;
function __construct($db)
{
$this->db = $db;
}
public function myfunction()
{
// do whatever with $this->db
}
}
$config = new Config();
try
{
$db = new mysqli($config->HOST, $config->USERNAME, $config->PASSWORD, $config->DATABASE);
$db->autocommit(FALSE);
}
catch(Exception $e)
{
if($db->connect_errno > 0){
echo 'Caught exception: ', $e->getMessage(), "\n";
}
}
$myclass = new Myclass($db);
Have a look into Dependency Injection. This is a favorable approach for dealing with classes that need access to a database. Instead of having all your classes extend the database, just pass the datsbase object as a parameter when creating new classes (that need the db).
Your derived class constructor is not calling the base constructor, so $this->db does not have the value it's supposed to. In PHP you must do this explicitly.
In this particular case, you should remove the derived constructor altogether since it's not doing anything. This will let PHP use the base constructor directly.