本篇文章给大家带来的内容是关于Laravel中的依赖注入和IoC的详细介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
作为开发者,我们一直在尝试通过使用设计模式和尝试新的健壮型框架来寻找新的方式来编写设计良好且健壮的代码。在本篇文章中,我们将通过 Laravel 的 IoC 组件探索依赖注入设计模式,并了解它如何改进我们的设计。
依赖注入
依赖注入一词是由 Martin Fowler 提出的术语,它是将组件注入到应用程序中的一种行为。就像 Ward Cunningham 说的:
依赖注入是敏捷架构中关键元素。
让我们看一个例子:
class UserProvider{ protected $connection; public function __construct(){ $this->connection = new Connection; } public function retrieveByCredentials( array $credentials ){ $user = $this->connection ->where( 'email', $credentials['email']) ->where( 'password', $credentials['password']) ->first(); return $user; } }
如果你要测试或者维护这个类,你必须访问数据库的实例来进行一些查询。为了避免必须这样做,你可以将此类与其他类进行 解耦 ,你有三个选项之一,可以将 Connection
类注入而不需要直接使用它。
将组件注入类时,可以使用以下三个选项之一:
构造方法注入
class UserProvider{ protected $connection; public function __construct( Connection $con ){ $this->connection = $con; } ...
Setter 方法注入
同样,我们也可以使用 Setter 方法注入依赖关系:
class UserProvider{ protected $connection; public function __construct(){ ... } public function setConnection( Connection $con ){ $this->connection = $con; } ...
接口注入
interface ConnectionInjector{ public function injectConnection( Connection $con ); } class UserProvider implements ConnectionInjector{ protected $connection; public function __construct(){ ... } public function injectConnection( Connection $con ){ $this->connection = $con; } }
当一个类实现了我们的接口时,我们定义了 injectConnection
方法来解决依赖关系。
优势
现在,当测试我们的类时,我们可以模拟依赖类并将其作为参数传递。每个类必须专注于一个特定的任务,而不应该关心解决它们的依赖性。这样,你将拥有一个更专注和可维护的应用程序。
如果你想了解更多关于 DI 的信息,Alejandro Gervassio 在 本系列 文章中对其进行了广泛而专业的介绍,所以一定要去读这些文章。那么,什么又是 IoC 呢?IoC (控制反转)不需要使用依赖注入,但它可以帮助你有效的管理依赖关系。
控制反转
Ioc 是一个简单的组件,可以更加方便地解析依赖项。你可以将对象形容为容器,并且每次解析类时,都会自动注入依赖项。
Laravel Ioc
当你请求一个对象时, Laravel Ioc 在解决依赖关系的方式上有些特殊:
我们使用一个简单的例子,将在本文中改进它。SimpleAuth
类依赖于 FileSessionStorage
,所以我们的代码可能是这样的:
class FileSessionStorage{ public function __construct(){ session_start(); } public function get( $key ){ return $_SESSION[$key]; } public function set( $key, $value ){ $_SESSION[$key] = $value; } } class SimpleAuth{ protected $session; public function __construct(){ $this->session = new FileSessionStorage; } } //创建一个 SimpleAuth $auth = new SimpleAuth();
这是一种经典的方法,让我们从使用构造函数注入开始。
class SimpleAuth{ protected $session; public function __construct( FileSessionStorage $session ){ $this->session = $session; } }
现在我们创建一个对象:
$auth = new SimpleAuth( new FileSessionStorage() );
现在我想使用 Laravel Ioc 来管理这一切。
因为 Application
类继承自 Container
类,所以你可以通过 App
门面来访问容器。
App::bind( 'FileSessionStorage', function(){ return new FileSessionStorage; });
bind
方法第一个参数是要绑定到容器的唯一 ID ,第二个参数是一个回调函数每当执行 FileSessionStorage
类时执行,我们还可以传递一个表示类名的字符串,如下所示。
Note: 如果你查看 Laravel 包时,你将看到绑定有时会分组,比如( view
, view.finder
……)。
假设我们将会话存储转换为 Mysql 存储,我们的类应该类似于:
class MysqlSessionStorage{ public function __construct(){ //... } public function get($key){ // do something } public function set( $key, $value ){ // do something } }
现在我们已经更改了依赖项,我们还需要更改 SimpleAuth
构造函数,并将新对象绑定到容器中!
高级模块不应该依赖于低级模块,两者都应该依赖于抽象对象。
抽象不应该依赖于细节,细节应该取决于抽象。Robert C. Martin
我们的 SimpleAuth
类不应该关心我们的存储是如何完成的,相反它更应该关注于消费的服务。
因此,我们可以抽象实现我们的存储:
interface SessionStorage{ public function get( $key ); public function set( $key, $value ); }
这样我们就可以实现并请求 SessionStorage
接口的实例:
class FileSessionStorage implements SessionStorage{ public function __construct(){ //... } public function get( $key ){ //... } public function set( $key, $value ){ //... } } class MysqlSessionStorage implements SessionStorage{ public function __construct(){ //... } public function get( $key ){ //... } public function set( $key, $value ){ //... } } class SimpleAuth{ protected $session; public function __construct( SessionStorage $session ){ $this->session = $session; } }
如果我们使用 App::make('SimpleAuth')
通过容器解析 SimpleAuth
类,容器将会抛出 BindingResolutionException
,尝试从绑定解析类之后,返回到反射方法并解析所有依赖项。
Uncaught exception 'Illuminate\Container\BindingResolutionException' with message 'Target [SessionStorage] is not instantiable.'
容器正试图将接口实例化。我们可以为该接口做一个具体的绑定。
App:bind( 'SessionStorage', 'MysqlSessionStorage' );
现在每次我们尝试从容器解析该接口时,我们会得到一个 MysqlSessionStorage
实例。如果我们想要切换我们的存储服务,我们只要变更一下这个绑定。
Note: 如果你想要查看一个类是否已经在容器中被绑定,你可以使用 App::bound('ClassName')
,或者可以使用 App::bindIf('ClassName')
来注册一个还未被注册过的绑定。
Laravel Ioc 也提供 App::singleton('ClassName', 'resolver')
来处理单例的绑定。
你也可以使用 App::instance('ClassName', 'instance')
来创建单例的绑定。
如果容器不能解析依赖项就会抛出 ReflectionException
,但是我们可以使用 App::resolvingAny(Closure)
方法以回调函数的形式来解析任何指定的类型。
Note: 如果你为某个类型已经注册了一个解析方式 resolvingAny
方法仍然会被调用,但它会直接返回 bind
方法的返回值。
小贴士
这些绑定写在哪儿:如果只是一个小型应用你可以写在一个全局的起始文件 global/start.php
中,但如果项目变得越来越庞大就有必要使用 Service Provider 。
测试:
当需要快速简易的测试可以考虑使用php artisan tinker
,它十分强大,且能帮你提升你的 Laravel 测试流程。Reflection API:
PHP 的 Reflection API 是非常强大的,如果你想要深入 Laravel Ioc 你需要熟悉 Reflection API ,可以先看下这个 教程 来获得更多的信息。【相关推荐:PHP视频教程】Atas ialah kandungan terperinci Laravel中的依赖注入和IoC的详细介绍(附示例). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Bertindak balas, vue, andangularcanbeintegratedwithlaravelbyfollowingspecificsetupsteps.1) forreact: installreactusinglaravelui, setupcomponentsinapp.js.2)

TaskManagementToolSareessfectiveFectiveremoteprojectmanagementbyprioritizingTasksandTrackingProgress.1) usetoolsliketrelloandasanatosetprioritieswithlabelsortags.2) prokertoolslikejiraandmondy.com

Laravel101hancesperformanceRoughseralkeyfeatures.1) itIntroduceSquerybuilderCachingtoreDuceeduceedataBaseload.2) itOpTimizeSeSeloquentModeLeloadingWithLazyLoadingProxies.3)

Strategi penggunaan aplikasi Laravel yang terbaik termasuk: 1. 1. Zero Downtime Deployment menggunakan Envoy atau Deployer untuk mengautomasikan proses penempatan untuk memastikan aplikasi tetap tersedia apabila dikemas kini. 2. Penyebaran biru dan hijau membolehkan penempatan downtime dengan mengekalkan dua persekitaran dan membolehkan pengembalian cepat. 3. Penggunaan berterusan mengautomasikan keseluruhan proses penempatan melalui githubactions atau gitlabci/cd. 4. Canary melepaskan melalui konfigurasi Nginx, secara beransur -ansur mempromosikan versi baru kepada pengguna untuk memastikan pengoptimuman prestasi dan pengembalian cepat.

Toscalealaravelapplicationefectively, focusondatabasesharding, caching, loadbosting, andmicroservices.1) pelaksanaanDataBaseshardingTodistributedataacrossmultipledatabasesforimprovedperformance.2)

TooverComeComeCommunicationBarriersAndistributedTeams, Gunakan: 1) videocallsforface-to-faceinteraction, 2) setclearResponsetimeexpectations, 3) chooseapproprateCommunicationTools, 4) createeAteamCommunicationGuide, dan5)

Laravelbladeenhancesfrontendtemplatinginfull-stackprojectsbyofferingcleansyntaxandpowerfeatures.1) itallowsforeasyvariabledisplayandControlstructures.2)

Laravelisidealffull-stackapplicationsduetoitselegantsyntax, comprehensiveecosystem, andpowerfeatures.1) useeloquentormforintuitiveBackenddatamanipulation, butavoidn 1queryissues.2) prajuritas


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Muat turun versi mac editor Atom
Editor sumber terbuka yang paling popular

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SecLists
SecLists ialah rakan penguji keselamatan muktamad. Ia ialah koleksi pelbagai jenis senarai yang kerap digunakan semasa penilaian keselamatan, semuanya di satu tempat. SecLists membantu menjadikan ujian keselamatan lebih cekap dan produktif dengan menyediakan semua senarai yang mungkin diperlukan oleh penguji keselamatan dengan mudah. Jenis senarai termasuk nama pengguna, kata laluan, URL, muatan kabur, corak data sensitif, cangkerang web dan banyak lagi. Penguji hanya boleh menarik repositori ini ke mesin ujian baharu dan dia akan mempunyai akses kepada setiap jenis senarai yang dia perlukan.

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

mPDF
mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),
