27
Dependency Inversion Dependency Injection Contract SOLID Service Provider Service Container IoC DI

Dependency Injection in Laravel

Embed Size (px)

Citation preview

Dependency Inversion

Dependency Injection

Contract

SOLID

Service ProviderService Container

IoC

DI

Dependency InversionSOLID

High-level modules should not depend on low-level modules. Both should depend on abstractions.

http://en.wikipedia.org/wiki/Dependency_inversion_principle

⾼高階模組不應該依賴低階模組。 兩者都應該要依賴於抽象

What the …

class UserModify { public function __constructor() {

$this->storage = new MysqlStorage(); }

public function modify($data) { $result = $this->storage->save($data); return $result;

} }

⾼高階直接依賴低階

class UserModify { public function __constructor(DataStorageInterface $storage) {

$this->storage = $storage; }

public function modify($data) { $result = $this->storage->save($data); return $result;

} }

class MysqlStorage implements DataStorageInterface { public function save($data){ // …. }

}

interface DataStorageInterface { public function save(array $data);

}

Abstraction

Low Level Module

Hight Level Module

Why

#隱藏低階模組的細節

#容易抽換實作

#程式碼變多

#追蹤⽐比較困難

#讓測試變容易 #⽐比較不直覺

隱藏低階模組的細節

class UserModify { public function __constructor() { $dbConfig = [….];

$this->storage = new MysqlStorage($dbConfig); }

}

容易抽換實作

class UserModify { public function __constructor(DataStorageInterface $storage) {

$this->storage = $storage; }

}

class SqliteStorage implements DataStorageInterface { public function save($data){ // …. }

}

SqliteStorage Instance

讓測試變容易

class DummyStorage implements DataStorageInterface { public function save() { return ‘Success’; }

}

class UserModify { public function modify($data) {

return $this->storage->save($data); }

}

class UserModifyTest { public function it_return_new_instance_after_modify($data) {

$instance = new UserModify(new DummyStorage); $result = $instance->modify();

assert($result, ‘Success’); }

}

How

Inverse of Control

http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC

Dependency Injection

http://en.wikipedia.org/wiki/Dependency_injection

Dependency injection is a software design pattern that implements inversion of control for software libraries, where the caller delegates to an external framework the control flow of discovering and importing a service or software module.

ServiceProvider

Container

http://laravel.tw/docs/5.0/providers

Service Provider

.

├── AppServiceProvider.php

├── BusServiceProvider.php

├── ConfigServiceProvider.php

├── EventServiceProvider.php

├── FilterServiceProvider.php

├── RepoServiceProvider.php

└── RouteServiceProvider.php

app/Providers

<?php namespace Backend\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function register() {

$this->app->bind( ‘Jaster/Interfaces/FooInterface’, ‘Jaster/Implements/FooImplementClass’ ); }}

app/Providers/AppServiceProvider.php

'providers' => [ /* * Laravel Framework Service Providers... */ 'Illuminate\Foundation\Providers\ArtisanServiceProvider', 'Illuminate\Auth\AuthServiceProvider', 'Illuminate\Bus\BusServiceProvider', 'Illuminate\Cache\CacheServiceProvider', 'Illuminate\Foundation\Providers\ConsoleSupportServiceProvider', 'Illuminate\Routing\ControllerServiceProvider',

// ….],

config/app.php

Service Container

The Laravel service container is a powerful tool for managing class dependencies. Dependency injection is a fancy word that essentially means this: class dependencies are "injected" into the class via the constructor or, in some cases, "setter" methods.

http://laravel.com/docs/5.0/container

Trace initialize of service container ( Illuminate\Foundation\Application )

Illuminate\Foundation\Application::__construct

Illuminate\Foundation\Application::registerBaseBindings

Illuminate\Foundation\Application::registerBaseServiceProviders

Illuminate\Foundation\Application::registerCoreContainerAliases

Trace register of Illuminate\Contracts\Http\Kernel

bootstrap/app.php $app->singleton(‘Illuminate\Contracts\Http\Kernel', 'App\Http\Kernel');

Illuminate\Foundation\Application::singleton

Illuminate\Foundation\Application::bind

Trace how to use Illuminate\Contracts\Http\Kernel

$kernel = $app->make('Illuminate\Contracts\Http\Kernel');public/index.php

Illuminate\Foundation\Application::make

Illuminate\Container\Container::make

Illuminate\Container\Container::build

Trace Facade autoloader

Illuminate\Foundation\Http\Kernel::bootstrap

Illuminate\Foundation\Application::bootstrapWith

Illuminate\Foundation\Bootstrap\RegisterFacades

Illuminate\Foundation\AliasLoader::register

Illuminate\Foundation\AliasLoader::prependToLoaderStack

PHP UK Conference 2014 - Stephan Hochdorfer - The 7 Deadly Sins of Dependency Injection

https://www.youtube.com/watch?v=hMix8gfDy54

Thank you