This question already has an answer here:
Cannot redeclare class - php [closed]
(1 answer)
Closed 6 years ago.
i recently started learning PDO and OOP to make my websites safer and faster. i am having some issues with OOP in PHP.
i have a folder named res (short for resources) and a folder named classes and an index.php file, in the res folder i have a menu.php file that needs two classes named class.ManageUsers.php and class.ManageNews.php. in both of these files i am including class.database.php, here is the code for that file:
<?php
class dbConnection {
protected $db_conn;
public $db_name = 'red_sec_net';
public $db_user = 'root';
public $db_pass = '';
public $db_host = 'localhost';
function connect(){
try{
$this->db_conn = new PDO("mysql:host=$this->db_host;dbname=$this->db_name;",$this->db_user,$this->db_pass);
$this->db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->db_conn;
$this->conn = null;
}catch(PDOException $e){
die('failed to connect to database');
}
}
}
?>
now in the index.php file i need class.ManageUsers.php so i include it just before i include menu.php but when i go to that page i get this error:
Cannot redeclare class dbConnection in C:\wamp64\www\redsec\classes\class.database.php on line 3
the people i consulted said i should close the connections so i did that using
$this->link = null; and all the other variables that contained anything related to the connection after i do return what i need.
this is my constructor method:
class ManageUsers {
public $link;
function __construct(){
$db_connection = new dbConnection();
$this->link = $db_connection->connect();
return $this->link;
$this->link = null;
}
}
all my attempts have failed and i am starting to pull my hair out any help appreciated
i believe the error is happening in the constructor method when i do $db_connection = new dbConnection();
When your PHP app loads, the interpreter comes across the same class declaration more than once.
Try this:
include_once or require_once (if multiple inclusions of the same file happen)
Probably this could be a duplicated:
Cannot redeclare class - php
Related
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();
Please look at my databaseClass I Used a public property Called "connection" but I'm unable to access that property other .php files. I'm learning OOP PHP. Please help me.
Here is the other File link http://pastebin.com/0Nh1uc8D
<?php
require_once('config.php');//calling config.php
class Database{
public $connection;//property
//__construct();
public function __construct(){
$this->openDbConnection();
}
//method
public function openDbConnection(){
$this->connection = mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if (mysqli_connect_errno()) {
# code...
die("Database Connection Failed Badly" . mysqli_error());
}else{
echo "DB Connected Successfully.";
}
}
}
//instance of the class
$database = new Database();
?>
Here is my confi.php file code
http://pastebin.com/wQ9BFGf4
Thanks in Advance.
For global access of classes and properties you can use it as static properties and methods:
class Database
{
public static $connection;//property
//method
public static function openDbConnection()
{
self::$connection = mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if (mysqli_connect_errno()) {
# code...
die("Database Connection Failed Badly" . mysqli_error());
}else{
echo "DB Connected Successfully.";
}
}
}
// once "create" connection
Database::openDbConnection();
// and for all other files
var_dump(Database::$connection);
The problem is that $database isn't definied at all by line 16 adminContent.php, if that is indeed all the code for that file in Pastebin.
You're getting distracted by the public property scope, that's working fine as-is. Public properties are definitely accessible from other files not included in other function or class scopes, but only if you've actually required the file that instantiates the $database object in the first place.
Without showing us more code on how adminContent.php is being included from, we can't debug why $database isn't instantiated by line 16.
Use a debugger to trace the code execution flow, or just add echo's or error_log's to both the database instantiation file and to adminContent.php code and run it. I think you'll find that $database isn't instantiated at all, or at least before you're accessing it in adminContent.php
This question already has answers here:
What is the difference between public, private, and protected?
(16 answers)
Closed 7 years ago.
I have a dbHandeller.php file . as follow
class dbHandeler {
var $conn;
public function __construct(){
$this->initiatedb();
}
private function initiatedb(){
//Details of the Databse
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "xxxxxx";
// Create connection
$this->conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$this->conn) {
die("Connection failed: " . mysqli_connect_error());
}else
return $this->conn;
}
private function sql_query($query){
}
}
Then I have donation.php and it extends the DB class
function __autoload($class_name) {
include $class_name . '.php';
}
class donation extends dbHandeler{
public function __construct(){
$dbObj = new dbHandeler();
$dbObj->initiatedb();
}
public function putDonation(){
var_dump($_POST);
}
public function getDonation(){
}
}
When I try to access the donation class I am getting following error
<br />
<b>Fatal error</b>: Call to private method dbHandeler::initiatedb() from context 'donation' in <b>C:\xampp\htdocs\templeform\api\donation.php</b> on line <b>13</b><br />
error
The "private" access specifier is meant to be available within the class it is defined only, you cannot call it from outside the class it is defined in, even from a child class. You can maybe use the "protected" access specifier instead which will be available to the child classes as well but not the other classes. Hope this helps.
If the method is private, there is a reason, why the method is private. A private functions could only be called inside the class. If the method should be available in inherited classes, you should mark the function protected.
If the function should be accessible from everywhere, it must be public.
If you want to change the accessibility of the function, you could do so with ReflectionMethod::setAccessible - but doing this is most often a good indicator for a bad design.
$method = new ReflectionMethod('dbHandeler', 'sql_query');
$method->setAccessible(true);
If you dont want to change the accessibility, you could also use reflection to invoke the method directly, which might be the better option.
Nevertheless you should really think about you design. If this is your own class, why don't you just mark the function public or protected?
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to access mysqli connection in another class on another page?
I have a PHP class for connecting to a MYSQLi database and I want to use this class within another class to create a prepared statement and display some info from a database.
Is this possible at all?
<?php
class database {
public $host = "localhost";
public $user = "root";
public $password = "root";
public $name = "store";
public function connect() {
$connect = new mysqli($this->host, $this->user, $this->password, $this->name);
if($connect->connect_errno > 0){
die('Unable to connect to database [' . $connect->connect_error . ']');
}
}
}
class products {
// In here I want to use a MYSQLi prepared statment to show some information
// from the database details in the class above
}
$database = new database();
$database->connect();
?>
Thanks in advance!
Instead of connecting in the other class, you have to connect somewhere in bootstrap, getting class instance into variable. Then you'll be able to either pass this variable into constructor parameters or simple use
global $db;
$this->db = $db;
in constructor
By the way, I see no use for separate connect() method. Why not to connect right in the constructor?
Also let me suggest you not to use die() but trigger_error() (or exception) instead.
I'm kinda new to PDO with MYSQL, here are my two files:
I have a connection class that I use to connect to the database:
class connection{
private $host = 'localhost';
private $dbname = 'devac';
private $username = 'root';
private $password ='';
public $con = '';
function __construct(){
$this->connect();
}
function connect(){
try{
$this->con = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username, $this->password);
$this->con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'We\'re sorry but there was an error while trying to connect to the database';
file_put_contents('connection.errors.txt', $e->getMessage().PHP_EOL,FILE_APPEND);
}
}
}
I have an account_info class that i use to query the data from the database:
class account_info{
function getAccountInfo(){
$acc_info = $this->con->prepare("SELECT * FROM account_info");
$acc_info->execute();
$results = $acc_info->fetchAll(PDO::FETCH_OBJ);
foreach ($results as $key) {
$results->owner_firstname;
}
}
}
I include both these files in my index.php page:
include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';
$con = new connection();
$info = new account_info();
$info->getAccountInfo();
I just cant get it to work I'm not getting any output, I think it has something to do with the scope, but I don't know the correct why to fix it as I'm new to this PDO and OOP stuff.
Thanks in advance.
Solution 1
Replace class account_info { with class account_info extends connection {
Replace
$con = new connection();
$info = new account_info();
with
$info = new account_info();
and it should work.
Solution 2 (suggested)
I highly suggest you to solve your problem with dependency injection in this case.
Just replace your account class with:
class account_info {
private $con;
public function __construct(connection $con) {
$this->con = $con->con;
}
public function getAccountInfo(){
$acc_info = $this->con->prepare("SELECT * FROM account_info");
$acc_info->execute();
$results = $acc_info->fetchAll(PDO::FETCH_OBJ);
foreach ($results as $key) {
$results->owner_firstname;
}
}
}
and use it in index.php like this:
include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';
$con = new connection();
$info = new account_info($con);
$info->getAccountInfo();
Explanation
As a general good rule: always specify the scope keyword for functions (public, protected or private).
The first solution is called inheritance and what we basically did was extending the account class with the connection class in order to inherit all the methods and properties from the connection class and easily use them. In this case you have to watch out for naming conflicts. I suggest you to take a look at the class inheritance in the PHP manual.
The second solution is called dependency injection and it is a wildly encouraged design pattern that makes your classes accept other classes in their constructor in order to explicitly define the class dependency tree (in this case account depend from connection and without the connection we can't make account work).
Another, of thousands of possible solution, would be the one that someone posted below which is a design pattern called Singleton. However that patter has been reevaluated recently as anti-pattern and should not be used.
A common method is to use a singleton pattern in your database class.
Something like this:
class connection {
private static $hInstance;
public static function getInstance() {
if (!(self::$hInstance instanceof self)) {
self::$hInstance = new self();
}
return self::$hInstance;
}
/* your code */
}
Then, you can simply use
$database = connection::getInstance();
$database->con->prepare(....)
etc