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?
Best Answer
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 theDatabaseInterface
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.
PDO
mysqli
The problem is
PDO
andmysqli
provide different interface to querying, creating transactions, so if you used for examplemysqli
in your application directly and then wanted to switch toPDO
, 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.
Right now you want to use
mysqli
, so you create a new class,MyMySQLiDriver
, which will implement theMyDatabase
interface and either take amysqli
object in its constructor as a parameter, or you can use the procedural-programmingmysqli_*
functions.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.Note that the
IAmUsingTheDatabase
has no idea whether you are usingPDO
,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 itMyPDODriver
or anything else, which will again implementMyDatabase
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).