简体   繁体   中英

PHP Singleton extending class

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?

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM