2

So in php 5.* versions i would set up constructor to be private and then get only instance of it, and that worked well, memory usage was low.

class bsdb extends mysqli {

    private $host = '';
    private $account = '';
    private $password = '';
    private $database = '';

    private static $instance;
    private function __construct(){

        try {

            parent::__construct($this->host, $this->account, $this->password, $this->database);
            parent::set_charset('utf8');

        } catch (mysqli_sql_exception $e) {

            log(sprintf("Connect failed: %s\n", mysqli_connect_error()), 'sql');
            die('DB Connection error');

        }
    }

    static function instance() {

        if (!self::$instance)
                self::$instance = new bsdb;

            return self::$instance;
    }
}

But in php7 im no longer able to do that because version 7 of php doesnt allow me to make constructor private if im inheriting from class that has public constructor. It is throwing me an error.

So my question is what is the best way to do this in new version of php?

Andrea
  • 19,134
  • 4
  • 43
  • 65
madeye
  • 1,398
  • 3
  • 15
  • 33
  • 1
    Have you thought about composition instead of inheritance? Will it work in your case, if you'll hold an instance of a parent type inside your child type, that will no longer be a child, and delegate the calls to this instance instead of using inheritance chain? – Yury Fedorov Dec 22 '15 at 12:23
  • @Orlangure by composition mean using Traits? Yeah that is first option for me for now. Im just asking if anyone have something else maybe something more elegant :) – madeye Dec 22 '15 at 12:27
  • I didn't mean traits. In OOP composition is usually favored over inheritance, so maybe you may have an instance variable of your parent type in instance of the class that was supposed to be derived. Like two unrelated objects. Can you create an instance of mysqli in your unrelated class and return it instead? Or create simple methods like mysqli_query in `bsdb` class that will just call mysqli methods and return their results, if you don't want to return an instance of mysqli? – Yury Fedorov Dec 22 '15 at 12:32
  • @Orlangure i tried to implement composition but i would need to mimic a lot of mysqli functions in my class like prepare, autocommit etc...and in it i would just call native mysqli methods in my class. That sounds like a lot of work. – madeye Dec 22 '15 at 14:39
  • So why not just return a connection? – Yury Fedorov Dec 22 '15 at 14:40

1 Answers1

4

In your question you describe the root of your problem as this:

But in php7 im no longer able to do that because version 7 of php doesnt allow me to make constructor private if im inheriting from class that has public constructor. It is throwing me an error.

It is correct that PHP 7 will give you fatal error similar to the following where Bar with a private ctor extends from Foo with a public one:

Fatal error: Access level to Bar::__construct() must be public (as in class Foo)

However you create the wrong impression that this should have worked in PHP 5 and is only prohibited since PHP 7. Rest assured, this is not the case.

Visibility to methods (including constructor methods) has been introduced in PHP 5 and you get the fatal error since the first PHP 5 release. See it in action with many today even unsupported PHP versions: https://3v4l.org/pfcBm

As visibility is part of the language since version 5 I can't see this is a PHP 7 issue but only for the very specific class mysqli.

However you don't need to make the ctor private. All you need is the single instance, not an implementation of the singleton pattern. A quick relief is to make the ctor public and just use the bsdb::instance() global static method to obtain that specific bsdb instance. From what is visible in the question, the main responsibility of that class is to manage the global variable within that global static method and to have the database configuration properties with constant values.

I would normally argue that the class you present does too much at once (instance creation and lifetime management, database configuration handling and last but not least being a mysqli) which is in times of change most often a burden and normally for that alone a good example why you should keep things apart that don't belong together.

A classic read here on stackoverflow that will perhaps help you to better identify and re-think your singleton needs:

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836