I'm new to using namespaces. In this example I made class, which handles database connection and I'm trying to use it inside the other classes. Can you explain what is wrong?
Connection.php
namespace Database;
class Connection
{
private static $instance = null;
private $pdo;
private function __construct()
{
$this->pdo = new PDO("mysql:host=localhost;dbname=database;", "root", "pw");
}
public static function get()
{
if (is_null(self::$instance))
self::$instance = new Connection();
return self::$instance;
}
}
Auth.php
namespace PHPAuth;
use Database\Connection;
class Auth
{
protected $dbh;
public function __construct()
{
$this->dbh = Connection::get();
...
Thanks in advance.
Edit: Ok, now I included autoloader and including class is now working correctly. But now I'm getting error when using $dbh in Auth like $query = $this->dbh->query("SELECT * FROM...");
Fatal error: Call to undefined method Database\Connection::query()
in...
First issue with class not found
I'll add the answer (which worked for you) for the first issue for reference: "Namespaces doesn't automatically load the files. You need to add an autoloader for that."
Second issue with undefined method
Fatal error: Call to undefined method Database\Connection::query()
The answer is in the error message. You've made the class Database\Connection into a singleton where Database\Connection::get() returns an instance of itself (which doesn't have any ->query() method), and not the actual PDO instance.
If you want that method to return the PDO instance instead, I would do something like this:
namespace Database;
use PDO;
class Connection
{
private static $pdo;
private function __construct()
{
// Leave the constructor private so it still becomes
// a singleton and so we can't instantiate this class.
}
public static function get()
{
if (is_null(self::$pdo)) {
self::$pdo = new PDO("mysql:host=localhost;dbname=database;", "root", "pw");
}
return self::$pdo;
}
}
Now the Connection class have become a Factory for the PDO-connection.
Connection::get() will return the same PDO instance over and over and you should be able to call $this->dbh->query("...") from your Auth class.
Related
I'm trying to use an existing class which has my DB connection in it to make a call within a new class. Here is my code to do this:
class ajaxHandler {
protected static $db;
function __construct() {
if (!class_exists('Db')) {
include "db_class.php";
$db = new Db();
}
}
function show_contest_details ($contest_id){
echo "The contest id is: ".$contest_id;
$event__conetest_details = $db->select("SELECT * FROM FF_CREATE_EVENT");
} // end of show_contest_details function
}
I am getting the following errors:
Notice: Undefined variable: db in /var/www/ajax_class.php on line 18
Fatal error: Call to a member function select() on a non-object in /var/www/ajax_class.php on line 18
How can I use my DB class within this class?
You've forgotten about self:::
class ajaxHandler {
protected static $db;
function __construct() {
if (!class_exists('Db')) {
include "db_class.php";
}
self::$db = new Db();
}
function show_contest_details ($contest_id){
echo "The contest id is: ".$contest_id;
$event__conetest_details = self::$db->select("SELECT * FROM FF_CREATE_EVENT");
} // end of show_contest_details function
}
Second thing, it is better to move code creating instance of Db outside the conditional block. You may accidentally include Db in other place, and then ajaxHandler will stop working, and you will not understand easily why.
You use class_exists() to test whether or not you have created the database. That is not correct. class_exists() checks if the class has been defined, which is true after PHP has loaded the file, not after it has created the first instatiation of the class. What you need is this:
class ajaxHandler {
protected static $db;
function __construct() {
if (is_null(self::$db)) {
include "db_class.php";
self::$db = new Db();
}
}
}
I don't seem to be able to access the parent class constructor In PHP.
Here is the code
class Mysql
{
const SERVER, USER, PASSWORD, DB;
function Mysql()
{
return mysqli_connect(self::SERVER, ETC);
}
}
class Mysql_Select extends Mysql
{
function Mysql_Select()
{
$conn = new Mysql();
etc
}
}
I'm trying to keep the actual connection in the parent class, but I get the non-object error.
You're doing it wrong
First thing is that PHP4-style constructors are deprecated, use __construct method to define a costructor.
Second is that you must not return from constructor but rather keep the connection object inside class as instance property.
Third is that you must call parent methods using parent keyword.
class Mysql
{
const SERVER, USER, PASSWORD, DB;
protected $conn;
function __construct()
{
$this->conn = mysqli_connect(self::SERVER, ETC);
}
}
class Mysql_Select extends Mysql
{
function __construct()
{
parent::__construct();
// use $this->conn here from the parent class.
}
}
So I have two files involved in this problem. One of them is the Database class and the other one is the file that include_once the Database file and then goes on to instantiate an object of that class to call a function -- getDB();.
Thats's where it goes wrong.
Database class:
<?php
class Database {
private static $datasource='mysql:host=localhost; dbname=db_name';
private static $username='root';
private static $password='root';
private static $db;
private function __construct(){}
public static function getDB(){
if(!isset(self::$db)){
try{
self::$db=new PDO(self::$datasource,self::$username,self::$password);
}
catch(PDOExceptin $e) {
$error=$e->getMessage(); //variable $error can be used in the database_error.php file
//display database error file.
//include('database_error.php');
exit();
}
}
return self::$db;
}
function Database(){
return new Database;
}
}
?>
And in my main file, I'm doing this:
<?php
include('partials/header.php');
include_once('functions/pdo.php');
$database = new Database();
$getdb = $database->getDB();
//Anything below won't show because of the failed instantiation of Database object above.
//code..
?>
Obviously, I'm doing something wrong here. I'm running MAMP with php 5.3.
How can I use my Database correctly? The reason I have a function with the same name as the class is because I read that you could instantiate the object with the function instead, but I didn't get that to work either...
You have a few errors here (use ini_set("display_errors", 1); error_reporting(-1); to see all your error messages):
The exception class of PDO is named PDOException and not PDOExceptin.
You call a static function from an non-static context: $database->getDb() where getDb is a static method. (write Database::getDb())
You write new Database which will result in a fatal error as the constructor is private (and named constructors have lower precedence than the magic method). Use there:
$getdb = Database::Database(); // and declare your Database method as static
PDOExceptin should be PDOException.
Also, it helps to turn display_errors on and to install xdebug when developing.
Obviously, I'm doing something wrong here.
Yes. you're writing way too much code.
The more code you write, the more errors you have. So, just get rid of all the useless code:
class Database {
private static $datasource='mysql:host=localhost; dbname=db_name';
private static $username='root';
private static $password='root';
private static $db;
public static function getDB(){
if(!isset(self::$db)){
self::$db=new PDO(self::$datasource,self::$username,self::$password);
}
return self::$db;
}
}
and call it this way
$db = Database::getDB();
Im having problems extending a Class.
This is what I was trying to do:
class Core
{
protected $db;
public function __construct()
{
$this->set_db_class();
}
private function set_db_class ()
{
include_once ( './classes/Database.php' );
$this->db = new Database();
}
}
class Functions extends Core
{
public function __construct()
{
parent::__construct();
}
public static function create_user ()
{
$this->db->query ( "INSERT ..." );
}
}
So, that's the estructure, but my problem is that I'm getting the following error:
Fatal error: Using $this when not in object context in /Applications/XAMPP/xamppfiles/htdocs/own/newsite/classes/class.Functions.php on line 10
What can I do to solve this?
Declare create_user as non-static and call it from an instance, otherwise (as the error message says) you cannot access $this, since $this is always a reference to the current instance. In a static context, there isn't one.
$functions = new Functions();
$functions->create_user();
instead of
Functions::create_user();
If you want to bundle functions that are not logically related to each other, use a namespace and not a class. You can go with an all-static class (every tiny property and method is static so that you don't need an instance at any time), but that's a horrible solution and not what classes should be used for.
Let's say I'm writing a PHP (>= 5.0) class that's meant to be a singleton. All of the docs I've read say to make the class constructor private so the class can't be directly instantiated.
So if I have something like this:
class SillyDB
{
private function __construct()
{
}
public static function getConnection()
{
}
}
Are there any cases where __construct() is called other than if I'm doing a
new SillyDB()
call inside the class itself?
And why am I allowed to instantiate SillyDB from inside itself at all?
__construct() would only be called if you called it from within a method for the class containing the private constructor. So for your Singleton, you might have a method like so:
class DBConnection
{
private static $Connection = null;
public static function getConnection()
{
if(!isset(self::$Connection))
{
self::$Connection = new DBConnection();
}
return self::$Connection;
}
private function __construct()
{
}
}
$dbConnection = DBConnection::getConnection();
The reason you are able/would want to instantiate the class from within itself is so that you can check to make sure that only one instance exists at any given time. This is the whole point of a Singleton, after all. Using a Singleton for a database connection ensures that your application is not making a ton of DB connections at a time.
Edit: Added $, as suggested by #emanuele-del-grande