I have a class address_book in which I want to set $DBConnection using method from another class:
<?php
class address_book
{
protected $DBConnection;
public function __construct()
{
$this->DBConnection=new address_book_db();
$this->init();
}
public function init()
{
add_shortcode('address_book', array($this,'load'));
}
public function load()
{
var_dump($DBConnection);
}
}
Another class:
<?php
class address_book_db
{
protected $dbconnection;
public function __construct()
{
$this->dbconnection='1';
}
}
So var_dum should return '1' as it has to be assigned to protected $DBConnection; in the first class. I'm starting my learning of PHP OOP so probably everything is bad.
Any way it has to work like this.
In first class I load db name which is being loaded from another class using methods which determines db name (not developed yet because I just want to pass this constructed dbname to first class).
You're missing $this-> to refer to the class property.
The property's value contains another class, so you have to refer to that class its property as wel with a second ->
var_dump($this->DBConnection->dbconnection)
Related
I am building an MVC component and I'm getting stuck with an issue with a parent and child model. I have a few methods in the parent Model and they're not working with the database_class object
the constructor works fine
but when I use that object in the methods its like the constructor doesn't exist?
Class Controlller
{
public function __construct()
{
$this->childModel = $this->model('childModel');
} // end construct
// methods go here
}
Here are the models:
class childModel extends parentModel {
private $dbo;
public function __construct()
{
$dbobj = new Database_class;
$this->dbo = $dbobj;
}
//methods
}
class parentModel {
private $dbom;
public function __construct()
{
$dbombj = new Database_class;
$this->dbom = $dbombj;
var_dump($this->dbom); //working perfectly as database object
}
public function methodName()
{
var_dump($this->dbom); //not showing up as database object
}
}
I don't think this code is doing what you think it's doing. In childModel, you are overwriting the __construct method of the parentModel, so the __construct in the parentModel never gets called. Therefore $this->dbom should be null. Furthermore if you wish to use $this->dbom from the childModel, you should probably change the scope from private $dbom to protected $dbom. See this page for more info on that: http://php.net/manual/en/language.oop5.visibility.php
If I have a base abstract class like so:
<?php
abstract class Record {
static $table;
public function getRows () {
return getRowsFromTable(static::$table);
}
}
?>
And I want to extend this class like so:
<?php
class User extends Record {
static $table = 'users';
private $name;
?>
Then if I call:
<?php
$user = new User;
$user->getRows();
?>
Internally, getRows() calls and returns getRowsFromTable('users').
But if I were to create another class that also extends Record:
<?php
class House extends Record {
static $table = 'houses';
private $address;
?>
Then that static $table = 'houses'; declaration overrides the Record::$table and, consequently, breaks the User class.
What's happening is, the declaration static $table = 'houses'; bubbles up to the parent class, so now Record::$table = 'houses';. Since House was declared after User, the next time I call $user->getRows(), internally, User references parent Record and ultimately calls getRowsFromTable('houses') instead of getRowsFromTable('users').
I'm using late static binding so as to get the property from the extended class; but since User and House extend the same parent class, they both end up with the same property value although they override it with different values.
If I were to duplicate the Record class by creating a class Record2 and having House extend Record2, I wouldn't have this problem -- but that wouldn't really help.
Is this the wrong setup? Should I not be using static variables in this context? What should I put in their place, if so? I know that $table doesn't necessarily have to be static, but there are other properties that may need to be static.
I really wouldn't use a static string for this purpose.
How about something like this...
abstract class Record {
/**
* #return table name as string
*/
abstract protected function getTable();
public function getRows () {
return getRowsFromTable($this->getTable());
}
}
Then, your concrete implementations would have to implement getTable, eg
class User extends Record {
protected function getTable() {
return 'users';
}
}
Probably a silly question, I have many classes in PHP with this template:
class SomeTable {
private $db;
private $prefix;
private $tbl_name;
function __construct($db, $tbl_name) {
$this->db = $db;
$this->prefix = $db->tblPrefix();
$this->tbl_name = $tbl_name;
$this->install();
}
private function install() {
$sql = "CREATE TABLE IF NOT EXISTS...";
$this->db->query($sql, null);
}
// query functions
...
}
I have one of these classes to represent each table in the database.
The 3 private variables at the top must be available in each class,
and they are set in the constructor.
The constructor is the same for every class.
The install() function is different for every class because it is
used to create the database table. (I like to keep it here because
I can keep looking back at it while I'm writing/editing queries).
Do I then create an abstract class with the 3 variables, constructor, empty install() function and implement it in each class? Will it work the same for me?
I'm sorry if it's a dumb question, I've really never used classes/inheritance before in PHP.
Do I then create an abstract class with the 3 variables, constructor,
empty install() function and implement it in each class? Will it work
the same for me?
Yes. The 3 variables will have to be protected now though, instead of private, since they need to be access from child classes. Something like this:
abstract class DBTable{
protected $db;
protected $prefix;
protected $tbl_name;
function __construct($db, $tbl_name) {
$this->db = $db;
$this->prefix = $db->tblPrefix();
$this->tbl_name = $tbl_name;
}
abstract function install();
}
class SomeTable extends DBTable {
private function install() {
$sql = "CREATE TABLE IF NOT EXISTS...";
$this->db->query($sql, null);
}
}
If you extend a class you will inherit any public or protected methods that exist in the parent class. So if you have a class like so:
class Database {
public function get_database(){
return 'blah';
}
}
And then you extend the class like so:
class Blah extends Database {
...
}
Now, the Blah class will inherit the method get_database() so both Database::get_database() and Blah::get_database() will return the same thing. You can also use the parent:: special name to target the extended class. Note: private methods are only available in the class in which they are instantiated and are not inherited.
I should also note that you can override methods by using the same method name in the child class. So if you write a get_database() method within the Blah class, it will take precedence over the parent's method of the same name.
I'm working on a sql class, and trying to figure out how to retrieve data from an external php file, to be available in the entire class.
Im guesing i have to do something like this:
class sqlQuery {
protected $database = array();
function __construct(){
require_once (config.php);
}
}
class model extends sqlQuery {
function __construct() {
$this->connect($this->database['hostname'], $this->database['user'], $this->database['pass'], $this->database['database']);
}
}
The file might contain other information in the future, so I want it available to more then just the extended class.
Firstly you should call parent constructor in class model:
function __construct() {
parent::__construct();
// your other logic there
}
Then just change constructor of your parent class for filling $this->database array
I am new to OOP (PHP) and just met the design pattern - singleton.
I have found a DB class which uses mysqli (singleton class). I have added some custom methods to it (insert_id(), query(), fetch_result(), etc).
Then I created a new class called UserTools and I want to extend the database class to use the methods I've created previously (query(), fetch_result(), etc).
But I get this error:
Fatal error: Call to private Database::__construct() from invalid context in (...)
when I try to create instance of the new class (User Tools).
What should I do? Is it a right structure?
There are several way to achieve what you want.
One would be :
class UserTools {
private $db;
function __construct() {
$this->db = Database::db_connect();
}
function login() { /* ... */}
}
Although it would be better to directly pass the database instance to the constructor like this :
class UserTools {
private $db;
function __construct($db) {
$this->db = $db;
}
function login() { /* ... */}
}
// Usage
$userTools = new UserTools(Database::db_connect());
If you're really lazy you could just modify your database class and make the constructor public :
class Database {
/* ... */
public function __construct(){/* ... */}
/* ... */
}
class UserTools extends Database {/* ... */}
But I really discourage you to use the latter one. It's really bad code and it doesn't make sense in a logical point of view. Your UserTools class use a database instance. It is not a database.
It is my understanding that only protected and public methods and variables are inherited through extension, not private ones. Try changing your methods/variables from private to protected. public ones are visible to all.
For more information, See: PHP Visibility (Manual)
Edit
Understand the Singleton pattern. It is called 'singleton' because only one instance of a class is expected. Because of this, most classes implementing the singleton pattern define the constructor as private to restrict you from creating more than one.
To create an instance of a singleton, most classes define some kind of getInstance static method, which is public. This public method calls the private constructor, which probably sets flags indiciating that the class has been instantiated in order to prevent further attempts to instantiate the class. The getInstance method returns the results of calling the constructor, essentially the instance of the class.
You could write something like
class UserTools extends DB {
....
}
A quick example on inheritance in PHP:
class A {
public $a;
public function set_a($new_a) { $this->a = $new_a; return $this; }
public function get_a() { return $this->a; }
}
class B extends A {
public $b;
public function set_b($new_b) { $this->b = $new_b; return $this; }
public function get_b() { return $this->b; }
}
$objb = new B();
$objb->set_a("Some Value")->get_a(); //Some Value
The singleton pattern in most cases prevents instantiating the Singleton class by defining the constructor as private (ie private function __construct()).
So if you try to instantiate either your custom class or the original one that you're extending you will get the message above. You should either create a different class or define and use your function as static (eg public static function query($sql, $dbconnection)).
See http://php.net/manual/en/language.oop5.patterns.php