Skip to content

Instantly share code, notes, and snippets.

@iansltx
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iansltx/7259e453b59c46b4baf2 to your computer and use it in GitHub Desktop.
Save iansltx/7259e453b59c46b4baf2 to your computer and use it in GitHub Desktop.
Trait Injection
<?php
// assumes DI container was already declared
$di->setter['BaseNamespace\Trait\Loggable']['setLogger'] = $di->lazyNew('MyAwesomePSRCompliantLoggingClass');
$di->setter['BaseNamespace\Trait\Mailable']['setMailer'] = $di->lazyNew('BaseNamespace\Service\EmailService');
// set up params for EmailService, MyAwesomePSRCompliantLoggingClass, SomeParentCLass, etc.
// advantages over constructor injection: less huge constructors of doom on, for example, controllers
// and yes, my controllers aren't aware that my container exists...their deps are all injected
// advantages over interface-based setter injection: less code in the injected classes, more consistent
// use of injected services...log() works the same on anything that pulls in loggable
// disadvantages: tighter coupling vs. interfaces (though I believe you can have a trait conform to an iface).
// slightly less obvious than constructor injection what deps are being used, though trait use's are nearby
<?php
namespace BaseNamespace\Service;
// this should be an interface but I'm lazy
class EmailService
{
/* properties */
public function __construct(/* params */) {
/* set stuff */
}
public function sendRegistrationEmail($data) {
/* mail stuff */
}
}
<?php
namespace BaseNamespace\Domain;
use BaseNamespace\Trait\Mailable;
use BaseNamespace\Trait\Loggable;
// SomeParentClass has its own constructor-injected params, but a logger and mailer aren't injected
class Injected extends SomeParentClass
{
use Mailable, Loggable;
public function someMethod($some_param) {
$this->log('I did a thing', 'info');
$this->getMailer()->sendRegistrationEmail($this->someParentMethod($some_param));
}
}
<?php
namespace BaseNamespace\Trait;
use Psr\Log\LoggerInterface as Logger;
trait Loggable
{
/** @var Logger */
protected $logger;
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
public function getLogger() {
return $this->logger;
}
public function log($level, $message, $context = []) {
if ($msg === null)
return $this->logger;
if ($this->logger)
return $this->logger->msg($level, $message, $context);
error_log(($level ?: 'debug') . ' - ' . $message . ' ' . json_encode($context));
}
}
<?php
namespace BaseNamespace\Trait;
use BaseNamespace\Service;
trait Mailable
{
protected $mailer;
public function setMailer(EmailService $mailer) {
$this->mailer = $mailer;
}
/** @return EmailService */
public function getMailer() {
return $this->mailer;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment