依賴注入php
⑴ php如何實現依賴注入
網上都有現成的代碼。我就隨便寫一個吧
⑵ php function括弧里(類名 變數名)這種寫法是什麼意思
php本來是弱類型語言,經過這幾年的發展,php也支持了類型判斷,比如可以聲明一個函數變數為
function test(int $a):int{}
對於類名,變數名這種寫法,是php5中引入的,這樣目的就是對參數進行限定,可以提前判斷出不符合類型的變數輪辯傳入。
依賴注入是一種設計模式,而它依賴的就是這個功能,螞桐判通過注入不同的類來實現不同悶改的功能。
⑶ 實現地址自動識別實例(PHP)
文章正文
址自動識別現在普遍,特別是用在快遞填寫地址,姓名,手機號碼的時候,會把這些按照一定的規范填寫後,點擊自動識別後,會自動填寫到各自的input。最近也簡單的實現了這個功能,給後台添加用戶的時候,自動識別地址。以下是效果圖
具體問題具體姿凱分析!代碼實現基於laravel完成。一個laravel完整的功能得具備這些:路由route,Model, View, Controller, 我這里用的有依賴注入服務容器等功能,當然,用到地址,你首先要有地址庫。。。
下面來看看是如何實現的,這里我只貼出核心代碼
UsersController控制器
在伏冊握這里新建構造函數,實現容器的依賴注入 UsersRepository
接下來就新缺慶建地址識別的方法, $discernDel 接收的數據是從前端傳過來的,後面再貼前端代碼。 業務代碼處理交給容器 UsersRepository 里的方法 getDiscern 處理
來看看 userRepository容器處理地址識別的各種業務代碼
上面的方法處理手機,名稱,和地址處理,地址處理有些繁雜,因為有時候填寫的地址有不一樣的,比如廣西省,有些就填寫廣西壯族自治區,所以 getAddressArrar 方法處理地址匹配信息,根據自己的業務做調整,如下
前端html部分代碼
基本上能看得懂的。jquery用到 getDiscern(); 方法,手機號碼,姓名,地址等input這里就不一一列出了。大家根據下面的jquery都能想像到
jquery代碼部分
ajax post後交給url: getDiscern 處理,這個就是上面controller的方法,success返回的數據後再追加到每個input里,最後再清除掉自動識別地址框的數據
整個過程簡單,又清晰明了,以上就是我的代碼,分享給大家,覺得哪個地方不對勁的,歡迎留言吐槽!
⑷ /api/contracts/overview/{contractId}要怎麼請求介面
在Laravel5中出現了一個新的東西,叫做contracts,那麼它到底是什麼?有什麼用?怎麼用?我們就來探討下吧。 我們先來看看官方文檔中對contracts的定義: Laravel's Contracts are a set of interfaces that define the core services provided by the framework.
意思是說Laravel的Contracts是一個由 框架提供 的定義了 核心服務介面 的集合。 也就是說,每一個Contract都是一個介面,對應一個框架核心服務。 那它的意義何在?官網給出的解釋也很簡單:使用介面是為了 松耦合 和 簡單 。 先不講大道舉胡理,先來點干貨,看看怎麼正物攔使用contract 先瀏覽下contracts介面列表: 代碼如下:
IlluminateContractsAuthGuard
…… 太多了,懶得繼續貼了,官網手冊里有。我們就拿 這個contract來演示一下吧。
首先,打開 app/Providers/AppServiceProvider.php,注意register方法: 代碼如下:
public function register()
{
$this->app->bind(
'',
'AppServicesRegistrar'
);
} $this->app 就是Application對象,也是容器對象,通過 $this->app->bind 方法我們綁定了一個實現螞旅介面的類AppServicesRegistrar。 注意,就是一個contract。AppServicesRegistrar 這個類文件在 app/Services/Registrar.php。 接著我們看 這個控制器類,看到它有 __construct 構造函數: 代碼如下:
public function __construct(Guard $auth, Registrar $registrar)
{
$this->auth = $auth;
$this->registrar = $registrar; $this->middleware('guest', ['except' => 'getLogout']);
} 它有兩個參數,對應的類命名空間在腳本開頭可以看到: 代碼如下:
use IlluminateContractsAuthGuard;
use ; 這兩個都是contract,但我們這里就拿 Registrar 說,我們注意到這裡面只是通過參數類型指明了$registrar的介面類型,而實際調用的時候實際上是 AppServicesRegistrar 這個類,這就是依賴注入的特性了,Laravel會自動在容器中搜索實現了介面的類或對象,有的話就取出來作為實際參數傳到構造函數里。 整個使用流程其實就可以總結為兩個步驟: 向容器中注冊實現contract介面的對象。
構造函數參數類型指定為contract介面類,框架會自動找到符合條件的對象。
那麼再來說說contract的好處。 松耦合 官網給了一個例子解釋什麼是緊耦合以及Contract介面為何能夠松耦合。 先來看看緊耦合的代碼: 代碼如下:
<?php namespace AppOrders;
class Repository {
/**
* The cache.
*/
protected $cache;
/**
* Create a new repository instance.
*
* @param SomePackageCacheMemcached $cache
* @return void
*/
public function __construct(SomePackageCacheMemcached $cache)
{
$this->cache = $cache;
}
/**
* Retrieve an Order by ID.
*
* @param int $id
* @return Order
*/
public function find($id)
{
if ($this->cache->has($id))
{
//
}
}
} 可以看到構造函數中注入了一個詳細的緩存實現 SomePackageCacheMemcached ,如果換Redis作為緩存伺服器或者更改了api方法,就需要修改,而如果項目很大,你不知道還有多少地方需要修改。 那麼,Contract介面是如何解決這個問題的?請看代碼: 代碼如下:
<?php namespace AppOrders;
use as Cache;
class Repository {
/**
* Create a new repository instance.
*
* @param Cache $cache
* @return void
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
} 注意,緩存實現我們使用了一個介面,也就是contract,,因為它只是介面,不需要關心背後是memcache還是redis。 簡單性 如果所有服務都使用介面定義,就可以很簡單的決定一個服務需要的功能,更加容易維護和擴展,並且contract介面還能看作一個簡潔的文檔便於閱讀。
⑸ php依賴注入是在構造函數中注入嗎
PHP 依賴注入
tags: dependency injection,php
by Ryan on January 8, 2009
Dependency injection is the answer to more maintainable, testable, molar code.
依賴注入是對於要求更易維護,更易測試,更加模塊化的代碼的答案。
Every project has dependencies and the more complex the project is the more dependencies it will most likely have. The most common dependency in today』s web application is the database and chances are if it goes down the app will all together stop working. That is because the code is dependent on the database server… and that is perfectly fine. Not using a database server because it could one day crash is a bit ridiculous. Even though the dependency has its flaws, it still makes life for the code, and thus the developer, a lot easier.
每個項目都有依賴(外界提供的輸入), 項目越復雜,越需要更多的依賴。在現今的網路應用程序中,最常見的依賴是資料庫,其風險在於,一旦資料庫暫停運行,那麼整個程序也因此而停止運行。這是因為代碼依賴資料庫伺服器。。。這已足夠。因為資料庫伺服器有時會崩潰而棄用它是荒謬的。盡管依賴有其自身的瑕疵,它仍然使代碼,因而也使程序開發人員的生活更容易些。
The problem with most dependencies its the way that code handles and interacts with them, meaning, the problem is the code and not the dependency. If you are not using dependency injection, chances are your code looks something like this:
對於大多依賴而言,問題在於代碼如何處理它們及與它們交往。也就是說,問題是代碼本身而非依賴。如果你沒有使用依賴注入,有機會遇到下列代碼:
class Book {
publicfunction __construct(){
$registry = RegistrySingleton::getInstance();
$this->_databaseConnection=$registry->databaseConnection;
// or
global$databaseConnection;
$this->_databaseConnection=$databaseConnection;
}
}
The book object now is given full access to the database once it is constructed. That is good, the book needs to be able to talk to the database and pull data. The problem lies in the way the book gained its access. In order for the book to be able to talk to the database the code must have an outside variable named $databaseConnection, or worse, it must have a singleton pattern class (registry) object containing a record for a databaseConnection. If these don』t exist the book fails, making this code is far from molar.
現在對象book一旦建立,就已經完全連到資料庫。這沒什麼不好,book需要跟資料庫交談並取得數據。問題在於book取得其接入的方法。要使book能夠與資料庫交談,代碼必須有一個外來的變數$databaseConnect, 更糟糕的是,它必須有個singleton類型類(registry)的對象,其包含一個databaseConnection的記錄。如果這些不存在的話,book會無法運行,這就使得這些代碼遠遠不夠模塊化。
This raises the question, how exactly does the book get access to the database? This is where inversion of control comes in.
這就提出一個問題,到底book如何接入資料庫?這就是IoC出現的原因了。
In Hollywood a struggling actor does not call up Martin Scorsese and ask for a role in his next film. No, the opposite happens. Martin Scorsese calls up the broke actor and asks him to play the main character in his next movie. Objects are struggling actors, they do not get to pick the roles they play, the director needs to tell them what to do. Objects do not get to pick the outside systems they interact with, instead, the outside systems are given to the objects. Remember this as Inversion of Control: The Hollywood Way.
在好萊塢,一個瀕臨絕境的演員不會打電話給Martin Scoresese要求在他的下個影片中扮演一個角色。絕不會這樣,實際正相反。Martin Scorese 會打電話給這個困頓的演員並邀請他在下一部影片中扮演重要的角色。對象是掙扎中的演員,他們不會去撿自己所扮演的角色,導演需要告訴他們去做什麼。對象不會到它所接觸的外界挑選系統,相反,外界系統會被賦予對象。記住這就是IoC( Inversion of Control):好萊塢的做法。
This is how a developer tells his objects how to interact with outside dependencies:
如下是開發人員告訴他的對象如何與外界的依賴打交道:
class Book {
publicfunction __construct(){}
publicfunction setDatabaseConnection($databaseConnection){
$this->_databaseConnection=$databaseConnection;
}
}
$book=new Book();
$book->setDatabase($databaseConnection);
This code allows for the book class to be used in any web app. The Book is no longer dependent on anything other than the developer supplying a database shortly after object creation.這代碼允許這個book類能在任何的網頁程序中使用。此book不再依賴任何事項,除了程序開發者要在對象創建後立即要提供一個資料庫。
This is, at its finest, dependency injection. There are two common practices of injecting dependencies. The first being constructor injection and the second being setter injection. Constructor injection involves passing all of the dependencies as arguments when creating a new object. The code would look something like this:
這就是最佳方法—依賴注入。有兩種常用的依賴注入的方式。一種是 constructor (註:構造函數。這種譯法似乎並不恰當,類中此方法更多是用來對某些屬性進行初始化)注入,一種是setter 注入。Constructor注入涉及到將所有依賴作為參數,傳遞給新創建的對象。看起來像這樣:
$book=new Book($databaseConnection,$configFile);
The more dependencies an object has, the messier this construction becomes. There are other reasons why this is a bad approach, involving ideas around code reusability and constructors doing work.
對象的依賴越多,construction就會變得越雜亂。這里還有其他的原因為什麼這是一個壞方法,其涉及到包括代碼重用和constructors要做的工作。
This leaves us with other method of dependency injection, called setting injection, which involves creating a public method inside the object for the dependencies that need injection.
這就給我們留下其他的方法進行依賴注入,稱為設置注入,包含在需要注入依賴的對象里創建一個公共方法:
$book=new Book();
$book->setDatabase($databaseConnection);
$book->setConfigFile($configFile);
This is easy to follow, but it leads writing more and more code for your application. When a book object is created three lines of code are required. If we have to inject another dependency, a 4th line of code is now needed. This gets messy quickly.
這很容易實現,但是它會導致為您的程序寫大量代碼。當創建一個book對象時,需要三行代碼。如果我們必須注入另外的依賴時,必須增加第四行代碼。這很快變得一團糟。
The answer to this problem is a factory, which is class that is designed to create and then inject all the dependencies needed for an object. Here is an example:
此問題的對策是一個工廠factory,它是一個類,用來創建然後注入一個對象的所有依賴。舉例如下:
class Factory {
public static $_database;
public static function makeBook(){
$book=new Book();
$book->setDatabase(self::$_database);
// more injection...(更多注入)
return$book;
}
}
And then:
然後:
$book= Factory::makeBook();
All dependencies should be registered into the factory object ring run time. This object is now the gateway that all dependencies must pass through before they can interact with any classes. In other words, this is the dependency container.
所有的依賴在運行期間都應在此factory對象中注冊。它現在是大門,在依賴可以與任何對象打交道前,都必經此門。
The reason makeBook is a public static function is for ease of use and global access. When I started this article off I made a reference to the singleton pattern and global access being a poor choices of code. They are… for the most part. It is bad design when they control access, but it is perfectly ok when they control creation. The makeBook function is only a shortcut for creation. There is no dependency what-so-ever between the book class and the factory class. The factory class exists so we can contain our dependencies in one location and automatically inject those dependencies with one line of code creation.
makeBook作為一個靜態方法的原因是易用並且可以在全局得到。在本文開頭,我提出使用singleton類型和全局變數對代碼而言是一個糟糕的選擇。多數情形下,確實如此!當他們控制接入時,是一個差設計。但是在他們控制創建時,是一個不錯的選擇。makeBook方法僅僅是創建的一個捷徑。在book類和factory類之間,沒有任何依賴。由於factory類的存在,我們的依賴可以存放在一個地點,並且用一行創建代碼就可自動注入這些依賴。
The factory or container class removes all of the extra work of dependency injection.
此處的factory或者容器類移走了依賴注入的所有額外工作。
Before injection:
以前的注入:
$book=new Book();
And now:
目前的方法:
$book= Factory::makeBook();
Hardly any extra work, but tons of extra benefits.
幾乎沒有任何的額外工作,但是有大量益處。
When test code is run, specifically unit tests, the goal is to see if a method of a class is working correctly. Since the book class requires database access to read the book data it adds a whole layer of complexity. The test has to acquire a database connection, pull data, and test it. All of a sudden the test is no longer testing a single method in the book class, it is now also testing database. If the database is offline, the test would fail. This is FAR from the goal a unit test.當運行測試代碼時,尤其是單元測試,其目標是檢查類中的方法是否正確地工作。由於book類要求接入資料庫並且讀取圖書數據,它增加了一層復雜度。此測試不得不進行資料庫連接,取得數據,然後測試它。瞬間,測試不再是測試book類中的單個方法,它目前同時也測試資料庫。如果資料庫離線,測試就會失敗。這已經遠離了單元測試的目的。
A way of dealing with this is just using a different database dependency for the unit tests. When the test suite starts up a mmy database is injected into the book. The mmy database will always have the data the developer expects it to have. If a live database was used in a unit test the data could potentially change causing tests to unnecessarily fail. There is no need for a unit test to be refactored when a record in a database changes.
解決上述問題的方法是用不同的資料庫依賴來作單元測試。當測試套件開始時,虛擬的資料庫被注入book.虛擬資料庫將永遠擁有開發人員所期待的數據。如果使用一個真實資料庫,數據的潛在變化會導致測試不必要的失敗。當資料庫的記錄改變了,不需因此重新進行單元測試。
The code is more molar because it can dropped into any other web application. Create the book object and inject a database connection with $book->setDatabase(). It does not matter if the database is in Registery::Database, $database, or $someRandomDatabaseVarible. As long as there is a database connection the book will work inside any system.
此代碼現在更加模塊化,因為它可以被放到任何其他的網頁程序。創建book對象並且用$book->setDatabase()注入資料庫連接。此時,資料庫在 Registery::Database, $database,或者$someRandomDatabaseVarible都無關大局。只要有一個資料庫連接,book就可以在任何系統內工作。
The code is more maintainable because each object given exactly what it needs. If separate database connections are required between different instances of the same class then there no extra code needed inside the class what-so-ever. Give book1 access to database1 and book2 access to database2.
代碼更加易維護,因為每個對象都被賦予了它的所需。如果同一類的實例需要不同的資料庫連接,在類內部一點兒也不需要額外的代碼。例如book1連接到資料庫1,book2連接到資料庫2
Factory::$_database=$ourDatabaseVarForDB1;
$book1= Factory::makeBook();
$book2= Factory::makeBook();
$book2->setDatabase($database2);
Dependency injection really is the answer to more maintainable, testable, molar code.
依賴注入真的是更易維護,更易測試和更加模塊化的答案。
⑹ php IOC容器的理解
依賴注入是指一個類必須依賴另一個實例才能進行實例化。
進一步圓團利用簡大介面
升華攔腔豎-IOC容器
使用示例
⑺ 怎麼能通俗易通的了解php中的反射和依賴注入這兩個概念
除非你去開發類似ZendFramework, ThinkPHP, CakePHP之類的框架,幾乎沒有機會用到這個。
這是很底層的東西,尤其是依賴注入這種東西的應用場景就是輔助開發,選型的框架支持依賴注入就行了,沒必要自己實現。而反射這個東西也差不多,在業務邏輯中我從來沒遇到過必須要靠反射解決的問題,同樣也是框架才用到。
⑻ PHP中什麼是依賴注入
依賴注入可能是我所知道的最簡單設計模式之一,很多情況下可能你無意識中已經使用了依賴注入。不過它也是最難解釋的一個。我認為有一部分原因是由於大多數介紹依賴注入的例子缺乏實際意義,讓人難理解。因為PHP主要用於Web開發,那就先來看一個簡單的web開發實例。
HTTP本身是一個無狀態的連接協議,為了支持客戶在發起WEB請求時應用程序能存儲用戶信息,我們就需要通過一種技術來實現存儲狀態交互。理所當然最簡單的是使用cookie,更好的方式是PHP內置的Session機制。
$_SESSION['language'] = 'fr';
上面代碼將用戶語言存儲在了名為language的Session變數中,因此在該用戶隨後的請求中,可以通過全局數組$_SESSION來獲取language:
$user_language = $_SESSION['language'];
依賴注入主要用於面向對像開發,現在讓我們假設我們有一個SessionStorage類,該類封裝了PHP Session機制:
class SessionStorage
{
function __construct($cookieName = 'PHP_SESS_ID')
{
session_name($cookieName);
session_start();
}
function set($key, $value)
{
$_SESSION[$key] = $value;
}
function get($key)
{
return $_SESSION[$key];
}
// ...
}
同時還有一個User類提供了更高級的封裝:
class User
{
protected $storage;
function __construct()
{
$this->storage = new SessionStorage();
}
function setLanguage($language)
{
$this->storage->set('language', $language);
}
function getLanguage()
{
return $this->storage->get('language');
}
// ...
}
代碼很簡單,同樣使用User類也很簡單:
$user = new User();
$user->setLanguage('fr');
$user_language = $user->getLanguage();
一切都很美好,除非你的程序需要更好的擴展性。假設現在你想要更改保存session_id的COOKIE鍵值,以下有一些可供選擇的方法:
User類中創建SessionStorage實例時,在SessionStorage構造方法中使用字元串』SESSION_ID』硬編碼:
class User
{
function __construct()
{
$this->storage = new SessionStorage('SESSION_ID');
}
// ...
}
在User類外部設置一個常量(名為STORAGE_SESSION_NAME)
class User
{
function __construct()
{
$this->storage = new SessionStorage(STORAGE_SESSION_NAME);
}
// ...
}
define('STORAGE_SESSION_NAME', 'SESSION_ID');
通過User類構造函數中的參數傳遞Session name
class User
{
function __construct($sessionName)
{
$this->storage = new SessionStorage($sessionName);
}
// ...
}
$user = new User('SESSION_ID');
還是通過User類構造函數中的參數傳遞Session name,不過這次參數採用數組的方式
class User
{
function __construct($storageOptions)
{
$this->storage = new SessionStorage($storageOptions['session_name']);
}
// ...
}
$user = new User(array('session_name' => 'SESSION_ID'));
上面的方式都很糟糕。
在user類中硬編碼設置session name的做法沒有真正解決問題,如果以後你還需要更改保存session_id的COOKIE鍵值,你不得不再一次修改user類(User類不應該關心COOKIE鍵值)。
使用常量的方式同樣很糟,造成User類依賴於一個常量設置。
通過User類構造函數的參數或數組來傳遞session name相對來說好一些,不過也不完美,這樣做干擾了User類構造函數的參數,因為如何存儲Session並不是User類需要關心的,User類不應該和它們扯上關聯。
另外,還有一個問題不太好解決:我們如何改變SessionStorage類。這種應用場景很多,比如你要用一個Session模擬類來做測試,或者你要將Session存儲在資料庫或者內存中。目前這種實現方式,在不改變User類的情況下,很難做到這點。
現在,讓我們來使用依賴注入。回憶一下,之前我們是在User類內部創建SessionStorage對像的,現在我們修改一下,讓SessionStorage對像通過User類的構造函數傳遞進去。
class User
{
function __construct($storage)
{
$this->storage = $storage;
}
// ...
這就是依賴注入最經典的案例,沒有之一。現在使用User類有一些小小的改變,首先你需要創建SessionStorage對像。
$storage = new SessionStorage('SESSION_ID');
$user = new User($storage);
現在,配置session存儲對像很簡單了,同樣如果改變session存儲對像也很簡單,所有這一切並不需要去更新User類,降低了業務類之間的耦合。
Pico Container 的網站上是這樣描述依賴注入:
依賴注入是通過類的構造函數、方法、或者直接寫入的方式,將所依賴的組件傳遞給類的方式。
所以依賴注入並不只限於通過構造函數注入。下面來看看幾種注入方式:
構造函數注入
class User
{
function __construct($storage)
{
$this->storage = $storage;
}
// ...
}
setter方法注入
class User
{
function setSessionStorage($storage)
{
$this->storage = $storage;
}
// ...
}
屬性直接注入
class User
{
public $sessionStorage;
}
$user->sessionStorage = $storage;
根據經驗,一般通過構造函數注入的是強依賴關系的組件,setter方式用來注入可選的依賴組件。
現在,大多數流行的PHP框架都採用了依賴注入的模式實現業務組件間的高內聚低耦合。
// symfony: 構造函數注入的例子
$dispatcher = new sfEventDispatcher();
$storage = new sfMySQLSessionStorage(array('database' => 'session', 'db_table' => 'session'));
$user = new sfUser($dispatcher, $storage, array('default_culture' => 'en'));
// Zend Framework: setter方式注入的例子
$transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
'auth' => 'login',
'username' => 'foo',
'password' => 'bar',
'ssl' => 'ssl',
'port' => 465,
));
$mailer = new Zend_Mail();
$mailer->setDefaultTransport($transport);
⑼ 自定義類的依賴注入
一、自定義類
新建文件:App\demo\fx.php
二、將fx類綁定到容器:
首先用artisan命令創建服伍衫務早桐者:php artisan make:provider myServiceProvider
然後綁定自腔睜腔定義類fx
三、將服務者myServiceProvider注冊到config\app.php中:
四、控制器中實現依賴注入