I'm creating an application using the Slim 3 framework which basically consists of dynamically populating a series of dropdown select statements and then produces a table of calculated data based on the selections.
I was originally going to stick to an MVC layout, however in order to separate out the data access layer (each model only handling a single item of data) I decided to place the business logic into a service layer after reading Dependency Injection Slim Framework 3
It's structured as :
- index.php - routing and DIC where routes are called by ajax from different web pages
- /models - contain classes for each item of data used in each dropdown e.g. Country.class.php, Product.class.php etc...
- /controllers - contain 2 classes InputController.class.php to handle the dropdowns and CalculateController.class.php to handle the calculations.
- /views - contains php templates to return with the response using php-views
- /services - service classes to handle business logic and return data to be passed to view by controller
In the DIC, i'm trying to avoid passing the container to other classes, however I've hit a situation where I'm not sure how to inject the dependencies properly.
In my index.php file, I have the following code:
//DIC
$container = $app->getContainer();
$container['view'] = function ($container) {
return new \Slim\Views\PhpRenderer('src/views/');
};
$container['InputService'] = function($container){
//questionable area
$model1 = $container->get('model1');
$model2 = $container->get('model2');
$model3 = $container->get('model3');
new InputService($model1, $model2, $model3);
}
$container['InputController'] = function($container){
$service = $container->get('InputService');
$view = $container->get('view');
new InputController($InputService, $view);
}
When the particular web page loads, an initial ajax call is sent which requests 2 or 3 of the dropdown views (as the first 2/3 aren't dependent on other choices in certain circumstances). As such the InputService
is injected with the 3 models. However, if I want to use the same service class to deal with the remaining dropdowns, how do I inject the right models?
A few thoughts I've had so far:
Inject all the models when instantiating the service, however this would mean a lot of redundant objects being created each time it's called.
$container['InputService'] = function($container){ //questionable area $model1 = $container->get('model1'); $model2 = $container->get('model2'); $model3 = $container->get('model3'); $model4 = $container->get('model4'); $model5 = $container->get('model5'); $model6 = $container->get('model6'); $model7 = $container->get('model7'); $model8 = $container->get('model8'); $model9 = $container->get('model9); new InputService( /*an array of the models*/ ); }
Create a different service class for each subsequent dropdown, although doing this makes me wonder if I should drop the service layer and just put the business logic in the models. However, wouldn't it be better to have the model classes gathering the data from the db, not be concerned about how it's then manipulated as in the future different areas of business logic will use the same data for something else?
controller1 > service1 > 3 models
controller1 > service2 > 1 model
controller1 > service3 > 1 model
controller1 > service4 > 1 model ...
or perhaps:
controller1 > model1 > 3 other models
controller1 > model5
controller1 > model6 ...
Pass the container to the controller and inject dependency into service as needed for each call.