>  기사  >  PHP 프레임워크  >  Laravel은 왜 Facade를 사용합니까?

Laravel은 왜 Facade를 사용합니까?

WBOY
WBOY원래의
2022-06-06 16:02:102091검색

Laravel에서는 전통적인 정적 메서드와 비교하여 파사드가 애플리케이션의 서비스 컨테이너에 "정적" 인터페이스를 제공할 수 있기 때문에 파사드에서 제공하는 "정적" 인터페이스는 서비스 컨테이너의 기본 클래스에 있는 정적 표현과 동일합니다. , 더 유연하고 테스트하기 쉬운 구문을 제공할 수 있으므로 laravel에서는 Facade를 사용하세요.

Laravel은 왜 Facade를 사용합니까?

이 기사의 운영 환경: Windows 10 시스템, Laravel 버전 6, Dell G3 컴퓨터.

laravel이 파사드를 사용하는 이유는 무엇인가요?

Laravel의 파사드는 일반적으로 파사드 패턴의 기본 아이디어를 따릅니다. Laravel의 파사드는 애플리케이션의 서비스 컨테이너에 대한 [정적] 인터페이스를 제공합니다. 이는 서비스 컨테이너의 기본 클래스에 있는 [정적 표현]과 동일하며, 보다 유연하고, 테스트하기 쉽고, 우아한 구문을 제공할 수 있습니다.

라라벨의 파사드에는 캐싱 등 자주 사용하게 될 것입니다.

Cache::get('key');

또 다른 예는 이전에 자주 사용했던 데이터베이스와 Redis입니다.

DB::connection('mysql2')->table('db_test')->get()->toArray();
 
Redis::connection('default')->client()->get('test')

아니요, 퍼사드는 모두 정적 메소드입니다. 하지만 클릭해 보면 이 파사드 카테고리에는 아무것도 없다는 것을 알 수 있습니다!

class Cache extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'cache';
    }
}

Facade 클래스에서는 지금은 다른 메소드 함수를 볼 필요가 없습니다. 아래로 스크롤하면 __callStatic()이라는 매직 메소드를 찾을 수 있습니다.

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);
}

__callStatic()은 정적으로 호출할 때 정의된 해당 메서드가 없으면 __callStatic() 메서드를 입력한다는 의미입니다. 예를 들어 우리가 호출하는 Cache::get() 메서드는 실제로 현재 Cache 파사드 클래스입니다. 해당 상위 클래스 Facade나 해당 상위 클래스는 이 메서드를 정의하므로 __callStatic()으로 직접 이동합니다. 그런 다음 getFacadeRoot()를 통해 현재 Facade의 인스턴스 객체를 가져온 다음 인스턴스 객체에서 get() 메서드를 호출합니다.

그렇습니다. 실제로 면접관이 인터뷰 중에 Laravel에서 Facade 모드를 구현하는 방법을 묻는다면 핵심은 __callStatic() 매직 메소드라고 자신있게 말할 수 있습니다. 그렇다면 이 특정 인스턴스 개체는 어디서 오는 걸까요? 계속해서 아래를 살펴보겠습니다.

Instance object

다음으로 Facade에서 특정 인스턴스 객체를 얻는 방법을 살펴보겠습니다. 여기서는 서비스 컨테이너로 돌아가야 합니다. 하지만 먼저 입구부터 살펴보겠습니다.

__callStatic() 메서드에서 특정 인스턴스 객체를 얻기 위해 static::getFacadeRoot() 메서드가 호출되는 것을 볼 수 있습니다.

public static function getFacadeRoot()
{
    return static::resolveFacadeInstance(static::getFacadeAccessor());
}

이 메소드의 내용은 매우 간단합니다. 다른 두 메소드만 호출합니다. getFacadeAccessor()는 각 Facade 하위 클래스에서 구현됩니다. 예를 들어, Cache 클래스에서 구현됩니다. 단지 인스턴스의 별칭을 반환합니다. 이 별칭이 정의된 위치를 기억하시나요? 우리는 이를 공급업체/laravel/framework/src/Illuminate/Foundation/Application.php의 RegisterCoreContainerAliases() 메소드에 정의된 서비스 컨테이너에서 확인했습니다.

다음으로 주로 살펴볼 것은 static::resolveFacadeInstance() 메서드입니다. 이름에서 파사드 인스턴스를 해결한다는 뜻임을 알 수 있습니다. 이 항목이 인스턴스 개체를 반환하지 않으면 이름에 걸맞는 것입니다.

protected static function resolveFacadeInstance($name)
{
    if (is_object($name)) {
        return $name;
    }
 
    if (isset(static::$resolvedInstance[$name])) {
        return static::$resolvedInstance[$name];
    }
 
    if (static::$app) {
        return static::$resolvedInstance[$name] = static::$app[$name];
    }
}

첫 번째 판단은 객체가 전달되면 직접 반환된다는 것입니다. 두 번째 판단은 현재 인스턴스 배열에 이미 하나가 있으면 다시 생성되지 않는다는 것이며 이는 플라이웨이트 모드의 효과와 유사합니다. 참고로 정적 멤버 배열입니다! 그것은 무엇을 의미합니까? 정적 및 전역적으로 공유됩니다. 즉, 인스턴스 객체가 생성된 후에는 완전한 싱글톤 상태로 다른 곳에서 사용할 수 있습니다. 마지막 판단은 앱, 즉 우리의 서비스 컨테이너가 존재한다면 서비스 컨테이너의 작업을 수행하는 것입니다.

먼저 앱 속성에 값이 할당되는 경우를 살펴보겠습니다. 서비스 제공자에 관해 이야기할 때 커널에는 RegisterFacades 제공자가 있는 부트스트래퍼 속성 배열이 있습니다. 당연히 Facade를 등록하는 데 사용되는 서비스 공급자입니다. 이 서비스 공급자에서는 다음과 같은 코드를 볼 수 있습니다.

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();
}

그 중 Facade::setFacadeApplication()은 서비스 컨테이너의 Application 객체를 Facade 클래스의 정적 멤버 변수 app에 주입합니다. 또한 정적이며 전역적으로 존재합니다.

그런 다음 계속해서 verifyFacadeInstance() 메서드로 돌아갑니다.

protected static function resolveFacadeInstance($name)
{
    // …………
    // …………
    if (static::$app) {
        return static::$resolvedInstance[$name] = static::$app[$name];
    }
}

무슨 일인가요? static::$app[$name]을 통해 인스턴스 개체를 어떻게 얻을 수 있나요? 흥분하지 말고, 걱정하지 마세요. 객체가 이러한 배열 작업을 수행하도록 만드는 방법에 대해 생각해 보세요. 우리는 전에 그것을 배웠습니다!

이것은 ArrayAccess 인터페이스이며, 구현해야 하는 몇 가지 메소드를 통해 객체를 배열처럼 사용할 수 있습니다.

자, 이제 원리를 알았으니 이것이 사실인지 알아보고 Application Vendor/laravel/framework/src/Illuminate/Container/Container.php 의 상위 클래스를 찾아보겠습니다.

class Container implements ArrayAccess, ContainerContract
{
    // …………
    // …………
    public function offsetGet($key)
    {
        return $this->make($key);
    }
    // …………
    // …………
}

베이맥스 같지 않나요? 더 이상 설명할 필요 없겠죠? make() 메소드는 이전 서비스 컨테이너에서 설명했습니다.

좋아요, 나머지는 여러분에게 달려 있습니다. Vendor/laravel/framework/src/Illuminate/Foundation/Application.php에 있는 RegisterCoreContainerAliases() 메서드의 별칭을 기반으로 캐시의 특정 구현 클래스를 찾은 다음 그 가져오기를 분석하세요. (), set(), Forget() 및 기타 메소드를 사용하여 구성 파일에 따라 다양한 캐시 저장 솔루션을 사용하는 방법을 확인합니다.

【관련 추천: laravel 비디오 튜토리얼

위 내용은 Laravel은 왜 Facade를 사용합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.