laravelサービスコンテナとは何ですか
laravel では、サービス コンテナはクラスの依存関係を管理し、依存関係の注入を実装するための強力なツールです。アプリケーションが特定のサービスを使用する必要がある場合、サービス コンテナはサービスを解決し、サービス間の依存関係を自動的に解決して、それをアプリケーションに渡して使用します。
このチュートリアルの動作環境: Windows 7 システム、Laravel 6 バージョン、Dell G3 コンピューター。
サービスコンテナとは
Laravel サービスコンテナは、クラスの依存関係を管理し、依存関係の注入を実装するための強力なツールです。依存関係注入という用語は、表面的には派手に見えるかもしれませんが、本質的には、コンストラクター、場合によっては「セッター」メソッドを通じて、クラスの依存関係をクラスに「注入」することを意味します。
Laravel の Route、Eloquent ORM、Request、Response などの機能モジュールは、実際にはコアとは関係のないクラスモジュールによって提供されており、これらのクラスは登録からインスタンス化まで、最終的にはクラスモジュールとして提供されます。実際の使用はLaravelのサービスコンテナの責任です。
サービス コンテナには 2 つの概念があります 制御の反転 (IOC)
と 依存性注入 (DI)
:
##依存性の注入と制御の反転は、同じものを異なる視点から説明したものです。依存関係の注入はアプリケーションの観点から説明されており、アプリケーションはコンテナーに依存して、必要な外部リソースを作成して注入します。制御の反転をコンテナの観点から説明すると、コンテナはアプリケーションを制御し、コンテナはアプリケーションが必要とする外部リソースをアプリケーションに逆注入します。Laravel では、フレームワークがさまざまなサービスをサービス コンテナにバインドしますが、カスタム サービスをコンテナにバインドすることもできます。アプリケーションが特定のサービスを使用する必要がある場合、サービス コンテナはサービスを解決し、サービス間の依存関係を自動的に解決して、それをアプリケーションに渡して使用します。 サービスのバインディングと解析が Laravel でどのように実装されるかについて説明しましょう。
サービス バインディング
サービスをコンテナにバインドするために一般的に使用されるメソッドには、インスタンス、バインド、シングルトン、エイリアスなどがあります。個別に見てみましょう。インスタンス
既存のオブジェクトをサービス コンテナにバインドします。その後サービスが名前によって解決されると、コンテナは常にバインドされたインスタンスを返します。$api = new HelpSpot\API(new HttpClient); $this->app->instance('HelpSpot\Api', $api);
[ 'HelpSpot\Api' => $api//$api是API类的对象,这里简写了 ]
bind
$this->app->bind('HelpSpot\API', null);
$this->app->bind('HelpSpot\API', function () { return new HelpSpot\API(); });//闭包直接提供类实现方式 $this->app->bind('HelpSpot\API', function ($app) { return new HelpSpot\API($app->make('HttpClient')); });//闭包返回需要依赖注入的类
$this->app->bind('Illuminate\Tests\Container\IContainerContractStub', 'Illuminate\Tests\Container\ContainerImplementationStub');
public function bind($abstract, $concrete = null, $shared = false) { $abstract = $this->normalize($abstract); $concrete = $this->normalize($concrete); //如果$abstract为数组类似['Illuminate/ServiceName' => 'service_alias'] //抽取别名"service_alias"并且注册到$aliases[]中 //注意:数组绑定别名的方式在5.4中被移除,别名绑定请使用下面的alias方法 if (is_array($abstract)) { list($abstract, $alias) = $this->extractAlias($abstract); $this->alias($abstract, $alias); } $this->dropStaleInstances($abstract); if (is_null($concrete)) { $concrete = $abstract; } //如果只提供$abstract,则在这里为其生成concrete闭包 if (! $concrete instanceof Closure) { $concrete = $this->getClosure($abstract, $concrete); } $this->bindings[$abstract] = compact('concrete', 'shared'); if ($this->resolved($abstract)) { $this->rebound($abstract); } } protected function getClosure($abstract, $concrete) { // $c 就是$container,即服务容器,会在回调时传递给这个变量 return function ($c, $parameters = []) use ($abstract, $concrete) { $method = ($abstract == $concrete) ? 'build' : 'make'; return $c->$method($concrete, $parameters); }; }
$bindings = [ 'HelpSpot\API' => [//闭包绑定 'concrete' => function ($app, $paramters = []) { return $app->build('HelpSpot\API'); }, 'shared' => false//如果是singleton绑定,这个值为true ] 'Illuminate\Tests\Container\IContainerContractStub' => [//接口实现绑定 'concrete' => 'Illuminate\Tests\Container\ContainerImplementationStub', 'shared' => false ] ]
singleton
public function singleton($abstract, $concrete = null) { $this->bind($abstract, $concrete, true); }
alias
サービスとサービス エイリアスをコンテナに登録する:public function alias($abstract, $alias) { $this->aliases[$alias] = $this->normalize($abstract); }
$this->app->alias('\Illuminate\ServiceName', 'service_alias');
$this->app->make('service_alias');
サービス解析
make: サービス コンテナからサービス オブジェクトを解析します。このメソッドは、解析するクラス名またはインターフェイス名を受け取りますパラメータとして/** * Resolve the given type from the container. * * @param string $abstract * @param array $parameters * @return mixed */ public function make($abstract, array $parameters = []) { //getAlias方法会假定$abstract是绑定的别名,从$aliases找到映射的真实类型名 //如果没有映射则$abstract即为真实类型名,将$abstract原样返回 $abstract = $this->getAlias($this->normalize($abstract)); // 如果服务是通过instance()方式绑定的,就直接解析返回绑定的service if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } // 获取$abstract接口对应的$concrete(接口的实现) $concrete = $this->getConcrete($abstract); if ($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete, $parameters); } else { //如果时接口实现这种绑定方式,通过接口拿到实现后需要再make一次才能 //满足isBuildable的条件 ($abstract === $concrete) $object = $this->make($concrete, $parameters); } foreach ($this->getExtenders($abstract) as $extender) { $object = $extender($object, $this); } //如果服务是以singleton方式注册进来的则,把构建好的服务对象放到$instances里, //避免下次使用时重新构建 if ($this->isShared($abstract)) { $this->instances[$abstract] = $object; } $this->fireResolvingCallbacks($abstract, $object); $this->resolved[$abstract] = true; return $object; } protected function getConcrete($abstract) { if (! is_null($concrete = $this->getContextualConcrete($abstract))) { return $concrete; } // 如果是$abstract之前没有注册类实现到服务容器里,则服务容器会认为$abstract本身就是接口的类实现 if (! isset($this->bindings[$abstract])) { return $abstract; } return $this->bindings[$abstract]['concrete']; } protected function isBuildable($concrete, $abstract) { return $concrete === $abstract || $concrete instanceof Closure; }
public function build($concrete, array $parameters = []) { // 如果是闭包直接执行闭包并返回(对应闭包绑定) if ($concrete instanceof Closure) { return $concrete($this, $parameters); } // 使用反射ReflectionClass来对实现类进行反向工程 $reflector = new ReflectionClass($concrete); // 如果不能实例化,这应该是接口或抽象类,再或者就是构造函数是private的 if (! $reflector->isInstantiable()) { if (! empty($this->buildStack)) { $previous = implode(', ', $this->buildStack); $message = "Target [$concrete] is not instantiable while building [$previous]."; } else { $message = "Target [$concrete] is not instantiable."; } throw new BindingResolutionException($message); } $this->buildStack[] = $concrete; // 获取构造函数 $constructor = $reflector->getConstructor(); // 如果构造函数是空,说明没有任何依赖,直接new返回 if (is_null($constructor)) { array_pop($this->buildStack); return new $concrete; } // 获取构造函数的依赖(形参),返回一组ReflectionParameter对象组成的数组表示每一个参数 $dependencies = $constructor->getParameters(); $parameters = $this->keyParametersByArgument( $dependencies, $parameters ); // 构建构造函数需要的依赖 $instances = $this->getDependencies( $dependencies, $parameters ); array_pop($this->buildStack); return $reflector->newInstanceArgs($instances); } //获取依赖 protected function getDependencies(array $parameters, array $primitives = []) { $dependencies = []; foreach ($parameters as $parameter) { $dependency = $parameter->getClass(); // 某一依赖值在$primitives中(即build方法的$parameters参数)已提供 // $parameter->name返回参数名 if (array_key_exists($parameter->name, $primitives)) { $dependencies[] = $primitives[$parameter->name]; } elseif (is_null($dependency)) { // 参数的ReflectionClass为null,说明是基本类型,如'int','string' $dependencies[] = $this->resolveNonClass($parameter); } else { // 参数是一个类的对象, 则用resolveClass去把对象解析出来 $dependencies[] = $this->resolveClass($parameter); } } return $dependencies; } //解析出依赖类的对象 protected function resolveClass(ReflectionParameter $parameter) { try { // $parameter->getClass()->name返回的是类名(参数在typehint里声明的类型) // 然后递归继续make(在make时发现依赖类还有其他依赖,那么会继续make依赖的依赖 // 直到所有依赖都被解决了build才结束) return $this->make($parameter->getClass()->name); } catch (BindingResolutionException $e) { if ($parameter->isOptional()) { return $parameter->getDefaultValue(); } throw $e; } }
laravel ビデオチュートリアル]
以上がlaravelサービスコンテナとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Laravelの電子メールの送信が失敗したときに戻りコードを取得する方法。 Laravelを使用してアプリケーションを開発する場合、検証コードを送信する必要がある状況に遭遇することがよくあります。そして実際には...

LaravelスケジュールタスクRAN RANSPONSIVEトラブルシューティングRALAVELのスケジュールタスクスケジューリングを使用すると、多くの開発者がこの問題に遭遇します。スケジュール:実行...

Laravelの電子メールの検証コードの送信の障害を処理する方法は、Laravelを使用することです...

DCATを使用するときにDCATADMIN(Laravel-Admin)にデータを追加するためにカスタムクリックのテーブル関数を実装する方法...

Laravel FrameworkでRedis接続の共有の影響とLaravelフレームワークとRedisを使用する際のメソッドを選択すると、開発者は問題に遭遇する可能性があります。

Laravel Multi-Tenant拡張機能パッケージStancl/Tenancyのカスタムテナントデータベース接続Laravel Multi-Tenant ExtensionパッケージStancl/Tenancyを使用したマルチテナントアプリケーションを構築する際の...

LaravelEloquentモデルの検索:データベースデータを簡単に取得するEloquentormは、データベースを操作するための簡潔で理解しやすい方法を提供します。この記事では、さまざまな雄弁なモデル検索手法を詳細に紹介して、データベースからのデータを効率的に取得するのに役立ちます。 1.すべてのレコードを取得します。 ALL()メソッドを使用して、データベーステーブルですべてのレコードを取得します:useapp \ models \ post; $ post = post :: all();これにより、コレクションが返されます。 Foreach Loopまたはその他の収集方法を使用してデータにアクセスできます。

700万のレコードを効率的に処理し、地理空間技術を使用したインタラクティブマップを作成します。この記事では、LaravelとMySQLを使用して700万を超えるレコードを効率的に処理し、それらをインタラクティブなマップの視覚化に変換する方法について説明します。最初の課題プロジェクトの要件:MySQLデータベースに700万のレコードを使用して貴重な洞察を抽出します。多くの人は最初に言語をプログラミングすることを検討しますが、データベース自体を無視します。ニーズを満たすことができますか?データ移行または構造調整は必要ですか? MySQLはこのような大きなデータ負荷に耐えることができますか?予備分析:キーフィルターとプロパティを特定する必要があります。分析後、ソリューションに関連している属性はわずかであることがわかりました。フィルターの実現可能性を確認し、検索を最適化するためにいくつかの制限を設定しました。都市に基づくマップ検索
