I am refactoring an old Codeigniter library to be php framework agnostic. There are these core parts:
-
the connection object – this will come from the "user"; ie, the framework's connection, or their own connection library. My library will not want to "know about it" except that (at first) it will be a PDO conn object (but things should be written to handle a native driver type)
-
the model object – runs the queries & returns results array (or error array) to the main lib. As it is now, it is very "thin" and only has transactions, query building & the actual db query
-
the model interface – I'm a big fan of interfaces, and I see this model as being swappable for a NoSQL model, for example
-
the main library – in my current CI library, this 1) receives the function request, 2) validates the params passed to it, 3) requests from the model, 4) creates a response array that includes the data & error codes and messages (multilingual configurable, but not really part of this question)
So, in summary, the way it works NOW is in your controller or calling page:
1) call main lib function
2) main lib calls model
3) model returns to main lib
4) main lib returns to controller
NOW starts my real design pattern question:
I would like to pass my conn object via DI to my main library, but I'd also like to pass my model via DI to the main library to keep things flexible. The flexibility goal I'm after would be to allow people to create their own Native DB or NoSQL models & pass non-PDO conns into this, so keeping them decoupled seems optimal.
BUT to do this, the only thing I can think of would end up as:
(controller – where I might actually execute the query in the lib, not model)
$conn //from the user
$model = new MyModel();
$lib = new MyLib($conn, $model);
or
$conn //from the user
$model = new MyModel($conn);
$lib = new MyLib($model);
which feels more "natural" since the query & conn tend to work together
Either case feels pretty clumsy for the user, and I can't help but wonder if I'm not either overdoing this whole DI thing or just have picked the wrong design pattern to go about this.
Any guidance as to how to best set this up would be greatly appreciated – spent more time thinking about this than it will take me to refactor the actual code!
TIA
Best Answer
I could be waaaaaay off, but...
It seems that a model is necessary to use the library, you just don't care which one, right? Further, the library doesn't care how the model gets its data, or where the data comes from, it just wants an object that meets the criteria of the interface.
If the library doesn't need the connection object, then make that the responsibility of the model.
And here is a simple class example:
And a Model example:
And here is an example of using it:
Now, if I decide that I want a file-based solution, I can easily swap the model. To test the model, the connection obj is injected, so that's easy. To test the library, the model is also injected, so, again, that's easy.
In this case, the model is only responsible for getting the data, while the library is responsible for handling and processing the data. Neither cares what or how the other one does it.
EDIT
the library with a factory method to create the model if none was given...