Eu tenho que admitir que realmente não sei qual o melhor título para este artigo. Mas coloquei, por fim, “autoinjeção de dependências em objetos PHP”. Eu sei que não é muito descritivo. Deixe-me explicar um pouco – eu queria automatizar o “Princípio de Hollywood” (“Não nos chame, nós chamamos você”), o lema da injeção de dependência. A Ideia é simples. Imagine um “controller”.
class Controller { public function hi($name) { return "Hi $name"; } }
Podemos automatizar facilmente a ação “hi”.
$controller = new Controller(); echo $controller->hi("Gonzalo");
Ou talvez se estamos construindo um framework e o nosso class name e action name dependem do input do usuário.
$class = "Controller"; $action = "hi"; $arguments = ['name' => "Gonzalo"]; echo call_user_function_array([new $class, $action], arguments);
Mas imagine que você queira permitir algo assim:
class Controller { public function hi($name, Request $request) { return "Hi $name " .$request->get('surname'); } }
Agora precisamos inventar o objeto Request com a nossa ação “hi”, mas não sempre. Apenas quando o usuário setar uma variável com o type “Request”. Imagine que você também quer permitir esse tipo de injeção no constructor. Pode ser que precise usar o Reflections para criar nossa instância e fazer o call to action. Algumas vezes, tenho que trabalhar com frameworks padrão e aplicações PHP legadas. Fiz isso em alguns projetos, mas agora eu quero criar uma biblioteca para automatizar essa operação.
A ideia é usar o Container de Injeção de Dependência (no meu caso, Pimple), e recuperar a dependência do container (se disponível). Eu não posso usar a keyword “new” para criar a instância e também não posso chamar a ação diretamente.
Um exemplo de uso é:
class Foo { public function hi($name) { return "Hi $name"; } } class Another { public function bye($name) { return "Bye $name"; } } class Bar { private $foo; public function __construct(Foo $foo, $surname = null) { $this->foo = $foo; $this->surname = $surname; } public function hi(Another $another, $name) { return $this->foo->hi($name . " " . $this->surname) . ' ' . $another->bye($name); } } $container = new Pimple(); $container['name'] = "Gonzalo2"; $builder = new G\Builder($container); $bar = $builder->create('Bar', ['surname' => 'Ayuso']); var_dump($builder->call([$bar, 'hi'])); var_dump($bar->hi(new Another(), 'xxxxx'));
Nossa biblioteca tenta recuperar a dependência do DIC. Se não consegue fazer isso, ela cria uma nova instância.
A “mágica” está toda na classe Builder. Você pode ver a biblioteca no meu GitHub.
***
Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://gonzalo123.com/2014/03/03/auto-injecting-dependencies-in-php-objects/