I am trying out a MVC concept where the main model for a database stems or trees off other models. I wanted to have a main database sort of model which does the connecting and queries. Then, other models are built to support the controller. Ie, a product model can be extended off the main database model to then query rather than using dependency injection.
My current ideology and attempt looks like this for the main database model:
namespace Portfolio\Application;
abstract class DriverModel {
private static $driver;
private $entity;
private function __construct() {
// Connection to the PDO will be done in here
}
private function __clone() {}
public static function getInstance() {
if(self::$driver)
return self::$driver;
self::$driver = new self();
return self::$driver;
}
protected function q($sql, $values = []) {
$stmt = $this->entity->Prepare($sql);
$stmt->execute($values);
return $stmt;
}
}
Then my example profile controller would look something like this (having the methods to use the main database to run queries):
class ProfileModel extends DriverModel {
public function doSomeQ() {
$this->q('SELECT fname FROM users WHERE id = ?', [(int)1]);
}
}
However, When I execute this line of code:
print_r(ProfileModel::getInstance()->doSomeQ());
I am left with this error: (which makes sense.)
Uncaught Error: Cannot instantiate abstract class.
I then remove the abstract attribute from the class (class DriverModel) but now, the instance I am receiving is the instance from the parent class meaning if I do a print_r() on the getInstance() method to the ProfileModel, there is no doSomeQ() method.
Any help on achieving this methodology would be helpful.
You have to use get_called_class() method instead of new self();
http://php.net/manual/en/function.get-called-class.php
Attached you can find sample who show your expected behaviour
class Main {
public static function getInstance() {
$class = get_called_class();
return new $class();
}
}
class Foo extends Main{
}
var_dump(Foo::getInstance()); // Output Foo object
Related
Lets say i have a singleton class with the sole purpose of creating singletons:
class singleton {
public static function getInstance() {
static $instance = null;
if($instance === null) {
$instance = new self;
}
return $instance;
}
}
And a custom database class extending the default one:
class database extends mysqli {
// obvious stuff
}
I now want to be able to have the database class being a children of both, the singleton (for the singleton creation) and the mysqli-class. Basically something like:
class database extends singleton {}
class database extends mysqli {}
According to my research, this is not possible in PHP.
What I'm trying to achieve is, having another method called getInstance() in the database class (so, this method is present in the classes "database" and "singleton", which then first calls the parent constructer (that creates the singleton) and then returns to the child to continue with custom stuff for the corresponding class. Like this:
class singleton {
public static function getInstance() {
static $instance = null;
if($instance === null) {
$instance = new self;
}
return $instance;
}
}
class database extends singleton {}
class database extends mysqli {
public static function getInstance() {
$instance = parent::getInstance();
// Custom code
return $instance;
}
}
Is that somehow possible? I thought about traits, but you cannot call them as parents.
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
So currently my class DATABASE uses a singleton for a connection and is called in the constructor of my class SQL. I have 4 other classes that extend class SQL for access to its methods. The problem is, the children instantiate each other in some cases so I'm afraid I'm creating multiple class SQL objects because they call their parent constructor by default, aka class SQL. I read about dependency injection, but no clear how to implement it in my situation so this is what I was thinking.
Have all classes extend class DATABASE and make class SQL methods static.
But then I would have to call the singleton connection in class DATABASE, on its own class as so.
class DATABASE {
function __construct() {
self::getInstance();
/// or DATABASE::getInstance ( im not quite positive which way )
}
public static function getInstance() {
if (self::$instance == false) {
self::$instance = new DATABASEMANAGER();
}
return self::$instance;
}
}
I figure this way, since all classes extend class DATABASE, and instantiate each other, I know I am not creating multiple objects.
I hope this makes sense and I can elaborate more if you need me to, but does this make since as an approach to my problem?
I guess you building your class other way around, this approach is more consistent in my opinion.
class DATABASE extends DATABASEMANAGER
{
static $instance;
private function __construct()
{
parent::__construct();
}
public static function getInstance()
{
if (empty(self::$instance))
{
self::$instance = new self();
}
return self::$instance;
}
}
Usage:
class Blog
{
public function __construct()
{
$this->database = DATABASE::getInstance();
}
public function getRecord($id)
{
$result = $this->database->query("SELECT * FROM blog WHERE id='{$id}'");
//or
$result = DATABASE::getInstance()->query("SELECT * FROM blog WHERE id='{$id}'");
//other actions...
}
}
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
Hello i want to make something on classes
i want to do a super class which one is my all class is extended on it
____ database class
/
chesterx _/______ member class
\
\_____ another class
i want to call the method that is in the database class like this
$this->database->smtelse();
class Hello extends Chesterx{
public function ornekFunc(){
$this->database->getQuery('popularNews');
$this->member->lastRegistered();
}
}
and i want to call a method with its parent class name when i extend my super class to any class
I'm not quite sure what you mean by your last sentence but this is perfectly valid:
class Chesterx{
public $database, $member;
public function __construct(){
$this->database = new database; //Whatever you use to create a database
$this->member = new member;
}
}
Consider the Singleton pattern - it usually fits better for database interactions. http://en.wikipedia.org/wiki/Singleton_pattern.
you could also consider using methods to get the sub-Objects
The advantage would be that the objecs are not initialized until they are need it, and also provides a much more loosely coupled code that lets you change the way the database is initialized more easy.
class Chesterx{
public $database, $member;
public function getDatabase() {
if (!$this->database ) {
$this->database = new database; //Whatever you use to create a database
}
return $this->database;
}
public function getMember() {
if (!$this->member) {
$this->member = new member;
}
return $this->member;
}
}