PHP 프레임워크 Laravel Laravel 프레임워크에서 Contracts 계약 구문 분석

Laravel 프레임워크에서 Contracts 계약 구문 분석

Jan 31, 2020 pm 08:08 PM

Laravel 프레임워크에서 Contracts 계약 구문 분석

Contracts

Laravel의 계약은 사용자 가드 계약 IllumninateContractsAuthGuard 및 사용자 제공 계약과 같이 프레임워크에서 제공하는 핵심 서비스를 정의하는 인터페이스 세트입니다. 사용자 인증을 소개하는 장 장치 계약 IlluminateContractsAuthUserProvider 및 프레임워크와 함께 제공되는 AppUser 모델에 의해 구현됩니다. IlluminateContractsAuthAuthenticatable계약. IllumninateContractsAuthGuard 和用户提供器契约IlluminateContractsAuthUserProvider以及框架自带的AppUser模型所实现的IlluminateContractsAuthAuthenticatable契约。

为什么使用契约

通过上面几个契约的源码文件我们可以看到,Laravel提供的契约是为核心模块定义的一组interface。Laravel为每个契约都提供了相应的实现类,下表列出了Laravel为上面提到的三个契约提供的实现类。

Laravel 프레임워크에서 Contracts 계약 구문 분석

所以在自己开发的项目中,如果Laravel提供的用户认证系统无法满足需求,你可以根据需求定义看守器和用户提供器的实现类,比如我之前做的项目就是用户认证依赖于公司的员工管理系统的API,所以我就自己写了看守器和用户提供器契约的实现类,让Laravel通过自定义的Guard和UserProvider来完成用户认证。自定义用户认证的方法在介绍用户认证的章节中我们介绍过,读者可以去翻阅那块的文章。

所以Laravel为所有的核心功能都定义契约接口的目的就是为了让开发者能够根据自己项目的需要自己定义实现类,而对于这些接口的消费者(比如:Controller、或者内核提供的 AuthManager这些)他们不需要关心接口提供的方法具体是怎么实现的, 只关心接口的方法能提供什么功能然后去使用这些功能就可以了,我们可以根据需求在必要的时候为接口更换实现类,而消费端不用进行任何改动。

定义和使用契约

上面我们提到的都是Laravel内核提供的契约, 在开发大型项目的时候我们也可以自己在项目中定义契约和实现类,你有可能会觉得自带的Controller、Model两层就已经足够你编写代码了,凭空多出来契约和实现类会让开发变得繁琐。我们先从一个简单的例子出发,考虑下面的代码有什么问题:

class OrderController extends Controller
{
    public function getUserOrders()
    {
        $orders= Order::where('user_id', '=', \Auth::user()->id)->get();
        return View::make('order.index', compact('orders'));
    }
}
로그인 후 복사

这段代码很简单,但我们要想测试这段代码的话就一定会和实际的数据库发生联系。

也就是说, ORM和这个控制器有着紧耦合。如果不使用Eloquent ORM,不连接到实际数据库,我们就没办法运行或者测试这段代码。这段代码同时也违背了“关注分离”这个软件设计原则。

简单讲:这个控制器知道的太多了。

控制器不需要去了解数据是从哪儿来的,只要知道如何访问就行。控制器也不需要知道这数据是从MySQL或哪儿来的,只需要知道这数据目前是可用的。

Separation Of Concerns 关注分离

Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

每个类都应该只有单一的职责,并且职责里所有的东西都应该由这个类封装

接下来我们定义一个接口,然后实现该接口

interface OrderRepositoryInterface 
{
    public function userOrders(User $user);
}
 
class OrderRepository implements OrderRepositoryInterface
{
    public function userOrders(User $user)
    {
        Order::where('user_id', '=', $user->id)->get();
    }
}
로그인 후 복사

将接口的实现绑定到Laravel的服务容器中

App::singleton('OrderRepositoryInterface', 'OrderRespository');
로그인 후 복사

然后我们将该接口的实现注入我们的控制器

class UserController extends Controller
{
    public function __construct(OrderRepositoryInterface $orderRepository)
    {
        $this->orders = $orderRespository;
    }
   
    public function getUserOrders()
    {
        $orders = $this->orders->userOrders();
        return View::make('order.index', compact('orders'));
    }
}
로그인 후 복사

现在我们的控制器就完全和数据层面无关了。在这里我们的数据可能来自MySQL,MongoDB或者Redis。我们的控制器不知道也不需要知道他们的区别。这样我们就可以独立于数据层来测试Web层了,将来切换存储实现也会很容易。

接口与团队开发

当你的团队在开发大型应用时,不同的部分有着不同的开发速度。

比如一个开发人员在开发数据层,另一个开发人员在做控制器层。

写控制器的开发者想测试他的控制器,不过数据层开发较慢没法同步测试。那如果两个开发者能先以interface的方式达成协议,后台开发的各种类都遵循这种协议。

一旦建立了约定,就算约定还没实现,开发者也可以为这接口写个“假”实现

class DummyOrderRepository implements OrderRepositoryInterface 
{
    public function userOrders(User $user)
    {
        return collect(['Order 1', 'Order 2', 'Order 3']);
    }
}
로그인 후 복사

一旦假实现写好了,就可以被绑定到IoC容器里

App::singleton('OrderRepositoryInterface', 'DummyOrderRepository');
로그인 후 복사

然后这个应用的视图就可以用假数据填充了。接下来一旦后台开发者写完了真正的实现代码,比如叫RedisOrderRepository

🎜계약을 사용하는 이유🎜🎜🎜위 계약의 소스 코드 파일을 통해 Laravel에서 제공하는 계약이 핵심 모듈에 대해 정의된 인터페이스 집합임을 알 수 있습니다. Laravel은 각 계약에 해당하는 구현 클래스를 제공합니다. 다음 표에는 위에서 언급한 세 가지 계약에 대해 Laravel이 제공하는 구현 클래스가 나열되어 있습니다. 🎜🎜Laravel 프레임워크에서 Contracts 계약 구문 분석 🎜🎜그래서 자체 개발한 프로젝트에서 Laravel에서 제공하는 사용자 인증 시스템이 요구 사항을 충족하지 못하는 경우 필요에 따라 가드 및 사용자 공급자의 구현 클래스를 정의할 수 있습니다. 인증은 회사의 직원 관리 시스템에 의존했기 때문에 Guard 및 User Provider Contract의 구현 클래스를 직접 작성하여 Laravel이 맞춤형 Guard 및 UserProvider를 통해 사용자 인증을 완료할 수 있도록 했습니다. 사용자 인증을 소개하는 장에서 사용자 인증을 사용자 정의하는 방법을 소개했습니다. 독자는 해당 기사를 읽을 수 있습니다. 🎜🎜그래서 Laravel이 모든 핵심 기능에 대한 계약 인터페이스를 정의하는 목적은 개발자가 자신의 프로젝트 요구 사항과 이러한 인터페이스(예: 커널에서 제공하는 Controller 또는 AuthManager)의 소비자에 따라 자체 구현 클래스를 정의할 수 있도록 하는 것입니다. ) 인터페이스에서 제공하는 메서드가 어떻게 구현되는지는 신경 쓸 필요가 없습니다. 인터페이스 메서드가 어떤 기능을 제공할 수 있는지만 신경 쓰고 필요한 경우 인터페이스의 구현 클래스를 변경할 수 있습니다. 필요하지만 소비자 측에서는 변경할 필요가 없습니다. 🎜🎜🎜계약 정의 및 사용🎜🎜🎜위에서 언급한 내용은 모두 Laravel 커널에서 제공하는 계약입니다. 대규모 프로젝트를 개발할 때 프로젝트에서 직접 계약 및 구현 클래스를 정의할 수도 있습니다. 컨트롤러와 모델의 두 계층만으로도 코드를 작성하기에 충분합니다. 추가 계약 및 구현 클래스를 추가하면 개발이 번거로워집니다. 간단한 예부터 시작하여 다음 코드에 어떤 문제가 있는지 생각해 보겠습니다. 🎜
public function testIndexActionBindsUsersFromRepository()
{    
    // Arrange...
    $repository = Mockery::mock('OrderRepositoryInterface');
    $repository->shouldReceive('userOrders')->once()->andReturn(['order1', 'order2]);
    App::instance('OrderRepositoryInterface', $repository);
    // Act...
    $response  = $this->action('GET', 'OrderController@getUserOrders');
         
    // Assert...
    $this->assertResponseOk();
    $this->assertViewHas('order', ['order1', 'order2']);
 }
로그인 후 복사
로그인 후 복사
🎜이 코드는 매우 간단하지만 이 코드를 테스트하려면 실제 데이터베이스와 접촉해야 합니다. 🎜🎜즉, ORM과 이 컨트롤러는 긴밀하게 결합되어 있습니다. Eloquent ORM을 사용하고 실제 데이터베이스에 연결하지 않고는 이 코드를 실행하거나 테스트할 방법이 없습니다. 이 코드는 또한 "관심사 분리"라는 소프트웨어 설계 원칙을 위반합니다. 🎜🎜간단히 말하면 이 컨트롤러는 너무 많은 것을 알고 있습니다. 🎜🎜컨트롤러는 데이터의 출처를 알 필요가 없으며 데이터에 액세스하는 방법만 알면 됩니다. 컨트롤러는 데이터가 MySQL에서 어디서 왔는지 알 필요가 없으며, 데이터가 현재 사용 가능하다는 것만 알면 됩니다. 🎜🎜🎜관심 사항 분리 🎜🎜
🎜모든 클래스에는 단일 책임이 있어야 하며 해당 책임은 클래스에 의해 완전히 캡슐화되어야 합니다.🎜
🎜모든 클래스에는 단일 책임만 있어야 하며 책임은 이 클래스에 의해 캡슐화되어야 합니다🎜🎜다음으로 인터페이스를 정의하고 인터페이스를 구현합니다🎜rrreee🎜인터페이스 구현을 라라벨의 서비스 컨테이너에 바인딩합니다🎜rrreee🎜그런 다음 인터페이스 구현을 주입합니다 우리의 컨트롤러🎜rrreee🎜이제 우리 컨트롤러는 데이터 레이어와 완전히 독립적입니다. 여기서 데이터는 MySQL, MongoDB 또는 Redis에서 가져올 수 있습니다. 우리 컨트롤러는 차이점을 모르고 알 필요도 없습니다. 이렇게 하면 데이터 계층과 독립적으로 웹 계층을 테스트할 수 있으며 향후 스토리지 구현을 쉽게 전환할 수 있습니다. 🎜🎜🎜인터페이스 및 팀 개발🎜🎜🎜팀이 대규모 애플리케이션을 개발할 때 부분마다 개발 속도가 다릅니다. 🎜🎜예를 들어 한 개발자는 데이터 레이어를 개발하고, 다른 개발자는 컨트롤러 레이어를 개발하고 있습니다. 🎜🎜컨트롤러를 작성한 개발자가 자신의 컨트롤러를 테스트하고 싶어하지만 데이터 레이어 개발이 느리고 동시에 테스트할 수 없습니다. 두 개발자가 먼저 인터페이스 형태로 합의하면 백그라운드에서 개발되는 모든 클래스는 이 합의를 따릅니다. 🎜🎜계약이 체결되면 계약이 아직 구현되지 않았더라도 개발자는 이 인터페이스에 대한 "가짜" 구현을 작성할 수 있습니다.🎜rrreee🎜가짜 구현이 작성되면 IoC 컨테이너에 바인딩될 수 있습니다🎜rrreee 🎜그러면 애플리케이션의 뷰가 가짜 데이터로 채워질 수 있습니다. 다음으로 백엔드 개발자가 실제 구현 코드 작성을 마치면 이를 RedisOrderRepository라고 합니다. 🎜

那么使用IoC容器切换接口实现,应用就可以轻易地切换到真正的实现上,整个应用就会使用从Redis读出来的数据了。

接口与测试

建立好接口约定后也更有利于我们在测试时进行Mock

public function testIndexActionBindsUsersFromRepository()
{    
    // Arrange...
    $repository = Mockery::mock('OrderRepositoryInterface');
    $repository->shouldReceive('userOrders')->once()->andReturn(['order1', 'order2]);
    App::instance('OrderRepositoryInterface', $repository);
    // Act...
    $response  = $this->action('GET', 'OrderController@getUserOrders');
         
    // Assert...
    $this->assertResponseOk();
    $this->assertViewHas('order', ['order1', 'order2']);
 }
로그인 후 복사
로그인 후 복사

总结

接口在程序设计阶段非常有用,在设计阶段与团队讨论完成功能需要制定哪些接口,然后设计出每个接口具体要实现的方法,方法的入参和返回值这些,每个人就可以按照接口的约定来开发自己的模块,遇到还没实现的接口完全可以先定义接口的假实现等到真正的实现开发完成后再进行切换,这样既降低了软件程序结构中上层对下层的耦合也能保证各部分的开发进度不会过度依赖其他部分的完成情况。

更多laravel框架相关技术文章,请访问laravel教程栏目!

위 내용은 Laravel 프레임워크에서 Contracts 계약 구문 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Laravel의 구성 요소를 사용하여 재사용 가능한 UI 요소를 만드는 방법은 무엇입니까? Laravel의 구성 요소를 사용하여 재사용 가능한 UI 요소를 만드는 방법은 무엇입니까? Mar 17, 2025 pm 02:47 PM

이 기사는 구성 요소를 사용하여 Laravel에서 재사용 가능한 UI 요소를 작성하고 사용자 정의하여 조직을위한 모범 사례를 제공하고 패키지 강화를 제안합니다.

클라우드 네이티브 환경에서 Laravel을 사용하기위한 모범 사례는 무엇입니까? 클라우드 네이티브 환경에서 Laravel을 사용하기위한 모범 사례는 무엇입니까? Mar 14, 2025 pm 01:44 PM

이 기사는 클라우드 네이티브 환경에서 Laravel을 배포하기위한 모범 사례에 대해 설명하고 확장 성, 신뢰성 및 보안에 중점을 둡니다. 주요 문제로는 컨테이너화, 마이크로 서비스, 무국적 설계 및 최적화 전략이 포함됩니다.

Laravel에서 Custom Blade Directives를 어떻게 작성하고 사용합니까? Laravel에서 Custom Blade Directives를 어떻게 작성하고 사용합니까? Mar 17, 2025 pm 02:50 PM

이 기사는 Laravel에서 사용자 정의 블레이드 지시문을 만들고 사용하여 템플릿을 향상시키는 것에 대해 설명합니다. 지침 정의, 템플릿에서이를 사용하고 대규모 프로젝트에서 관리하고 개선 된 코드 재사용 성 및 R과 같은 이점을 강조합니다.

Laravel에서 사용자 정의 검증 규칙을 어떻게 작성하고 사용하려면? Laravel에서 사용자 정의 검증 규칙을 어떻게 작성하고 사용하려면? Mar 17, 2025 pm 02:38 PM

이 기사에서는 Laravel에서 사용자 정의 검증 규칙을 작성하고 사용하여이를 정의하고 구현하는 단계를 제공합니다. 재사용 성과 특이성과 같은 이점을 강조하고 Laravel의 검증 시스템을 확장하는 방법을 제공합니다.

Laravel의 Artisan 콘솔을 사용하여 일반적인 작업을 자동화하려면 어떻게합니까? Laravel의 Artisan 콘솔을 사용하여 일반적인 작업을 자동화하려면 어떻게합니까? Mar 17, 2025 pm 02:39 PM

Laravel의 Artisan Console은 코드 생성, 마이그레이션 실행 및 스케줄링과 같은 작업을 자동화합니다. 주요 명령에는 Make : Controller, Migrate 및 DB : SEED가 포함됩니다. 특정 요구에 대해 사용자 정의 명령을 작성할 수 있으며 워크 플로 효율 향상.

Laravel의 라우팅 기능을 사용하여 SEO 친화적 인 URL을 만드는 방법은 무엇입니까? Laravel의 라우팅 기능을 사용하여 SEO 친화적 인 URL을 만드는 방법은 무엇입니까? Mar 17, 2025 pm 02:43 PM

이 기사는 Laravel의 라우팅을 사용하여 SEO 친화적 인 URL을 생성, 모범 사례, 표준 URL 및 SEO 최적화 도구를 다루는 것에 대해 설명합니다.

어느 것이 더 낫습니까, 장고 또는 라벨? 어느 것이 더 낫습니까, 장고 또는 라벨? Mar 28, 2025 am 10:41 AM

Django와 Laravel은 모두 풀 스택 프레임 워크입니다. Django는 Python 개발자 및 복잡한 비즈니스 논리에 적합한 반면 Laravel은 PHP 개발자 및 우아한 구문에 적합합니다. 1. Django는 파이썬을 기반으로하며 빠른 개발 및 높은 동시성에 적합한 "배터리 완성"철학을 따릅니다. 2. Laravel은 PHP를 기반으로하며 개발자 경험을 강조하며 중소형 프로젝트에 적합합니다.

Laravel은 다른 PHP 프레임 워크 (Symfony, Codeigniter, YII)와 어떻게 비교됩니까? Laravel은 다른 PHP 프레임 워크 (Symfony, Codeigniter, YII)와 어떻게 비교됩니까? Mar 14, 2025 pm 01:49 PM

우아한 구문으로 유명한 Laravel은 Symfony, Codeigniter 및 Yii와 비교됩니다. Eloquent ORM 및 Artisan CLI와 같은 부드러운 학습 곡선과 독특한 기능을 제공하여 사용 편의성을 강력한 기능과 균형을 유지합니다.

See all articles