Facade는 실제로 컨테이너에 있는 클래스의 정적 프록시입니다. 이를 통해 컨테이너에 저장된 모든 객체의 모든 메서드를 정적으로 호출할 수 있습니다. 다음 글에서는 주로 Laravel의 Facade 로딩 프로세스와 원리를 소개합니다. 관련정보를 참고할 수 있습니다.
머리말
이 글은 주로 라라벨의 Facade 로딩 프로세스와 원리에 대한 관련 내용을 소개하고 참고 및 학습을 위해 공유합니다. 아래에서는 자세히 설명하지 않겠습니다. 자세한 소개.
Introduction
Facades(발음: /fəˈsäd/)는 애플리케이션의 서비스 컨테이너에서 사용할 수 있는 클래스에 대한 "정적" 인터페이스를 제공합니다. 개체의 특정 메서드에 액세스하기 위해 여러 개의 네임스페이스를 사용하거나 개체를 인스턴스화할 필요가 없습니다.
use Config; class Test { public function index() { return Config::get('app.name'); } }
Facade 시작 및 등록
Facade 시작 부팅은 IlluminateFoundationBootstrapRegisterFacades에 등록됩니다.
public function bootstrap(Application $app) { Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); }
기본 별칭 구성은 앱 구성 파일 아래의 별칭에서 읽혀집니다. PackageManifest는 laravel 5.5의 새로운 패키지 자동 검색 규칙입니다. 여기서는 당분간 PackageManifest 패키지에서 제공하는 별칭을 고려하지 않습니다. .
그 중 array_merge는 다음 형식으로 배열을 반환합니다.
"App" => "Illuminate\Support\Facades\App" "Artisan" => "Illuminate\Support\Facades\Artisan" "Auth" => "Illuminate\Support\Facades\Auth" "Blade" => "Illuminate\Support\Facades\Blade" ...
위 코드는 AliasLoader를 통해 자동 로딩되도록 모든 Facade를 등록합니다. 핵심은 PHP의 spl_autoload_register입니다.
/** * Prepend the load method to the auto-loader stack. * * @return void */ protected function register() { if (! $this->registered) { spl_autoload_register([$this, 'load'], true, true); $this->registered = true; } }
등록이 완료되면 이후 사용 클래스는 모두 로드 기능을 통해 자동으로 로드됩니다.
참고: 여기에서 spl_autoload_register를 정의하면 마지막 매개변수가 true로 전달됩니다. 이 매개변수가 true이면 spl_autoload_register()는 대기열의 꼬리 대신 대기열의 머리에 함수를 추가합니다. (이 기능을 통해 먼저 자동 로딩이 완료됩니다.)
즉,
<?php use Config; use App\User; class Test { public function index() { Config::get('app.name'); new User(); } }
무엇을 사용하든 기존의 특정 클래스(AppUser) 또는 별칭(Config)을 사용하여 먼저 완료됩니다. 로드 기능 자동 로딩, 이 함수가 false를 반환하면 다른 자동 로딩 기능이 자동 로딩을 완료합니다(예: 작곡가 psr-4).
AliasLoader의 로드 메서드에서 class_alias 함수는 주로 별칭 자동 로드를 구현하는 데 사용됩니다.
public function load($alias) { if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } }
class_alias에 대한 공식 예는 다음과 같습니다.
class foo { } class_alias('foo', 'bar'); $a = new foo; $b = new bar; // the objects are the same var_dump($a == $b, $a === $b); //true var_dump($a instanceof $b); //false // the classes are the same var_dump($a instanceof foo); //true var_dump($a instanceof bar); //true var_dump($b instanceof foo); //true var_dump($b instanceof bar); //true
Facade loading
다음과 같이 Facade를 사용할 때:
실제로 로드된 것은 IlluminateSupportFacadesConfig 클래스(class_alias를 등록했기 때문에)는 다음과 동일합니다:<?php use Config; class Test { public function index() { Config::get('app.name'); } }그리고 모든 Facade는 IlluminateSupportFacadesFacade 클래스에서 상속되며 __callStatic 메소드는 이 기본 클래스에 정의됩니다. 이는 Facade를 인스턴스화 없이 쉽게 사용할 수 있습니다. ).
<?php use Illuminate\Support\Facades\Config; class Test { public function index() { Config::get('app.name'); } }getFacadeRoot 메소드는 별칭 클래스의 특정 인스턴스 열을 얻는 데 사용됩니다. 우리는 모든 Facade 클래스가 getFacadeAccessor 메소드를 정의해야 한다는 것을 알고 있습니다. 이 메서드의 가능한 반환 값은 다음과 같습니다.
문자열 유형 문자열(예: config, db)
문자열 유형 문자열 유사(예: AppServiceSomeService)
객체 특정 구체화된 객체
Closure closure
예를 들어 Config Facade의 getFacadeAccessor 메소드는 다음과 같습니다:
<?php public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); }getFacadeRoot 메소드는
getFacadeAccessor()의 반환 값을 기반으로 컨테이너에서 해당 실제 열 개체를 검색합니다.
. protected static function getFacadeAccessor() { return 'config'; }
getFacadeAccessor()
的返回值,从容器从取出对应的实列对象。
public static function getFacadeRoot() { $name = static::getFacadeAccessor(); if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app[$name]; }
由于 APP 容器中已经注册过 config 的实列
<?php //Illuminate\Foundation\Bootstrap/LoadConfiguration $app->instance('config', $config = new Repository($items));
所以 Config::get('app.name', 'dafault)
实际访问的是 Repository 实列的 get('app.name', 'default')
config 인스턴스가 APP 컨테이너
Config::get('app.name', 'dafault)
는 실제로 Repository에 액세스합니다. 실제 열의 get('app.name', 'default')
메서드. 🎜위 내용은 Laravel의 Facade 로딩 프로세스 및 원리 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!