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();
Related
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.
I'm trying to learn how to properly code PHP OOP.
This is where I'm running into issues.
I created several classes that extend main Application class and I want to make things work properly.
I have main file that's index.php that looks like this:
include_once('classes/Application.php');
include_once('classes/Configuration.php');
include_once('classes/Database.php');
$app = new Application;
$config = new Configuration;
$db = new Database;
var_dump($app->db_connected);
var_dump($db->db_connected);
$db->connect($config->dbhost, $config->dbuser, $config->dbpass, $config->dbname);
var_dump($app->db_connected);
var_dump($db->db_connected);
The output is:
1. bool(false)
2. bool(false)
3. bool(false)
4. bool(true)
My main application file looks like this:
class Application {
public $db_connected = false;
}
And my Database class looks like this:
class Database extends Application {
function connect($dbhost, $dbuser, $dbpass, $dbname) {
if(!$this->db_connected) {
mysql_connect($dbhost, $dbuser, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
$this->db_connected = true;
}
}
}
So the question is, why would line #3 of the output of index.php display false? The db_connected property has been overridden in Database class and set to TRUE, but it still returns false.
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
Also when does the class EXTEND command occurs? Whenever parent class' instance is created or I have to manually create instance of the child class?
It seems you are reaching for the concept of of a static variable all instances of a class share the same static variable so using the new twice will not be an issue.
You can see the code on ideaone.
// your code goes here
class Application {
static $db_connected = false;
}
class Database extends Application {
function connect() {
if(!static::$db_connected) {
static::$db_connected = true;
}
}
}
$app = new Application;
$db = new Database;
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
$db->connect();
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
Your comment make me think you are looking for a better pattern all together. I would like to throw out some key principles namely OCP and LSP SOLID.
In this case you would avoid having Application being an instance of Database but instead use dependency injection. Here is the refactored code.
class Database {
private $db_connect = false;
public function connect () {
if(!$this->db_connect) { /* do connection */ }
}
}
class Application {
private $db;
public function setDatabse(Database $db) {
$this->db = $db;
}
public function getDatabase() {
return $this->db;
}
}
$db = new Database;
$app = new Application;
$app->setDatabase($db);
$app->getDatabase()->connect();
This line is your hint
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
You have 2 instances. Above you are checking $db instance which you connected with, and then you print from $app which was never connected. They are separate entities, one is connected one is not.
Extend occurs as soon as the file is loaded, read by the php interpreter, this happens regardless of ever using the class.
Extend is called from the child and inherits everything form the class it extends. So if you call a child method in the parent, well you are doing it backwards. It goes one way, Prent -> Child.
I would use Dependance injection for the database, then you can reuse it's code.
Like this:
//parent class
class Application {
//holds a reference to the Database class
protected static $db_conn = false;
public function __construct($db){
self::$db_conn = $db;
}
}
//child class of Application
class Application2 extends Application {
public function getSomething($id){
return self::$db_conn->getbyId($id) ;
}
}
//separate utility class
class Database{
static $conn;
public function __construct( $dbhost, $dbname, $dbuser, $dbpass, $dbname) {
static::$conn = mysqli_connect($dbhost, $dbuser,$dbpass,$dbname);
}
public function getbyId( $id ){
..code to get stuff by id using $conn - previous connection ...
return $result;
}
}
$db = new Database("myhost", "myuser", "mypassw", "mybd");
$app = new Application2( $db );
$app->getSomething(1);
//create another app with the same database connection, this is the value of injecting it.
$second_app = new Application2( $db );
See you can reuse database over and over, you can replace it without changing the code in Application as long as the calls for the functions of the Database class don't change. Each thing is responsible for it's own business.
This is called separation of concerns.
Inheritance is good, when it's needed. You might have an basic application for free users of you're services and then extend that with a premium application for paid members. Sense they paid they get all the free functionality, but also the premium stuff to.
In my example above the database is something they both need, as well as other things will probably use this. Such as a login system may need a database connection, payment system might, a shopping cart might. These are all separate objects, they don't / nor should they extend off of one Master Class, that's a bad idea. Keep them separate.
STATIC
I seen mention of the :: static object operator. My example is a bit flawed when using the static property protected static $db_conn = false;
$app = new Application2( $db );
$second_app = new Application2( $db ); //assigning db 2x is not needed.
The reason for :: and the -> normal way. Is that static :: is shared across all instance of a class, and -> is just this instance of the class. I had assigned the $db class to a static variable 2 times a better way would have been like this.
//parent class
class Application {
protected static $db_conn = false;
//separate method then construct.
public function connect($db){
self::$db_conn = $db;
}
}
//we'll keep the rest of the code the same here.
$db = new Database();
$app = new Application2();
$app->connect( $db );
$second_app = new Application2();
$second_app->getSomething(1);
Now in this example $second_app never ran it's connect method. But because the first $app did and because the static for the database variable protected static $db_conn. Now all classes that have extended the Application class have a database connection. This is what static does. It's value is shared across all instance of the class. So when you see :: think all class instance and when you see -> think only this class instance. It's actually one thing I love about php, makes it so much easier to keep track of then in some other languages.
Not to confuse you but the other use of the :: is not actually needing an instance at all. Assume you have a Config class like this.
class Config{
static $db = 'hello';
static $items = array('one' => 'item 1' );
private __construct(){} // no construction allowed
static function getItem( $which ){
return self::$items[$which];
}
}
Now without ever creating an instance of the class by calling new Config() , you can simply.
echo Config::$db;
// prints hello
echo Config::getItem('one');
// prints 'item 1'
This is quite use full for config type classes. Where they are an empty shell just used to store data in and you don't need an object for them, essentially a way to keep things organized. So tying this in to the previous examples
$db = new Database(Config::$myhost, Config::$myuser, Config::$mypassw, Config::$mybd);
In your case best OOP practice is to use Mediator pattern. Concrete Mediator will be Application class:
class ApplicationBase {
private $db;
private $cfg;
public function setDb(Database $db) {
$this->db = $db; return $this;
}
public function setConfig(Config $cfg) {
$this->cfg = $cfg; return $this;
}
}
class Application extends ApplicationBase {
public function getDsn() {
return $this->cfg->getDsn();
}
public function getDbUser() {
return $this->cfg->getDbUser();
}
public function getDbPass() {
return $this->cfg->getDbPass();
}
public function getConnection() {
return $this->db->getConnection();
}
}
class AppComponent {
protected $app;
public function __construct(Application $app) {
$this->app = $app;
}
}
class Config extends AppComponent {
private $dsn;
private $dbuser;
private $dbpass;
// ... getters and setters
}
class Database extends AppComponent {
private $connection;
private function connect() {
$this->connection = new PDO(
$this->app->getDsn(),
$this->app->getUser(),
$this->app->getPass()
);
}
public function getConnection() {
if (null === $this->connection) $this->connect();
return $this->connection;
}
}
class Model extends AppComponent {
protected $table;
// Model stuff here
}
class Content extends Model {
public function getNews() {
$db = $this->app->getConnection();
return $db->query("SELECT * FROM $this->table LIMIT 5")->fetchAll();
}
}
Such architecture will be enough for simple, clean-looking applications and classes will be ready for easy unit-testing:
$app = new Application();
$cfg = new Config($app);
$db = new Database($app);
$app->setDb($db)->setConfig($cfg);
$content = new Content($app);
$news = $content->getNews();
Im trying to understand objects & classes. But Im having a problem. Im trying to pass a variable from a class into another class.
Why Im doing this is mostly because I want to understand more how classs work but also for future where Im gonna need to send database connection into classes.
Here is my code simplified for the problem:
class databaseConnection
{
public function connect(){
return "localhost";
}
}
class like
{
private $database;
public function __construct(){
$this->database = databaseConnection::connect();
}
public function addLike()
{
return $database;
}
}
$obj = new like;
echo $obj->addLike();
But this doesn't show anything. What i thought the results would be is echo "localhost";
Why isn't this working?
connect is not a static method, you should either change it to static or create an instance.
// if you use databaseConnection::connect();
public static function connect(){
or
$db = new databaseConnection;
$this->database = $db->connect();
And you also need to change
public function addLike()
{
// use $this to access object property
return $this->database;
}
You are calling databaseConnection::connect() as a static method. Modify it to:
public static function connect(){ }
Edit - as #Shankar Damodaran pointed, also add:
public function addLike()
{
return $this->database;
}
First of all you should really follow convention and start naming classes StartingWithCapitalLetter.
Secondly, "::" operator is used to call static methods (to put it simply - you don't have to create object of a class to call them, if they are public).
Normally, to call object's method you use operator "->", like $object->method(arguments);
So in your case, you need to first create an object of your databaseConnection class (because you can't call methods on not-initialized methods) and then call "connect" on it, like that:
$connection = new databaseConnection();
$database = $connection->connect();
To pass a parameter, you need to modify the method declaration
public function connect($parameter){
return "Connecting to " ... $parameter;
}
and call it with
$database = $connection->connect($parameter);
On a sidenote, you should really use parenthesis when creating objects of a class, like:
$obj = new like();
echo $obj->addLike();
Also, as deceze pointed out, you need to access class variable using $this instead of accessing local method variable:
public function addLike()
{
return $this->database;
}
public function addLike()
{
return $this->database;
}
$database and $this->database are two different variables. $database is a local function variable which does not exist, it's not the object property you set before.
I am building an API in PHP and I have a question. I'm using classes, and some of these classes need to access my database. However, I don't want to define variables for the database in every single class in order to open it, or have to send my mysqli object as a parameter of every single class constructor.
What would be the best way to go about this? Do I define a global variable of some kind?
A classic solution would be as follows
Create an instance of dbatabase handler class, either raw mysqli (worse) or better abstraction class (way better)
In the constructor of your application class take this db class instance as a parameter and assign it to a local variable
Use this variable with your class.
A quick example:
class Foo()
{
protected $db;
function __construct($db);
{
$this->db = $db;
}
function getBar($id)
{
return $this->db->getOne("SELECT * FROM bar WHERE id=?i", $id);
}
}
$db = new safeMysql();
$foo = new Foo($db);
$bar = $foo->getBar($_GET['id']);
How about using a static classes?
class mysqli_wrapper {
private static $db = null;
public static function open() {
GLOBAL $opts; // this can be global or setup in other ways
if (!self::$db) {
self::close();
self::$db = null;
}
self::$db = #mysqli_connect('p:'.$opts['hn'], $opts['un'], $opts['pw'], $opts['db']);
return self::$db;
}
public static function query($qry) {
return mysqli_query ( self::$db, $qry );
}
public static function affected_rows() { return #mysqli_affected_rows(self::$db); }
public static function error() { return #mysqli_error(self::$db); }
public static function close() { #mysqli_close(self::$db); }
} // end mysqli_wrapper
mysqli_wrapper::open(); // Here's how to call it
In a system I maintain my app needs to access its own MySQL db, as well as remote Oracle and SQL Server databases, and I use a trait for it. Here's a simplification of my code, just using MySQL:
dbaccess.php
trait DatabaseAccess {
protected $db;
private $host = 'host', $dbName = 'db', $username = 'username', $password = 'pword';
public function connectToMysql() {
$this->db= new mysqli(......);
}
}
then in myclass.php
require 'dbaccess.php';
class MyClass {
use DatabaseAccess;
//class code.....
}
All elements of DatabaseAccess will be available as if you hand-typed them in MyClass.
Note: if you're using PHP < 5.4, then this solution won't be possible.
I've trying to learn PHP OOP and have made some research on how to make a global database class to use around in my project. From what I've seen the most appropriate pattern available is a singleton which would ensure that only one database connection are present at all times. However as this is my first time working with the Singleton pattern, I am not sure that I have made it right.
Is this a proper singleton? Will this code ensure one database connection only? Is there any way I can test this? (Learn a man to fish and he will have food for the rest of his life...)
I am using redbean as my ORM and here's how I set it up plainly:
require_once PLUGINPATH.'rb.php';
$redbean= R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
I've made the following script based upon this source, as my own singleton Database class;
class database {
private $connection = null;
private function __construct(){
require_once PLUGINPATH.'rb.php';
$this->connection = R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
}
public static function get() {
static $db = null;
if ( $db === null )
$db = new database();
return $db;
}
public function connection() {
return $this->connection;
}
}
Thanks!
The instance variable needs to be a static member of the class. I haven't tested this code, but it should work. Connection should probably be static too. With this code, you will have one instance of your database class, and one instance of the connection. It is possible to do this without connection being static, but making it static will ensure there is only one connection instance. I also changed the literal names of the class to php magic constants. This make your code more maintainable. If you change the name of your class down the road, you won't have to go and find all of the literal instances of the old class name in your code. This may seem like overkill now, but trust me, as you work on more and more complex projects, you will appreciate the value.
class database {
private static $connection = null;
private static $db;
private function __construct(){
require_once PLUGINPATH.'rb.php';
self::$connection = R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
}
public static function get() {
if ( !(self::$db instanceof __CLASS__) ) {
$klass = __CLASS__; // have to set this to a var, cant use the constant with "new"
self::$db = new $klass();
}
return self::$db;
}
public function connection() {
return self::$connection;
}
}
You're singleton is almost correct.
The private member (no pun intended) $connection needs to be static as well. You might go with the following too:
class database {
private static $instance = NULL;
protected $conn;
private function __construct() {
$this->conn = mysql_connect( ... );
}
public static function init() {
if (NULL !== self::$instance)
throw new SingletonException();
self::$instance = new database();
}
public static function get_handle() {
if (NULL === self::$instance)
; // error handling here
return self::$instance->conn;
}
}