1

I'm working on my HMVC project.

First: I have a list of helper/utilities classes, used to accomplish specific tasks: Arrays, Classes, Files, Log, Messages, Images, Encryption, etc.

For example, in the Arrays class I defined a function to read an array value in a multidimensional array by a given keypath (ex: get 'app/paths/modules' value).

For some classes, some of them are required dependencies, therefore beeing mandatory to be injected in constructors. Like, the Array class is a mandatory dependency of the Config class, used to read the values from the application configurations array.

For other classes they are not required dependencies. Like the Log class. It's used sometimes in controller actions, or in QueryBuilder methods, for logging purposes.

I would like to know, how the instances of this type of classes should be injected.

  • As setter dependencies, or
  • as arguments in the methods which are using them?

Second: Should I consider a Request class as a required, e.g. constructor dependency in controllers?

I'm also using a dependency injection container.

Thank you.

Edit

Removed bullet lists from "For some classes..." and "For other classes...".

EDIT 2

Here is an example of using Arrays class inside ConnectionConfiguration:

/*
 * Connection configuration.
 */

namespace [...]\Database;

use PDO;
use [...]\Config;
use [...]\Utils\Arrays;

/**
 * Connection configuration.
 */
class ConnectionConfiguration {

    /**
     * Config.
     * 
     * @var Config
     */
    private $config;

    /**
     * Arrays.
     * 
     * @var Arrays
     */
    private $arrays;

    /**
     * Connection name.
     * 
     * @var string
     */
    private $connectionName;

    /**
     * Default connection attributes.
     * 
     * @var array
     */
    private $defaultConnectionAttributes = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES => FALSE,
        PDO::ATTR_PERSISTENT => TRUE
    );

    /**
     * 
     * @param Config $config Config.
     */
    public function __construct(Config $config, Arrays $arrays) {
        $this
                ->setConfig($config)
                ->setArrays($arrays);
    }

    /**
     * Get the connection attributes (merged over the default ones).
     * 
     * @return array
     */
    public function getConnectionAttributes() {
        $defaultAttributes = $this->getDefaultConnectionAttributes();
        $connectionAttributes = $this->getConnectionAttributes();

        return $this->getArrays()->mergeArrays($defaultAttributes, $connectionAttributes);
    }

}

1 Answers1

0

I personally use Request as dependency of controller's method, that actually needs it.

As for the rest of your code, it seem that you are attempting to shove too much within controller. I would recommend for you to add a "service layer", that handles the application logic, with each controller only depending on those services as requirements in constructor.

To add anything more, you will have to show some code.

tereško
  • 58,060
  • 25
  • 98
  • 150
  • As, until now, I worked with a PHP MVC framework having a lot of singletons and static classes/methods, I lack the experience with a framework, that doesn't contain such elements. That's the reason, why I personally can't measure the grade of too much responsibilities in an objective manner. So I have to base the structuring of my project on my good-sense and on the valuable experience and opinions of other developers. Like you, I indeed think, that these "not required" dependencies would be "too much". Cont... –  May 18 '17 at 11:34
  • ...Cont: Having them setter-injected, would lead to having them injected at bootstrap level in all controllers or other classes, in which **I think** they could be needed in the future. But, of course, I'll not need the `Log` class all the time in a controller, for example. Cont... –  May 18 '17 at 11:37
  • ... Cont: Sorry, I had network problems. You are proposing adding a service layer for application logic. You know already Martin Fowler's definition for [Service Layer](https://martinfowler.com/eaaCatalog/serviceLayer.html). That I understand as an application layer for business logic only. A layer having the main purpose of coordinating user interactions with storage layer. Now, I read some of your articles, regarding applying the decorator pattern for tasks like... –  May 18 '17 at 12:27
  • ... like [non-invasive logging](http://stackoverflow.com/questions/18673941/php-implement-logging-mechanism-to-file-in-several-classes/18682856#18682856), or using services like for [Authentication](http://stackoverflow.com/questions/3430181/how-can-i-implement-an-access-control-list-in-my-web-mvc-application), and other good ones. Now I'm a bit confused, to which type of service are you referring? Are there services which belong to application logic and **other** belonging to application's domain logic? Cont... –  May 18 '17 at 12:27
  • ... Cont: Or are all services actually part of a big service layer, in which each service just do what it's supposed to do? I'll edit the question now, with an example of using my utility classes. Thank you for your answer. –  May 18 '17 at 12:29
  • Ugh. There is a lot of things to go through and I am at work at the moment (you will have to wait for actual updates to the answer till I get back home). As I understand it, services are part of a big layer, where each service is dedicated to specific aspect of your application logic. For example, you would have a separate service, that "does uploads". It should have methods like `$file = $fs->storeFile($request->get('upload'))` and `$fs->setFileOwner($file, $account);`, that you would call from a controller. – tereško May 18 '17 at 13:36
  • Each of those services should be handling a specific aspect of your "application logic". You can think of that logic as "tasks that controller execute". The only code that I can quickly show you would be from [this project](https://github.com/teresko/palladium) (incomplete, don't use in production code .. yet). That contains a library with 4 services, where each service handles some aspect of a greater whole. That's all I can tell you right now ... I will update the answer when I get home from work. – tereško May 18 '17 at 13:40
  • **Please, do your things. Read this only later if you wish :-)** I know this is a complex aspect, so I had no rush. It's important to have the main principle. As you see it (and, I'm sure, you use it) and as I see it from a pure logical point of view: there is the one (and only one) application logic layer. Consisting of multiple services of any kind: storage handling, file uploads handling, logging, authentication, image processing, etc. Cont... –  May 18 '17 at 14:27
  • ... Martin Fowler's "Service Layer" is presented as a "Domain Logic Pattern", so he referrs to it as it would be only the collection of domain logic services inside the application logic layer. But we can abstract by saying: MF's layer is one service layer, on the same niveau with other service layers, which are responsible/user interfaces for other kind of processes/operations (file system, messaging, etc). And all of these services would then form the one aplication logic layer. –  May 18 '17 at 14:28
  • Then: the whole helper/utils dependencies should actually be **constructor-injected** in the services which make use of them. Only this services should be **constructor-injected** into the controllers and views (they'll share them). A class as `ConnectionConfiguration` (as in my edited question) needs `Arrays` constructor-injected, because it is a "required dependency". So, injection schema for this case would be approx: `Arrays` -> `ConnectionConfiguration` -> `Connection` -> `DbAdapter` -> `DataMapper` -> `Repository` -> `AuthenticationService` (along with needed domain objects). –  May 18 '17 at 14:28
  • ... And only `AuthenticationService` should be injected in corresponding controllers/views. Otherwise should `Arrays` (as representant of helper/utilities classes) not be used as standalone argument in controllers/views. Done... @teresko, great answer! I appreciate it! –  May 18 '17 at 14:29
  • I read your part 2 of your comments only now. Thanks, I'll look in your project. –  May 18 '17 at 14:33