1

i will try to explain my question via an example:

we have 1 main php script, that instantiates a few classes/objects, our project specific code. We want to add a logger to all those classes. what is the common-practice way to do that? for the sake of an example, we want to have Monolog, its supposed to be instantiated with:

$log = new Monolog\Logger('name');
$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
$log->addWarning('Foo');

option #1: we could have 1 monolog per class. i guess not the best option.

option #2: from the main script, have a $log object, and pass it to each called object (and then in each object __construct assign the $log to a private variable $class_logger and then use it:

for example, main script:

$logger = Logger::getLogger("main");
$logger->info("This is an informational message.");
$logger->warn("I'm not feeling so good...");

$test_run = new called_object($logger);
$test_run->call_it();

called_object class:

class called_object {


    private $logger;

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

    public function call_it()
    {
        $this->logger->warn("from called_object!");
    }
}

second seems better, but still i feel its not too practical, perhaps i am missing something here?

ilias-sp
  • 6,135
  • 4
  • 28
  • 41
  • The second option is called "dependency injection" and is definitely the way I would do it. If you want things to be easier for you, use a proper DI Container like Pimple or Illuminates Container (the same that Laravel is using and has automatic dependency resolution). That will help you to control all dependencies easier. – M. Eriksson Apr 21 '17 at 15:28
  • You should read about dependency injection http://stackoverflow.com/a/140655/4916265 also read this to get an simple concept of if http://pimple.sensiolabs.org/ – JustOnUnderMillions Apr 21 '17 at 15:28
  • @MagnusEriksson yes, but if you have a logger and 3-4 other objects you need to inject to lets say 10 classes, then you get a lot of overhead, and i was thinking there is another way to do it, but seems this is not the case. I do need to check Pimple, thank you! – ilias-sp Apr 21 '17 at 15:53
  • @JustOnUnderMillions thank you, will dig in the Pimple solution i guess – ilias-sp Apr 21 '17 at 15:54
  • Why would you get overhead by using a container? The automatic resolution (which uses reflection) isn't mandatory. – M. Eriksson Apr 21 '17 at 16:34
  • @MagnusEriksson sorry, i read again my comment and its not expressing what i was trying to say, i was talking about plain dependancy injection, without using container (like Pimple). please ignore :) my intention is to give Pimple a try. – ilias-sp Apr 21 '17 at 23:46

1 Answers1

2

The second option is called dependency injection and is preferred. It gives you a single point of configuration -- for example, if you want to change how the logger behaves, you only have to do it in once place. It also allows for easier testing, for example, you may have a separate testing configuration which configures a null logger.

Alex Howansky
  • 50,515
  • 8
  • 78
  • 98
  • understand. but it gives you a lot of overhead, if you want to pass 2-3-4 objects to each called class, and you have a lot of classes to call. I am familiar with Codeigniter and i know that you can access loaded classes and their functions without any declaration. but i guess this loading technique is for more advanced/complex projects. i will take a look at Pimple as mentioned in a few comments above. thank you – ilias-sp Apr 21 '17 at 15:57