# 依賴注入與服務定位器(Dependency Injection/Service Location)[](# "永久鏈接至標題")
接下來的例子有些長,但解釋了為什么我們使用依賴注入與服務定位器.首先,假設我們正在開發一個組件,叫SomeComponent,它執行的內容現在還不重要。我們的組件需要依賴數據庫的連接。
在下面第一個例子中,數據庫的連接是在組件內部建立的。這種方法是不實用的;事實上這樣做的話,我們不能改變創建數據庫連接的參數或者選擇不同的數據庫系統,因為連接是當組件被創建時建立的。
~~~
<?php
class SomeComponent
{
/**
* 連接數據庫的實例是被寫死在組件的內部
* 因此,我們很難從外部替換或者改變它的行為
*/
public function someDbTask()
{
$connection = new Connection(
array(
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo"
)
);
// ...
}
}
$some = new SomeComponent();
$some->someDbTask();
~~~
為了解決這樣的情況,我們建立一個setter,在使用前注入獨立外部依賴。現在,看起來似乎是一個不錯的解決辦法:
~~~
<?php
class SomeComponent
{
protected $_connection;
/**
* 設置外部傳入的數據庫的連接實例
*/
public function setConnection($connection)
{
$this->_connection = $connection;
}
public function someDbTask()
{
$connection = $this->_connection;
// ...
}
}
$some = new SomeComponent();
// 建立數據庫連接實例
$connection = new Connection(
array(
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo"
)
);
// 向組件注入數據連接實例
$some->setConnection($connection);
$some->someDbTask();
~~~
想一下,假設我們使用這個組件在應用內的好幾個地方都用到,然而我們在注入連接實例時還需要建立好幾次數據的連接實例。如果我們可以獲取到數據庫的連接實例而不用每次都要創建新的連接實例,使用某種全局注冊表可以解決這樣的問題:
~~~
<?php
class Registry
{
/**
* 返回數據庫連接實例
*/
public static function getConnection()
{
return new Connection(
array(
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo"
)
);
}
}
class SomeComponent
{
protected $_connection;
/**
* 設置外部傳入的數據庫的連接實例
*/
public function setConnection($connection)
{
$this->_connection = $connection;
}
public function someDbTask()
{
$connection = $this->_connection;
// ...
}
}
$some = new SomeComponent();
// 把注冊表中的連接實例傳遞給組件
$some->setConnection(Registry::getConnection());
$some->someDbTask();
~~~
現在,讓我們設想一下,我們必須實現2個方法,第一個方法是總是創建一個新的連接,第二方法是總是使用一個共享連接:
~~~
<?php
class Registry
{
protected static $_connection;
/**
* 建立一個新的連接實例
*/
protected static function _createConnection()
{
return new Connection(
array(
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo"
)
);
}
/**
* 只建立一個連接實例,后面的請求只返回該連接實例
*/
public static function getSharedConnection()
{
if (self::$_connection===null) {
$connection = self::_createConnection();
self::$_connection = $connection;
}
return self::$_connection;
}
/**
* 總是返回一個新的連接實例
*/
public static function getNewConnection()
{
return self::_createConnection();
}
}
class SomeComponent
{
protected $_connection;
/**
* 設置外部傳入的數據庫的連接實例
*/
public function setConnection($connection)
{
$this->_connection = $connection;
}
/**
* 這個方法總是需要共享連接實例
*/
public function someDbTask()
{
$connection = $this->_connection;
// ...
}
/**
* 這個方法總是需要新的連接實例
*/
public function someOtherDbTask($connection)
{
}
}
$some = new SomeComponent();
// 注入共享連接實例
$some->setConnection(Registry::getSharedConnection());
$some->someDbTask();
// 這里我們總是傳遞一個新的連接實例
$some->someOtherDbTask(Registry::getConnection());
~~~
到目前為止,我們已經看到依賴注入怎么解決我們的問題了。把依賴作為參數來傳遞,而不是建立在內部建立它們,這使我們的應用更加容易維護和更加解耦。不管怎么樣,長期來說,這種形式的依賴注入有一些缺點。
例如,如果這個組件有很多依賴,我們需要創建多個參數的setter方法來傳遞依賴關系,或者建立一個多個參數的構造函數來傳遞它們,另外在使用組件前還要每次都創建依賴,這讓我們的代碼像這樣不易維護:
~~~
<?php
// 創建依賴實例或從注冊表中查找
$connection = new Connection();
$session = new Session();
$fileSystem = new FileSystem();
$filter = new Filter();
$selector = new Selector();
// 把實例作為參數傳遞給構造函數
$some = new SomeComponent($connection, $session, $fileSystem, $filter, $selector);
// ... 或者使用setter
$some->setConnection($connection);
$some->setSession($session);
$some->setFileSystem($fileSystem);
$some->setFilter($filter);
$some->setSelector($selector);
~~~
假設我們必須在應用的不同地方使用和創建這些對象。如果當你永遠不需要任何依賴實例時,你需要去刪掉構造函數的參數,或者去刪掉注入的setter。為了解決這樣的問題,我們再次回到全局注冊表創建組件。不管怎么樣,在創建對象之前,它增加了一個新的抽象層:
~~~
<?php
class SomeComponent
{
// ...
/**
* Define a factory method to create SomeComponent instances injecting its dependencies
*/
public static function factory()
{
$connection = new Connection();
$session = new Session();
$fileSystem = new FileSystem();
$filter = new Filter();
$selector = new Selector();
return new self($connection, $session, $fileSystem, $filter, $selector);
}
}
~~~
瞬間,我們又回到剛剛開始的問題了,我們再次創建依賴實例在組件內部!我們可以繼續前進,找出一個每次能奏效的方法去解決這個問題。但似乎一次又一次,我們又回到了不實用的例子中。
一個實用和優雅的解決方法,是為依賴實例提供一個容器。這個容器擔任全局的注冊表,就像我們剛才看到的那樣。使用依賴實例的容器作為一個橋梁來獲取依賴實例,使我們能夠降低我們的組件的復雜性:
~~~
<?php
use Phalcon\DI;
class SomeComponent
{
protected $_di;
public function __construct($di)
{
$this->_di = $di;
}
public function someDbTask()
{
// 獲得數據庫連接實例
// 總是返回一個新的連接
$connection = $this->_di->get('db');
}
public function someOtherDbTask()
{
// 獲得共享連接實例
// 每次請求都返回相同的連接實例
$connection = $this->_di->getShared('db');
// 這個方法也需要一個輸入過濾的依賴服務
$filter = $this->_di->get('filter');
}
}
$di = new DI();
// 在容器中注冊一個db服務
$di->set('db', function () {
return new Connection(
array(
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo"
)
);
});
// 在容器中注冊一個filter服務
$di->set('filter', function () {
return new Filter();
});
// 在容器中注冊一個session服務
$di->set('session', function () {
return new Session();
});
// 把傳遞服務的容器作為唯一參數傳遞給組件
$some = new SomeComponent($di);
$some->someDbTask();
~~~
這個組件現在可以很簡單的獲取到它所需要的服務,服務采用延遲加載的方式,只有在需要使用的時候才初始化,這也節省了服務器資源。這個組件現在是高度解耦。例如,我們可以替換掉創建連接的方式,它們的行為或它們的任何其他方面,也不會影響該組件。
### 實現方法(Our approach)[](# "永久鏈接至標題")
Phalcon\DI 是一個實現依賴注入和定位服務的組件,而且它本身就是一個裝載它們的容器。
因為Phalcon是高度解構的,整合框架的不同組件,使用Phalcon\DI是必不可少的。開發者也可以使用這個組件去注入依賴和管理的應用程序中來自不同類的全局實例。
基本上,這個組件實現了 [控制反轉]([http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC](http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC)) 的模式。使用這種模式,組件的對象不用再使用setter或者構造函數去接受依賴實例,而是使用請求服務的依賴注入。這減少了總的復雜性,因為在組件內,只有一個方法去獲取所需的依賴實例。
另外,該模式增加了代碼的可測試性,從而使其不易出錯。
### 使用容器注冊服務(Registering services in the Container)[](# "永久鏈接至標題")
框架本身或者開發者都可以注冊服務。當一個組件A需要組件B(或者它的類的實例) 去操作,它可以通過容器去請求組件B,而不是創建一個新的組件B實例。
這個工作方法給我們提供了許多優勢:
- 我們可以很容易的使用一個我們自己建立的或者是第三方的組件去替換原有的組件。
- 我們完全控制對象的初始化,這讓我們在傳遞它們的實例到組件之前,根據需要設置這些對象。
- 我們可以在一個結構化的和統一組件內獲取全局實例。
服務可以使用不同方式去定義:
~~~
<?php
use Phalcon\Http\Request;
// 創建一個依賴注入容器
$di = new Phalcon\DI();
// 通過類名稱設置服務
$di->set("request", 'Phalcon\Http\Request');
// 使用匿名函數去設置服務,這個實例將被延遲加載
$di->set("request", function () {
return new Request();
});
// 直接注冊一個實例
$di->set("request", new Request());
// 使用數組方式定義服務
$di->set(
"request",
array(
"className" => 'Phalcon\Http\Request'
)
);
~~~
使用數組的方式去注冊服務也是可以的:
~~~
<?php
use Phalcon\Http\Request;
// 創建一個依賴注入容器
$di = new Phalcon\DI();
// 通過類名稱設置服務
$di["request"] = 'Phalcon\Http\Request';
// 使用匿名函數去設置服務,這個實例將被延遲加載
$di["request"] = function () {
return new Request();
};
// 直接注冊一個實例
$di["request"] = new Request();
// 使用數組方式定義服務
$di["request"] = array(
"className" => 'Phalcon\Http\Request'
);
~~~
在上面的例子中,當框架需要訪問request服務的內容,它會在容器里面查找名為‘request’的服務。在容器中將返回所需要的服務的實例。當有需要時,開發者可能最終需要替換這個組件。
每個方法(在上面的例子證明)用于設置/注冊服務方面具都具有優勢和劣勢。這是由開發者和特別的要求決定具體使用哪個。
通過字符串設置一個服務是很簡單,但是缺乏靈活性。通過數組設置服務提供了更加靈活的方式,但是使代碼更復雜。匿名函數是上述兩者之間的一個很好的平衡,但是會導致比預期的更多維護。
Phalcon\DI 對每個儲存的服務提供了延遲加載。除非開發者選擇直接實例化一個對象并將其存儲在容器中,任何儲存在里面的對象(通過數組,字符串等等設置的)都將延遲加載,即只要當使用到時才實例化。
### 簡單的注冊(Simple Registration)[](# "永久鏈接至標題")
就像你之前看到的那樣,這里有幾種方法去注冊服務。下面是簡單調用的例子:
#### 字符串(String)[](# "永久鏈接至標題")
使用字符串注冊服務需要一個有效的類名稱,它將返回指定的類對象,如果類還沒有加載的話,將使用自動加載器實例化對象。這種類型不允許向構造函數指定參數:
~~~
<?php
// 返回 new Phalcon\Http\Request(); 對象
$di->set('request', 'Phalcon\Http\Request');
~~~
#### 對象(Object)[](# "永久鏈接至標題")
這種類型注冊服務需要一個對象。實際上,這個服務不再需要初始化,因為它已經是一個對象,可以說,這是不是一個真正的依賴注入,但是如果你想強制總是返回相同的對象/值,使用這種方式還是有用的:
~~~
<?php
use Phalcon\Http\Request;
// 返回 Phalcon\Http\Request(); 對象
$di->set('request', new Request());
~~~
#### 閉包與匿名函數(Closures/Anonymous functions)[](# "永久鏈接至標題")
這個方法提供了更加自由的方式去注冊依賴,但是如果你想從外部改變實例化的參數而不用改變注冊服務的代碼,這是很困難的:
~~~
<?php
use Phalcon\Db\Adapter\Pdo\Mysql as PdoMysql;
$di->set("db", function () {
return new PdoMysql(
array(
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "blog"
)
);
});
~~~
這些限制是可以克服的,通過傳遞額外的變量到閉包函數里面:
~~~
<?php
use Phalcon\Db\Adapter\Pdo\Mysql as PdoMysql;
// 把當前域的$config變量傳遞給匿名函數使用
$di->set("db", function () use ($config) {
return new PdoMysql(
array(
"host" => $config->host,
"username" => $config->username,
"password" => $config->password,
"dbname" => $config->name
)
);
});
~~~
### 復雜的注冊(Complex Registration)[](# "永久鏈接至標題")
如果要求不用實例化/解析服務,就可以改變定義服務的話,我們需要使用數組的方式去定義服務。使用數組去定義服務可以更加詳細:
~~~
<?php
use Phalcon\Logger\Adapter\File as LoggerFile;
// 通過類名和參數,注冊logger服務
$di->set('logger', array(
'className' => 'Phalcon\Logger\Adapter\File',
'arguments' => array(
array(
'type' => 'parameter',
'value' => '../apps/logs/error.log'
)
)
));
// 使用匿名函數的方式
$di->set('logger', function () {
return new LoggerFile('../apps/logs/error.log');
});
~~~
上面兩種注冊服務的方式的結果是一樣的。然而,使用數組定義的話,在需要的時候可以變更注冊服務的參數:
~~~
<?php
// 改變logger服務的類名
$di->getService('logger')->setClassName('MyCustomLogger');
// 不用實例化就可以改變第一個參數值
$di->getService('logger')->setParameter(0, array(
'type' => 'parameter',
'value' => '../apps/logs/error.log'
));
~~~
除了使用數組的語法注冊服務,你還可以使用以下三種類型的依賴注入:
#### 構造函數注入(Constructor Injection)[](# "永久鏈接至標題")
這個注入方式是通過傳遞依賴/參數到類的構造函數。讓我們假設我們有下面的組件:
~~~
<?php
namespace SomeApp;
use Phalcon\Http\Response;
class SomeComponent
{
protected $_response;
protected $_someFlag;
public function __construct(Response $response, $someFlag)
{
$this->_response = $response;
$this->_someFlag = $someFlag;
}
}
~~~
這個服務可以這樣被注入:
~~~
<?php
$di->set('response', array(
'className' => 'Phalcon\Http\Response'
));
$di->set('someComponent', array(
'className' => 'SomeApp\SomeComponent',
'arguments' => array(
array('type' => 'service', 'name' => 'response'),
array('type' => 'parameter', 'value' => true)
)
));
~~~
reponse服務(Phalcon\Http\Response)作為第一個參數傳遞給構造函數,與此同時,一個布爾類型的值(true)作為第二個參數傳遞。
#### 設值注入(Setter Injection)[](# "永久鏈接至標題")
類中可能有setter去注入可選的依賴,前面那個class可以修改成通過setter來注入依賴的方式:
~~~
<?php
namespace SomeApp;
use Phalcon\Http\Response;
class SomeComponent
{
protected $_response;
protected $_someFlag;
public function setResponse(Response $response)
{
$this->_response = $response;
}
public function setFlag($someFlag)
{
$this->_someFlag = $someFlag;
}
}
~~~
用setter方式來注入的服務可以通過下面的方式來注冊:
~~~
<?php
$di->set('response', array(
'className' => 'Phalcon\Http\Response'
));
$di->set(
'someComponent',
array(
'className' => 'SomeApp\SomeComponent',
'calls' => array(
array(
'method' => 'setResponse',
'arguments' => array(
array(
'type' => 'service',
'name' => 'response'
)
)
),
array(
'method' => 'setFlag',
'arguments' => array(
array(
'type' => 'parameter',
'value' => true
)
)
)
)
)
);
~~~
#### 屬性注入(Properties Injection)[](# "永久鏈接至標題")
這是一個不太常用的方式,這種方式的注入是通過類的public屬性來注入:
~~~
<?php
namespace SomeApp;
use Phalcon\Http\Response;
class SomeComponent
{
public $response;
public $someFlag;
}
~~~
通過屬性注入的服務,可以像下面這樣注冊:
~~~
<?php
$di->set(
'response',
array(
'className' => 'Phalcon\Http\Response'
)
);
$di->set(
'someComponent',
array(
'className' => 'SomeApp\SomeComponent',
'properties' => array(
array(
'name' => 'response',
'value' => array(
'type' => 'service',
'name' => 'response'
)
),
array(
'name' => 'someFlag',
'value' => array(
'type' => 'parameter',
'value' => true
)
)
)
)
);
~~~
支持包括下面的參數類型:
| Type | 描述 | 例子 |
|-----|-----|-----|
| parameter | 表示一個文本值作為參數傳遞過去 | array(‘type' => ‘parameter', ‘value' => 1234) |
| service | 表示作為服務 | array(‘type' => ‘service', ‘name' => ‘request') |
| instance | 表示必須動態生成的對象 | array(‘type' => ‘instance', ‘className' => ‘DateTime', ‘arguments' => array(‘now')) |
解析一個定義復雜的服務也許性能上稍微慢于先前看到的簡單定義。但是,這提供了一個更強大的方式來定義和注入服務。
混合不同類型的定義是可以的,每個人可以應用需要決定什么樣的注冊服務的方式是最適當的。
### 服務解疑(Resolving Services)[](# "永久鏈接至標題")
從容器中獲取一個服務是一件簡單的事情,只要通過“get”方法就可以。這將返回一個服務的新實例:
~~~
<?php $request = $di->get("request");
~~~
或者通過魔術方法的方式獲取:
~~~
<?php
$request = $di->getRequest();
~~~
或者通過訪問數組的方式獲取:
~~~
<?php
$request = $di['request'];
~~~
參數可以傳遞到構造函數中,通過添加一個數組的參數到get方法中:
~~~
<?php
// 將返回:new MyComponent("some-parameter", "other")
$component = $di->get("MyComponent", array("some-parameter", "other"));
~~~
[*Phalcon\Di*](#) is able to send events to an [*EventsManager*](#) if it is present.Events are triggered using the type “di”. Some events when returning boolean false could stop the active operation.The following events are supported:
| Event Name | Triggered | Can stop operation? | Triggered on |
|-----|-----|-----|-----|
| beforeServiceResolve | Triggered before resolve service. Listeners receive the service name and the parameters passed to it. | No | Listeners |
| afterServiceResolve | Triggered after resolve service. Listeners receive the service name, instance, and the parameters passed to it. | No | Listeners |
### 共享服務(Shared services)[](# "永久鏈接至標題")
服務可以注冊成“shared”類型的服務,這意味著這個服務將使用 [單例模式]([http://zh.wikipedia.org/wiki/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F](http://zh.wikipedia.org/wiki/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F)) 運行,一旦服務被首次解析后,這個實例將被保存在容器中,之后的每次請求都在容器中查找并返回這個實例
~~~
<?php
use Phalcon\Session\Adapter\Files as SessionFiles;
// 把session服務注冊成“shared”類型
$di->setShared('session', function () {
$session = new SessionFiles();
$session->start();
return $session;
});
$session = $di->get('session'); // 第一次獲取session服務時,session服務將實例化
$session = $di->getSession(); // 第二次獲取時,不再實例化,直接返回第一次實例化的對象
~~~
另一種方式去注冊一個“shared”類型的服務是,傳遞“set”服務的時候,把true作為第三個參數傳遞過去:
~~~
<?php
// 把session服務注冊成“shared”類型
$di->set('session', function () {
// ...
}, true);
~~~
如果一個服務不是注冊成“shared”類型,而你又想從DI中獲取服務的“shared”實例,你可以使用getShared方法:
~~~
<?php
$request = $di->getShared("request");
~~~
### 單獨操作服務(Manipulating services individually)[](# "永久鏈接至標題")
一旦服務被注冊到服務容器中,你可以單獨操作它:
~~~
<?php
use Phalcon\Http\Request;
// 注冊request服務
$di->set('request', 'Phalcon\Http\Request');
// 獲取服務
$requestService = $di->getService('request');
// 改變它的定義
$requestService->setDefinition(function () {
return new Request();
});
// 修改成shared類型
$requestService->setShared(true);
// 解析服務(返回Phalcon\Http\Request實例)
$request = $requestService->resolve();
~~~
### 通過服務容器實例化類(Instantiating classes via the Service Container)[](# "永久鏈接至標題")
當你從服務容器中請求一個服務,如果找不到具有相同名稱的服務,它將嘗試去加載以這個服務為名稱的類。利用這個的行為,我們可以代替任意一個類,通過簡單的利用服務的名稱來注冊:
~~~
<?php
// 把一個控制器注冊為服務
$di->set('IndexController', function () {
$component = new Component();
return $component;
}, true);
// 把一個控制器注冊為服務
$di->set('MyOtherComponent', function () {
// 實際上返回另外一個組件
$component = new AnotherComponent();
return $component;
});
// 獲取通過服務容器創建的對象
$myComponent = $di->get('MyOtherComponent');
~~~
你可以利用這種方式,通過服務容器來總是實例化你的類(即是他們沒有注冊為服務),DI會回退到一個有效的自動加載類中,去加載這個類。通過這樣做,以后你可以輕松替換任意的類通過為它實現一個定義。
### 自動注入 DI(Automatic Injecting of the DI itself)[](# "永久鏈接至標題")
如果一個類或者組件需要用到DI服務,你需要在你的類中實現 [*Phalcon\DI\InjectionAwareInterface*](#) 接口,這樣就可以在實例化這個類的對象時自動注入DI的服務:
~~~
<?php
use Phalcon\DI\InjectionAwareInterface;
class MyClass implements InjectionAwareInterface
{
protected $_di;
public function setDi($di)
{
$this->_di = $di;
}
public function getDi()
{
return $this->_di;
}
}
~~~
按照上面這樣,一旦服務被解析,$di對象將自動傳遞到setDi()方法:
~~~
<?php
// 注冊服務
$di->set('myClass', 'MyClass');
// 解析服務(注意:將自動調用$myClass->setDi($di)方法)
$myClass = $di->get('myClass');
~~~
### 避免服務解析(Avoiding service resolution)[](# "永久鏈接至標題")
一些服務是用于應用的每個請求中,通過消除解析服務的過程的方式,可以使得服務解析在性能上會有小小的提升:
~~~
<?php
// 外部解析服務對象而不是使用定義服務的方式
$router = new MyRouter();
// 把已解析的對象設置到注冊服務中
$di->set('router', $router);
~~~
### 使用文件組織服務(Organizing services in files)[](# "永久鏈接至標題")
你可以更好的組織你的應用,通過移動注冊的服務到獨立的文件里面,而不是全部寫在應用的引導文件中:
~~~
<?php
$di->set('router', function () {
return include "../app/config/routes.php";
});
~~~
這樣,在文件(”../app/config/routes.php”)中,返回已解析的對象:
~~~
<?php
$router = new MyRouter();
$router->post('/login');
return $router;
~~~
### 使用靜態的方式訪問注入器(Accessing the DI in a static way)[](# "永久鏈接至標題")
如果需要的話,你可以訪問最新創建的DI對象,通過下面這種靜態方法的方式:
~~~
<?php
use Phalcon\DI;
class SomeComponent
{
public static function someMethod()
{
// 獲取session服務
$session = DI::getDefault()->getSession();
}
}
~~~
### 注入器默認工廠(Factory Default DI)[](# "永久鏈接至標題")
盡管Phalcon的解耦性質為我們提供了很大的自由度和靈活性,也許我們只是單純的想使用它作為一個全棧框架。為了達到這點,框架提供了變種的 Phalcon\DI 叫 Phalcon\DI\FactoryDefault 。這個類會自動注冊相應的服務,并捆綁在一起作為一個全棧框架。
~~~
<?php
use Phalcon\DI\FactoryDefault;
$di = new FactoryDefault();
~~~
### 服務名稱約定(Service Name Conventions)[](# "永久鏈接至標題")
盡管你可以用你喜歡的名字來注冊服務,但是Phalcon有一些命名約定,這些約定讓你在需要的時候,可以獲得正確的(內置)服務。
<table border="1" class="docutils"><colgroup><col width="11%"/><col width="24%"/><col width="54%"/><col width="10%"/></colgroup><thead valign="bottom"><tr class="row-odd"><th class="head">服務名稱</th><th class="head">介紹</th><th class="head">默認</th><th class="head">是否是shared服務</th></tr></thead><tbody valign="top"><tr class="row-even"><td>dispatcher</td><td>控制器調度服務</td><td><a class="reference internal" href="../api/Phalcon_Mvc_Dispatcher.html"><em>Phalcon\Mvc\Dispatcher</em></a></td><td>是</td></tr><tr class="row-odd"><td>router</td><td>路由服務</td><td><a class="reference internal" href="../api/Phalcon_Mvc_Router.html"><em>Phalcon\Mvc\Router</em></a></td><td>是</td></tr><tr class="row-even"><td>url</td><td>URL生成服務</td><td><a class="reference internal" href="../api/Phalcon_Mvc_Url.html"><em>Phalcon\Mvc\Url</em></a></td><td>是</td></tr><tr class="row-odd"><td>request</td><td>HTTP 請求環境服務</td><td><a class="reference internal" href="../api/Phalcon_Http_Request.html"><em>Phalcon\Http\Request</em></a></td><td>是</td></tr><tr class="row-even"><td>response</td><td>HTTP響應環境服務</td><td><a class="reference internal" href="../api/Phalcon_Http_Response.html"><em>Phalcon\Http\Response</em></a></td><td>是</td></tr><tr class="row-odd"><td>cookies</td><td>HTTP Cookie管理服務</td><td><a class="reference internal" href="../api/Phalcon_Http_Response_Cookies.html"><em>Phalcon\Http\Response\Cookies</em></a></td><td>是</td></tr><tr class="row-even"><td>filter</td><td>輸入過濾服務</td><td><a class="reference internal" href="../api/Phalcon_Filter.html"><em>Phalcon\Filter</em></a></td><td>是</td></tr><tr class="row-odd"><td>flash</td><td>閃現信息服務</td><td><a class="reference internal" href="../api/Phalcon_Flash_Direct.html"><em>Phalcon\Flash\Direct</em></a></td><td>是</td></tr><tr class="row-even"><td>flashSession</td><td>閃現session信息服務</td><td><a class="reference internal" href="../api/Phalcon_Flash_Session.html"><em>Phalcon\Flash\Session</em></a></td><td>是</td></tr><tr class="row-odd"><td>session</td><td>session服務</td><td><a class="reference internal" href="../api/Phalcon_Session_Adapter_Files.html"><em>Phalcon\Session\Adapter\Files</em></a></td><td>是</td></tr><tr class="row-even"><td>eventsManager</td><td>事件管理服務</td><td><a class="reference internal" href="../api/Phalcon_Events_Manager.html"><em>Phalcon\Events\Manager</em></a></td><td>是</td></tr><tr class="row-odd"><td>db</td><td>底層數據庫連接服務</td><td><a class="reference internal" href="../api/Phalcon_Db.html"><em>Phalcon\Db</em></a></td><td>是</td></tr><tr class="row-even"><td>security</td><td>安全助手</td><td><a class="reference internal" href="../api/Phalcon_Security.html"><em>Phalcon\Security</em></a></td><td>是</td></tr><tr class="row-odd"><td>crypt</td><td>加密/解密數據</td><td><a class="reference internal" href="../api/Phalcon_Crypt.html"><em>Phalcon\Crypt</em></a></td><td>是</td></tr><tr class="row-even"><td>tag</td><td>HTML生成助手</td><td><a class="reference internal" href="../api/Phalcon_Tag.html"><em>Phalcon\Tag</em></a></td><td>是</td></tr><tr class="row-odd"><td>escaper</td><td>內容(HTML)轉義</td><td><a class="reference internal" href="../api/Phalcon_Escaper.html"><em>Phalcon\Escaper</em></a></td><td>是</td></tr><tr class="row-even"><td>annotations</td><td>注釋分析器</td><td><a class="reference internal" href="../api/Phalcon_Annotations_Adapter_Memory.html"><em>Phalcon\Annotations\Adapter\Memory</em></a></td><td>是</td></tr><tr class="row-odd"><td>modelsManager</td><td>model管理服務</td><td><a class="reference internal" href="../api/Phalcon_Mvc_Model_Manager.html"><em>Phalcon\Mvc\Model\Manager</em></a></td><td>是</td></tr><tr class="row-even"><td>modelsMetadata</td><td>model元數據服務</td><td><a class="reference internal" href="../api/Phalcon_Mvc_Model_MetaData_Memory.html"><em>Phalcon\Mvc\Model\MetaData\Memory</em></a></td><td>是</td></tr><tr class="row-odd"><td>transactionManager</td><td>model事務管理服務</td><td><a class="reference internal" href="../api/Phalcon_Mvc_Model_Transaction_Manager.html"><em>Phalcon\Mvc\Model\Transaction\Manager</em></a></td><td>是</td></tr><tr class="row-even"><td>modelsCache</td><td>model的緩存服務</td><td>None</td><td><ul class="first last simple"><li/></ul></td></tr><tr class="row-odd"><td>viewsCache</td><td>view的緩存服務</td><td>None</td><td><ul class="first last simple"><li/></ul></td></tr></tbody></table>
### 自定義注入器(Implementing your own DI)[](# "永久鏈接至標題")
如果你要創建一個自定義注入器或者繼承一個已有的,接口 [*Phalcon\DiInterface*](#) 必須被實現。
|
- [索引](# "總目錄")
- [下一頁](# "MVC 架構(The MVC Architecture)") |
- [上一頁](# "示例列表(List of examples)") |
- Phalcon 2.0.6文檔
- API參考
- API列表
- Abstract class Phalcon\Acl
- Abstract class Phalcon\Acl\Adapter
- Class Phalcon\Acl\Adapter\Memory
- Interface Phalcon\Acl\AdapterInterface
- Class Phalcon\Acl\Exception
- Class Phalcon\Acl\Resource
- Interface Phalcon\Acl\ResourceInterface
- Class Phalcon\Acl\Role
- Interface Phalcon\Acl\RoleInterface
- Class Phalcon\Annotations\Annotation
- Abstract class Phalcon\Annotations\Adapter
- Class Phalcon\Annotations\Adapter\Apc
- Class Phalcon\Annotations\Adapter\Files
- Class Phalcon\Annotations\Adapter\Memory
- Class Phalcon\Annotations\Adapter\Xcache
- Interface Phalcon\Annotations\AdapterInterface
- Class Phalcon\Annotations\Collection
- Class Phalcon\Annotations\Exception
- Class Phalcon\Annotations\Reader
- Interface Phalcon\Annotations\ReaderInterface
- Class Phalcon\Annotations\Reflection
- Class Phalcon\Assets\Collection
- Class Phalcon\Assets\Exception
- Interface Phalcon\Assets\FilterInterface
- Class Phalcon\Assets\Filters\Cssmin
- Class Phalcon\Assets\Filters\Jsmin
- Class Phalcon\Assets\Filters\None
- Class Phalcon\Assets\Inline
- Class Phalcon\Assets\Inline\Css
- Class Phalcon\Assets\Inline\Js
- Class Phalcon\Assets\Manager
- Class Phalcon\Assets\Resource
- Class Phalcon\Assets\Resource\Css
- Class Phalcon\Assets\Resource\Js
- Abstract class Phalcon\Cache\Backend
- Class Phalcon\Cache\Backend\Apc
- Class Phalcon\Cache\Backend\File
- Class Phalcon\Cache\Backend\Libmemcached
- Class Phalcon\Cache\Backend\Memcache
- Class Phalcon\Cache\Backend\Memory
- Class Phalcon\Cache\Backend\Mongo
- Class Phalcon\Cache\Backend\Redis
- Class Phalcon\Cache\Backend\Xcache
- Interface Phalcon\Cache\BackendInterface
- Class Phalcon\Cache\Exception
- Class Phalcon\Cache\Frontend\Base64
- Class Phalcon\Cache\Frontend\Data
- Class Phalcon\Cache\Frontend\Igbinary
- Class Phalcon\Cache\Frontend\Json
- Class Phalcon\Cache\Frontend\None
- Class Phalcon\Cache\Frontend\Output
- Interface Phalcon\Cache\FrontendInterface
- Class Phalcon\Cache\Multiple
- Class Phalcon\Cli\Router\Route
- Class Phalcon\Config
- Class Phalcon\Config\Adapter\Ini
- Class Phalcon\Config\Adapter\Json
- Class Phalcon\Config\Adapter\Php
- Class Phalcon\Config\Adapter\Yaml
- Class Phalcon\Config\Exception
- Class Phalcon\Crypt
- Class Phalcon\Crypt\Exception
- Interface Phalcon\CryptInterface
- Abstract class Phalcon\Db
- Abstract class Phalcon\Db\Adapter
- Abstract class Phalcon\Db\Adapter\Pdo
- Class Phalcon\Db\Adapter\Pdo\Mysql
- Class Phalcon\Db\Adapter\Pdo\Oracle
- Class Phalcon\Db\Adapter\Pdo\Postgresql
- Class Phalcon\Db\Adapter\Pdo\Sqlite
- Interface Phalcon\Db\AdapterInterface
- Class Phalcon\Db\Column
- Interface Phalcon\Db\ColumnInterface
- Abstract class Phalcon\Db\Dialect
- Class Phalcon\Db\Dialect\Oracle
- Class Phalcon\Db\Dialect\Postgresql
- Class Phalcon\Db\Dialect\Sqlite
- Interface Phalcon\Db\DialectInterface
- Class Phalcon\Db\Exception
- Class Phalcon\Db\Index
- Interface Phalcon\Db\IndexInterface
- Class Phalcon\Db\Profiler
- Class Phalcon\Db\Profiler\Item
- Class Phalcon\Db\RawValue
- Class Phalcon\Db\Reference
- Interface Phalcon\Db\ReferenceInterface
- Class Phalcon\Db\Result\Pdo
- Interface Phalcon\Db\ResultInterface
- Class Phalcon\Debug
- Class Phalcon\Debug\Dump
- Class Phalcon\Debug\Exception
- Interface Phalcon\DiInterface
- Abstract class Phalcon\Dispatcher
- Interface Phalcon\DispatcherInterface
- Class Phalcon\Escaper
- Class Phalcon\Escaper\Exception
- Interface Phalcon\EscaperInterface
- Class Phalcon\Events\Event
- Interface Phalcon\Events\EventsAwareInterface
- Class Phalcon\Events\Exception
- Class Phalcon\Events\Manager
- Interface Phalcon\Events\ManagerInterface
- Class Phalcon\Exception
- Class Phalcon\Filter
- Class Phalcon\Filter\Exception
- Interface Phalcon\Filter\UserFilterInterface
- Interface Phalcon\FilterInterface
- Abstract class Phalcon\Flash
- Class Phalcon\Flash\Direct
- Class Phalcon\Flash\Exception
- Class Phalcon\Flash\Session
- Interface Phalcon\FlashInterface
- Class Phalcon\Forms\Form
- Abstract class Phalcon\Forms\Element
- Class Phalcon\Forms\Element\Check
- Class Phalcon\Forms\Element\Email
- Class Phalcon\Forms\Element\File
- Class Phalcon\Forms\Element\Date
- Class Phalcon\Forms\Element\Hidden
- Class Phalcon\Forms\Element\Numeric
- Class Phalcon\Forms\Element\Password
- Class Phalcon\Forms\Element\Radio
- Class Phalcon\Forms\Element\Select
- Class Phalcon\Forms\Element\Submit
- Class Phalcon\Forms\Element\Text
- Class Phalcon\Forms\Element\TextArea
- Interface Phalcon\Forms\ElementInterface
- Class Phalcon\Forms\Exception
- Class Phalcon\Forms\Manager
- Class Phalcon\Http\Cookie
- Class Phalcon\Http\Cookie\Exception
- Class Phalcon\Http\Request
- Class Phalcon\Http\Request\Exception
- Class Phalcon\Http\Request\File
- Interface Phalcon\Http\Request\FileInterface
- Interface Phalcon\Http\RequestInterface
- Class Phalcon\Http\Response
- Class Phalcon\Http\Response\Cookies
- Interface Phalcon\Http\Response\CookiesInterface
- Class Phalcon\Http\Response\Exception
- Class Phalcon\Http\Response\Headers
- Interface Phalcon\Http\Response\HeadersInterface
- Interface Phalcon\Http\ResponseInterface
- Class Phalcon\Image
- Abstract class Phalcon\Image\Adapter
- Class Phalcon\Image\Adapter\Imagick
- Interface Phalcon\Image\AdapterInterface
- Class Phalcon\Image\Exception
- Class Phalcon\Kernel
- Class Phalcon\Loader
- Class Phalcon\Loader\Exception
- Abstract class Phalcon\Logger
- Abstract class Phalcon\Logger\Adapter
- Class Phalcon\Logger\Adapter\File
- Class Phalcon\Logger\Adapter\Firephp
- Class Phalcon\Logger\Adapter\Stream
- Class Phalcon\Logger\Adapter\Syslog
- Interface Phalcon\Logger\AdapterInterface
- Class Phalcon\Logger\Exception
- Abstract class Phalcon\Logger\Formatter
- Class Phalcon\Logger\Formatter\Firephp
- Class Phalcon\Logger\Formatter\Json
- Class Phalcon\Logger\Formatter\Line
- Class Phalcon\Logger\Formatter\Syslog
- Interface Phalcon\Logger\FormatterInterface
- Class Phalcon\Logger\Item
- Class Phalcon\Logger\Multiple
- Class Phalcon\Mvc\Application
- Class Phalcon\Mvc\Application\Exception
- Abstract class Phalcon\Mvc\Collection
- Abstract class Phalcon\Mvc\Collection\Behavior
- Class Phalcon\Mvc\Collection\Behavior\SoftDelete
- Class Phalcon\Mvc\Collection\Behavior\Timestampable
- Interface Phalcon\Mvc\Collection\BehaviorInterface
- Class Phalcon\Mvc\Collection\Document
- Class Phalcon\Mvc\Collection\Exception
- Class Phalcon\Mvc\Collection\Manager
- Interface Phalcon\Mvc\Collection\ManagerInterface
- Interface Phalcon\Mvc\CollectionInterface
- Abstract class Phalcon\Mvc\Controller
- Interface Phalcon\Mvc\ControllerInterface
- Class Phalcon\Mvc\Dispatcher
- Class Phalcon\Mvc\Dispatcher\Exception
- Interface Phalcon\Mvc\DispatcherInterface
- Interface Phalcon\Mvc\EntityInterface
- Class Phalcon\Mvc\Micro
- Class Phalcon\Mvc\Micro\Collection
- Interface Phalcon\Mvc\Micro\CollectionInterface
- Class Phalcon\Mvc\Micro\Exception
- Class Phalcon\Mvc\Micro\LazyLoader
- Interface Phalcon\Mvc\Micro\MiddlewareInterface
- Abstract class Phalcon\Mvc\Model
- Abstract class Phalcon\Mvc\Model\Behavior
- Class Phalcon\Mvc\Model\Behavior\SoftDelete
- Class Phalcon\Mvc\Model\Behavior\Timestampable
- Interface Phalcon\Mvc\Model\BehaviorInterface
- Class Phalcon\Mvc\Model\Criteria
- Interface Phalcon\Mvc\Model\CriteriaInterface
- Class Phalcon\Mvc\Model\Exception
- Class Phalcon\Mvc\Model\Manager
- Interface Phalcon\Mvc\Model\ManagerInterface
- Class Phalcon\Mvc\Model\Message
- Interface Phalcon\Mvc\Model\MessageInterface
- Abstract class Phalcon\Mvc\Model\MetaData
- Class Phalcon\Mvc\Model\MetaData\Apc
- Class Phalcon\Mvc\Model\MetaData\Files
- Class Phalcon\Mvc\Model\MetaData\Libmemcached
- Class Phalcon\Mvc\Model\MetaData\Memcache
- Class Phalcon\Mvc\Model\MetaData\Memory
- Class Phalcon\Mvc\Model\MetaData\Session
- Class Phalcon\Mvc\Model\MetaData\Strategy\Annotations
- Class Phalcon\Mvc\Model\MetaData\Strategy\Introspection
- Interface Phalcon\Mvc\Model\MetaData\StrategyInterface
- Class Phalcon\Mvc\Model\MetaData\Xcache
- Interface Phalcon\Mvc\Model\MetaDataInterface
- Class Phalcon\Mvc\Model\Query
- Class Phalcon\Mvc\Model\Query\Builder
- Interface Phalcon\Mvc\Model\Query\BuilderInterface
- Abstract class Phalcon\Mvc\Model\Query\Lang
- Class Phalcon\Mvc\Model\Query\Status
- Interface Phalcon\Mvc\Model\Query\StatusInterface
- Interface Phalcon\Mvc\Model\QueryInterface
- Class Phalcon\Mvc\Model\Relation
- Interface Phalcon\Mvc\Model\RelationInterface
- Interface Phalcon\Mvc\Model\ResultInterface
- Abstract class Phalcon\Mvc\Model\Resultset
- Class Phalcon\Mvc\Model\Resultset\Complex
- Class Phalcon\Mvc\Model\Resultset\Simple
- Abstract class Phalcon\Mvc\Model\Validator
- Class Phalcon\Mvc\Model\Validator\Email
- Class Phalcon\Mvc\Model\Validator\Exclusionin
- Class Phalcon\Mvc\Model\Validator\Inclusionin
- Class Phalcon\Mvc\Model\Validator\Ip
- Class Phalcon\Mvc\Model\Validator\Numericality
- Class Phalcon\Mvc\Model\Validator\PresenceOf
- Class Phalcon\Mvc\Model\Validator\Regex
- Class Phalcon\Mvc\Model\Validator\StringLength
- Class Phalcon\Mvc\Model\Validator\Uniqueness
- Class Phalcon\Mvc\Model\Validator\Url
- Interface Phalcon\Mvc\Model\ValidatorInterface
- Interface Phalcon\Mvc\Model\ResultsetInterface
- Class Phalcon\Mvc\Model\Row
- Class Phalcon\Mvc\Model\Transaction
- Class Phalcon\Mvc\Model\Transaction\Exception
- Class Phalcon\Mvc\Model\Transaction\Failed
- Class Phalcon\Mvc\Model\Transaction\Manager
- Interface Phalcon\Mvc\Model\Transaction\ManagerInterface
- Interface Phalcon\Mvc\Model\TransactionInterface
- Class Phalcon\Mvc\Model\ValidationFailed
- Interface Phalcon\Mvc\ModelInterface
- Interface Phalcon\Mvc\ModuleDefinitionInterface
- Class Phalcon\Mvc\Router
- Class Phalcon\Mvc\Router\Annotations
- Class Phalcon\Mvc\Router\Exception
- Class Phalcon\Mvc\Router\Group
- Interface Phalcon\Mvc\Router\GroupInterface
- Class Phalcon\Mvc\Router\Route
- Interface Phalcon\Mvc\Router\RouteInterface
- Interface Phalcon\Mvc\RouterInterface
- Class Phalcon\Mvc\Url
- Class Phalcon\Mvc\Url\Exception
- Interface Phalcon\Mvc\UrlInterface
- Class Phalcon\Mvc\User\Component
- Class Phalcon\Mvc\User\Module
- Class Phalcon\Mvc\User\Plugin
- Class Phalcon\Mvc\View
- Abstract class Phalcon\Mvc\View\Engine
- Class Phalcon\Mvc\View\Engine\Php
- Class Phalcon\Mvc\View\Engine\Volt
- Class Phalcon\Mvc\View\Engine\Volt\Compiler
- Interface Phalcon\Mvc\View\EngineInterface
- Class Phalcon\Mvc\View\Exception
- Class Phalcon\Mvc\View\Simple
- Interface Phalcon\Mvc\ViewBaseInterface
- Interface Phalcon\Mvc\ViewInterface
- Abstract class Phalcon\Paginator\Adapter
- Class Phalcon\Paginator\Adapter\Model
- Class Phalcon\Paginator\Adapter\NativeArray
- Class Phalcon\Paginator\Adapter\QueryBuilder
- Interface Phalcon\Paginator\AdapterInterface
- Class Phalcon\Paginator\Exception
- Class Phalcon\Queue\Beanstalk
- Class Phalcon\Queue\Beanstalk\Job
- Final class Phalcon\Registry
- Class Phalcon\Security
- Class Phalcon\Security\Exception
- Abstract class Phalcon\Session
- Abstract class Phalcon\Session\Adapter
- Class Phalcon\Session\Adapter\Files
- Class Phalcon\Session\Adapter\Libmemcached
- Class Phalcon\Session\Adapter\Memcache
- Interface Phalcon\Session\AdapterInterface
- Class Phalcon\Session\Bag
- Interface Phalcon\Session\BagInterface
- Class Phalcon\Session\Exception
- Class Phalcon\Tag
- Class Phalcon\Tag\Exception
- Abstract class Phalcon\Tag\Select
- Abstract class Phalcon\Text
- Abstract class Phalcon\Translate
- Abstract class Phalcon\Translate\Adapter
- Class Phalcon\Translate\Adapter\Csv
- Class Phalcon\Translate\Adapter\Gettext
- Class Phalcon\Translate\Adapter\NativeArray
- Interface Phalcon\Translate\AdapterInterface
- Class Phalcon\Translate\Exception
- Class Phalcon\Validation
- Class Phalcon\Validation\Exception
- Class Phalcon\Validation\Message
- Class Phalcon\Validation\Message\Group
- Interface Phalcon\Validation\MessageInterface
- Abstract class Phalcon\Validation\Validator
- Class Phalcon\Validation\Validator\Alnum
- Class Phalcon\Validation\Validator\Alpha
- Class Phalcon\Validation\Validator\Between
- Class Phalcon\Validation\Validator\Confirmation
- Class Phalcon\Validation\Validator\Digit
- Class Phalcon\Validation\Validator\Email
- Class Phalcon\Validation\Validator\ExclusionIn
- Class Phalcon\Validation\Validator\File
- Class Phalcon\Validation\Validator\Identical
- Class Phalcon\Validation\Validator\InclusionIn
- Class Phalcon\Validation\Validator\Numericality
- Class Phalcon\Validation\Validator\PresenceOf
- Class Phalcon\Validation\Validator\Regex
- Class Phalcon\Validation\Validator\StringLength
- Class Phalcon\Validation\Validator\Uniqueness
- Class Phalcon\Validation\Validator\Url
- Interface Phalcon\Validation\ValidatorInterface
- Class Phalcon\Version
- 參考手冊
- 安裝(Installation)
- 教程 1:讓我們通過例子來學習(Tutorial 1: Let’s learn by example)
- 教程 2:Introducing INVO(Tutorial 2: Introducing INVO)
- 教程 3: Securing INVO
- 教程 4: Using CRUDs
- 教程 5: Customizing INVO
- 教程 6: Vkuró
- 教程 7:創建簡單的 REST API(Tutorial 7: Creating a Simple REST API)
- 示例列表(List of examples)
- 依賴注入與服務定位器(Dependency Injection/Service Location)
- MVC 架構(The MVC Architecture)
- 使用控制器(Using Controllers)
- 使用模型(Working with Models)
- 模型元數據(Models Meta-Data)
- 事務管理(Model Transactions)
- Phalcon 查詢語言(Phalcon Query Language (PHQL))
- 緩存對象關系映射(Caching in the ORM)
- 對象文檔映射 ODM (Object-Document Mapper)
- 使用視圖(Using Views)
- 視圖助手(View Helpers)
- 資源文件管理(Assets Management)
- Volt 模版引擎(Volt: Template Engine)
- MVC 應用(MVC Applications)
- 路由(Routing)
- 調度控制器(Dispatching Controllers)
- 微應用(Micro Applications)
- 使用命名空間(Working with Namespaces)
- 事件管理器(Events Manager)
- Request Environment
- 返回響應(Returning Responses)
- Cookie 管理(Cookies Management)
- 生成 URL 和 路徑(Generating URLs and Paths)
- 閃存消息(Flashing Messages)
- 使用 Session 存儲數據(Storing data in Session)
- 過濾與清理(Filtering and Sanitizing)
- 上下文編碼(Contextual Escaping)
- 驗證(Validation)
- 表單(Forms)
- 讀取配置(Reading Configurations)
- 分頁(Pagination)
- 使用緩存提高性能(Improving Performance with Cache)
- 安全(Security)
- Encryption/Decryption
- 訪問控制列表 ACL(Access Control Lists ACL)
- 多語言支持(Multi-lingual Support)
- Universal Class Loader
- 日志記錄(Logging)
- 注釋解析器(Annotations Parser)
- 命令行應用(Command Line Applications)
- 隊列(Queueing)
- 數據庫抽象層(Database Abstraction Layer)
- 國際化(Internationalization)
- 數據庫遷移(Database Migrations)
- 調試應用程序(Debugging Applications)
- Phalcon 開發工具(Phalcon Developer Tools)
- 提高性能:下一步該做什么?(Increasing Performance: What’s next?)
- 單元測試(Unit testing)
- 授權(License)