3

I have a basic Database class, and it has a mysqli property (an object itself) which contains the connection information. Other classes uses this class to read and manipulate the database.

There are built-in functions in any database connection object (in this case, PHP's mysqli::multi_query, mysqli::next_result etc.), that I need to use in other classes.

The problem is that I really do not want to set the connection property as public since I believe it is a bad practice to do so in any property, especially not one with connection information.

So what should I do? Should I set it to public anyway, or should I create manually a function for each built-in function I need to use?

4

The whole point of wrapping a core PHP database driver is to provide your custom interface for handling database requests. Making the mysqli property public completely defies the purpose and you wouldn't really need your custom class in the first place.

The best approach would be to create a DatabaseInterface, have class or classes implement it, classes, which, preferably in their constructor, take a core PHP database driver (be it mysqli or PDO) and use the DatabaseInterface as parameters for classes which require database interaction.

This way you provide your own abstraction, over which you have full control, and are also not limited to single implementation.


More details and implementation example

In PHP you have generally two recommended options for database connection.

  • using PDO
  • using mysqli

The problem is PDO and mysqli provide different interface to querying, creating transactions, so if you used for example mysqli in your application directly and then wanted to switch to PDO, you would have to refactor every single database call in your app.

Use interfaces for abstraction

You create an interface, which will represent your very own interface for database calls. Here is a very simple example how some of its methods may look.

interface MyDatabase
{
    public function beginTransaction();
    public function commitTransaction();
    public function doQuery($sql);
}

Right now you want to use mysqli, so you create a new class, MyMySQLiDriver, which will implement the MyDatabase interface and either take a mysqli object in its constructor as a parameter, or you can use the procedural-programming mysqli_* functions.

class MyMySQLiDriver implements MyDatabase
{
    protected $mysqli;

    public function __construct($mysqli)
    {
        $this->mysqli = $mysqli;
    }

    public function beginTransaction() { /* use $this->mysqli here */ }
    public function commitTransaction() { /* use $this->mysqli here */ }
    public function doQuery($sql) { /* use $this->mysqli here */ }
}

Anywhere else in your code, if you want to use a database, you are going to pass an object of MyDatabase (the interface) type as a parameter and use its methods.

function IAmUsingTheDatabase(MyDatabase $db)
{
    $db->beginTransaction();
    $db->doQuery("SELECT * ...");
    $db->commitTransaction();
}

Note that the IAmUsingTheDatabase has no idea whether you are using PDO, mysqli or anything else. It wants to use the database and it uses the interface you provided.

As I have said in the comments under this post, if, in the future, you don't want to use the MyMySQLiDriver anymore, you create a new class, be it MyPDODriver or anything else, which will again implement MyDatabase interface.


Where to go from here

You can study more on this topic under Inversion of Control (this is directly tied to Dependency injection and benefits greatly from the Strategy pattern).

| improve this answer | |
  • But what would be exactly the structure of that interface? – Sipo Oct 20 '15 at 11:41
  • Take a look at YAGNI. You shouldn't make methods just because you think one day you are going to need it. If you need a method for something, add and implement it, but in your case, they will be fairly similar to the core methods. – Andy Oct 20 '15 at 12:02
  • But why create an interface? I could just stay with my class and create those functions I need. Sorry if it is a silly question, I am pretty new to OOP. – Sipo Oct 20 '15 at 14:51
  • @Sipo You want to create an interface and have a class implement said interface to be able to swap out the implementation, should you ever, without changing anything else. Let's say you decide to use PDO instead of mysqli in 2 years, you will just create a new database driver implementing DatabaseInterface which will use the PDO and simply change in your config you no longer want to use the one using mysqli but the one which uses PDO instead. And everything will still work, because the database contract is guaranteed by the interface and not a specific class. – Andy Oct 20 '15 at 15:04
  • Could you add some basic example to your answer? Thanks. – Sipo Oct 20 '15 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.