로직을 추가 할 MVC (Laravel)


137

CRUD 작업을 수행하거나 특정 방식으로 관계를 수정할 때마다 다른 작업을 원한다고 가정 해 봅시다. 예를 들어 누군가가 게시물을 게시 할 때마다 분석을 위해 테이블에 무언가를 저장하려고합니다. 아마도 가장 좋은 예는 아니지만 일반적으로이 "그룹화 된"기능이 많이 있습니다.

일반적으로 이러한 유형의 논리가 컨트롤러에 적용됩니다. 이 기능을 많은 곳에서 재현하고 싶을 때까지는 괜찮습니다. 부분적으로 들어가고 API를 만들고 더미 컨텐츠를 생성하기 시작하면 DRY를 유지하는 데 문제가됩니다.

이를 관리하는 방법은 이벤트, 리포지토리, 라이브러리 및 모델에 추가하는 것입니다. 각각에 대한 나의 이해는 다음과 같습니다.

서비스 : 대부분의 사람들이이 코드를 넣을 수있는 곳입니다. 서비스의 주요 문제는 때로는 특정 기능을 찾기가 어려우며 사람들이 Eloquent를 사용하는 데 집중할 때 잊어 버린 것 같습니다. publishPost()내가 할 수있을 때 라이브러리에서 메소드를 호출해야한다는 것을 어떻게 알 수 $post->is_published = 1있습니까?

내가 잘 작동하는 유일한 조건은 서비스 만 사용하는 것입니다 (그리고 컨트롤러에서 모두 Eloquent에 액세스 할 수 없도록하는 것이 이상적입니다).

궁극적으로 요청이 일반적으로 모델 구조를 따르는 경우 불필요한 추가 파일을 많이 생성하는 것처럼 보입니다.

리포지토리 : 내가 이해 한 바에 따르면 이것은 기본적으로 서비스와 비슷하지만 인터페이스가 있으므로 ORM간에 전환 할 수 있습니다.

이벤트 : 모델 이벤트가 항상 Eloquent 메소드에서 호출되므로 일반적인 컨트롤러처럼 컨트롤러를 작성할 수 있기 때문에 이것이 가장 우아한 시스템이라고 생각합니다. 나는 이것들이 지저분 해지는 것을 볼 수 있으며 누군가 중요한 커플 링을위한 이벤트를 사용하는 대규모 프로젝트의 예를 가지고 있다면 그것을보고 싶습니다.

모델 : 전통적으로 CRUD를 수행하고 임계 커플 링을 처리하는 클래스가있었습니다. CRUD +와 관련된 모든 기능을 알고 있기 때문에 실제로는 쉽게 할 수 있습니다.

간단하지만 MVC 아키텍처에서는 일반적으로 내가 본 것이 아닙니다. 어떤 점에서는 찾기가 더 쉽고 추적 할 파일이 적기 때문에 서비스보다 이것을 선호합니다. 그래도 약간 혼란 스러울 수 있습니다. 이 방법에 대한 몰락과 대부분의 사람들이 왜 그렇게하지 않는지 듣고 싶습니다.

각 방법의 장단점은 무엇입니까? 뭔가 빠졌습니까?


3
질문을 최소화 할 수 있습니까?
알파

3
또한 이것을 확인할 수 있습니다 .
알파

1
"$ post-> is_published = 1을 수행 할 수있을 때 라이브러리에서 publishPost () 메소드를 호출해야한다는 것을 어떻게 알 수 있습니까?" 선적 서류 비치?
ceejayoz

웅변과 ORMS에 대한 아름다움 중 하나는 많은 문서없이 그들과 함께 작업하는 것이 더 쉽다는 것입니까?
Sabrina Leggett

1
이것을 게시 해 주셔서 감사합니다. 나는 같은 문제로 어려움을 겪고 있으며 귀하의 게시물과 답변이 엄청나게 도움이되었습니다. 궁극적으로 나는 Laravel이 루비 온 레일 웹 사이트를 넘어 더 빠르고 더러운 것에 대해 좋은 아키텍처를 제공하지 않기로 결정했습니다. 어디서나 클래스를 찾는 데 어려움을 겪고 있으며, 어디서나 수많은 자동 마술 쓰레기를 찾을 수 없습니다. ORM은 작동하지 않았으며 사용중인 경우 NoSQL을 사용해야합니다.
Alex Barker

답변:


171

SOLID 원칙 을 따르는 한 모든 패턴 / 아키텍처가 매우 유용하다고 생각합니다 .

논리를 추가위치에 대해서는 단일 책임 원칙 을 참조하는 것이 중요하다고 생각합니다 . 또한 제 대답은 당신이 중형 / 대형 프로젝트를 진행하고 있다고 생각합니다. 그것이 페이지에 던지기 프로젝트 인 경우,이 답변을 잊어 컨트롤러 나 모델에 모두 추가하십시오.

짧은 대답은 : 그것은 (서비스) 당신에게 의미가 어디 .

긴 대답 :

컨트롤러 : 컨트롤러 의 책임은 무엇입니까? 물론, 모든 논리를 컨트롤러에 넣을 수는 있지만 컨트롤러의 책임입니까? 나는 그렇게 생각하지 않습니다.

나에게 컨트롤러는 요청을 받고 데이터를 반환해야하며 이것은 유효성 검사를하거나 db 메소드를 호출하는 장소가 아닙니다.

모델 : 사용자가 게시물의 투표 수를 등록하거나 업데이트 할 때 환영 이메일을 보내는 것과 같은 논리를 추가하기에 좋은 장소입니까? 코드의 다른 곳에서 동일한 이메일을 보내야한다면 어떻게해야합니까? 정적 메소드를 작성합니까? 해당 이메일에 다른 모델의 정보가 필요한 경우 어떻게합니까?

모델이 엔티티를 나타내야한다고 생각합니다. Laravel으로, 나는 단지 같은 것들을 추가하는 모델 클래스를 사용 fillable, guarded, table(다른 모델도있을 것입니다, 나는 저장소 패턴을 사용하기 때문에이과의 관계를 save, update, find, 등의 방법).

리포지토리 (리포지토리 패턴) : 처음에 나는 이것으로 매우 혼란 스러웠습니다. 그리고 당신처럼, 저는 "저는 MySQL을 사용합니다."라고 생각했습니다.

그러나 리포지토리 패턴 사용의 장단점을 균형있게 조정했으며 이제는 사용합니다. 나는 지금 이 순간에 MySQL 만 사용하면 된다고 생각한다 . 그러나 3 년 후 MongoDB와 같은 것으로 변경해야 할 경우 대부분의 작업이 완료됩니다. 하나의 추가 인터페이스와 $app->bind(«interface», «repository»).

이벤트 ( 관찰자 패턴 ) : 이벤트는 주어진 시간에 어떤 클래스에서든 던질 수있는 것들에 유용합니다. 예를 들어, 사용자에게 알림을 보내는 것을 생각하십시오. 필요할 때 응용 프로그램의 모든 클래스에서 알림을 보내도록 이벤트를 시작합니다. 그런 다음 UserNotificationEvents사용자 알림을 위해 시작된 모든 이벤트를 처리 하는 클래스를 만들 수 있습니다 .

서비스 : 지금까지 컨트롤러 나 모델에 로직을 추가 할 수 있습니다. 나에게 서비스 내에 논리를 추가하는 것이 모든 의미가있다 . 서비스는 클래스의 멋진 이름입니다. 그리고 당신은 당신의 응용 프로그램 내에서 당신이 이해하는만큼 많은 수업을 가질 수 있습니다.

이 예를 보자. 얼마 전, 나는 구글 폼과 같은 것을 개발했다. 나는 시작 CustomFormService과 함께 결국 CustomFormService, CustomFormRender, CustomFieldService, CustomFieldRender, CustomAnswerServiceCustomAnswerRender. 왜? 이해가 되었기 때문입니다. 팀과 함께 작업하는 경우 팀에 적합한 위치에 논리를 배치해야합니다.

서비스 대 컨트롤러 / 모델 사용의 이점은 단일 컨트롤러 또는 단일 모델에 의해 제한을받지 않는다는 것입니다. 응용 프로그램의 디자인과 요구에 따라 필요한만큼의 서비스를 만들 수 있습니다. 응용 프로그램의 모든 클래스 내에서 서비스를 호출하면 이점이 있습니다.

이것은 오래 걸리지 만 응용 프로그램을 어떻게 구성했는지 보여 드리고자합니다.

app/
    controllers/
    MyCompany/
        Composers/
        Exceptions/
        Models/
        Observers/
        Sanitizers/
        ServiceProviders/
        Services/
        Validators/
    views
    (...)

특정 기능을 위해 각 폴더를 사용합니다. 예를 들어, Validators디렉토리에는 BaseValidator검증 프로세스를 담당 하는 클래스 가 포함되어 있습니다 .$rules$messages 특정 유효성 검사기 및 특정 유효성 검사기 (일반적으로 각 모델마다 하나씩)를 . 이 코드를 서비스에 쉽게 넣을 수는 있지만 서비스 내에서만 사용하더라도 지금은 특정 폴더를 갖는 것이 좋습니다.

다음 기사를 읽어보십시오. 내용이 조금 더 잘 설명 될 수 있습니다.

Dayle Rees (CodeBright의 저자)가 틀을 깨다

리포지토리 및 서비스를 사용하여 Laravel에서 코드 분리Chris Goosey의 를 :이 게시물에서는 서비스 및 리포지토리 패턴과 그 구성 방식을 잘 설명합니다.

라라 캐스트는 또한 리포지토리 단순화단일 책임 이 있으며 실제 사례를 통해 훌륭한 리소스를 제공합니다 (비용을 지불해야하더라도).


3
좋은 설명. 여기에 내가 현재 서있는 곳이 있습니다. 현재 프로젝트에서 비즈니스 논리를 모델로 만들고 실제로 실제로 잘 작동합니다. 우리는 SOLID를 조금만 퍼지해야하지만, 아직 문제가되지는 않았습니다. 빠르지 만 좀 더러워 지지만 지금까지는 너무 건조하기 때문에 프로젝트를 유지 보수 할 수 있습니다. 나는 그들이 일을 끝내기 때문에 지금 당장 고집하는 것에 대해 확실히 괜찮습니다. 그러나 미래의 프로젝트에서는 아마도 표준이 무엇이든 갈 것입니다. 이것은 리포지토리가 된 것처럼 들립니다.
Sabrina Leggett

2
당신에게 맞는 방법을 찾아서 다행입니다. 오늘 의 가정에주의하십시오 . 나는 3 년 이상 프로젝트를 수행했으며 5000 줄 이상의 코드로 컨트롤러와 모델로 끝났습니다. 프로젝트에 행운을 빕니다.
Luís Cruz

또한 좀 더러워 지지만 모델이 커지는 것을 피하기 위해 특성을 사용하는 것에 대해 생각하고있었습니다. 그렇게하면 조금 분리 할 수 ​​있습니다
Sabrina Leggett

이 기사는 서비스를 사용하는 것이 합리적 일 때 명확하게 설명합니다. Form 예제에서는 서비스를 사용하는 것이 합리적이지만, 서비스를 사용하는 방법을 설명합니다. 논리는 모델에 직접 연결되는 모델입니다. justinweiss.com/articles/where-do-you-put-your-code
Sabrina Leggett

나는 설명을 정말로 좋아한다. 내가 가지고있는 한 가지 질문이 있습니다. 컨트롤러에 유효성 검사를하지 말 것을 언급 했으므로 유효성 검사를 수행하는 가장 좋은 장소는 어디라고 생각합니까? 많은 사람들이 확장 요청 클래스 (및 현재 수행중인 작업)에 넣을 것을 제안하지만 http 요청뿐만 아니라 장인 명령 등을 확인하고 싶다면 실제로 좋은 장소는 무엇입니까?
kingshark

24

내 질문에 대한 답변을 게시하고 싶었습니다. 나는 이것에 대해 며칠 동안 이야기 할 수 있지만, 나는 그것을 빨리 올리기 위해 이것을 빨리 게시하려고 노력할 것입니다.

Laravel이 제공하는 기존 구조를 사용하여 결국 파일을 기본적으로 모델, 뷰 및 컨트롤러로 유지했습니다. 또한 실제로 모델링되지 않은 재사용 가능한 구성 요소에 대한 라이브러리 폴더도 있습니다.

서비스 / 라이브러리에서 모델을 래핑하지 않았습니다 . 제공된 모든 이유가 100 % 서비스 사용의 이점을 확신하지 못했습니다. 내가 틀릴 수도 있지만, 내가 볼 수있는 한, 모델로 작업 할 때 만들고 전환 해야하는 엄청난 양의 여분의 파일이 생성되고 웅변 사용의 이점을 실제로 줄입니다 (특히 모델 복구와 관련하여) 예를 들어 페이지 매김, 범위 등을 사용).

비즈니스 로직을 모델에 넣고 컨트롤러에서 직접 웅변 적으로 액세스합니다. 비즈니스 로직이 우회되지 않도록 여러 가지 접근 방식을 사용합니다.

  • 접근 자와 뮤 테이터 : 라 라벨에는 훌륭한 접근 자와 뮤 테이터가 있습니다. 게시물을 초안에서 게시로 옮길 때마다 작업을 수행하려면 setIsPublishedAttribute 함수를 작성하고 거기에 논리를 포함하여 이것을 호출 할 수 있습니다
  • 작성 / 업데이트 등 재정의 : 사용자 정의 기능을 포함하도록 모델에서 항상 Eloquent 메소드를 재정의 할 수 있습니다. 이렇게하면 모든 CRUD 작업에서 기능을 호출 할 수 있습니다. 편집 : 최신 Laravel 버전에서 create를 재정의하는 데 버그가 있다고 생각합니다 (따라서 부트에 등록 된 이벤트를 사용합니다)
  • 유효성 검사 : 유효성 검사를 같은 방식으로 연결합니다. 예를 들어 CRUD 함수를 재정 의하여 유효성 검사를 실행하고 필요한 경우 접근 자 / 돌연변이를 실행합니다. 자세한 내용은 Esensi 또는 dwightwatson / 유효성 확인을 참조하십시오.
  • 매직 메소드 : 모델의 __get 및 __set 메소드를 사용하여 적절한 경우 기능에 연결합니다.
  • Eloquent 확장 : 모든 업데이트 / 생성 작업을 수행하려는 경우 웅변을 확장 하여 여러 모델에 적용 할 수도 있습니다.
  • 사건 : 이것은 솔직한 것이며 일반적으로 이것을하기 위해 합의 된 장소입니다. 이벤트의 가장 큰 단점은 예외를 추적하기 어렵다는 것입니다 (Laravel의 새로운 이벤트 시스템에서는 새로운 경우가 아닐 수도 있습니다). 또한 전화를받을 때 대신에하는 일을 기준으로 내 이벤트를 그룹화하고 싶습니다. 예를 들어, 메일을 보내는 이벤트를 수신하는 MailSender 가입자가 있습니다.
  • 피벗 / BelongsToMany 이벤트 추가 : 내가 가장 오랫동안 고민 한 것 중 하나는 belongsToMany 관계의 수정에 동작을 추가하는 방법이었습니다. 예를 들어, 사용자가 그룹에 참여할 때마다 작업을 수행합니다. 나는 이것을 위해 커스텀 라이브러리를 다듬었다. 아직 게시하지 않았지만 기능적입니다! 곧 링크를 게시하려고합니다. 편집 나는 모든 피벗을 일반 모델로 만들고 결국 내 인생이 훨씬 쉬워졌습니다 ...

모델 사용에 대한 사람들의 우려를 해결 :

  • 조직 :. 모델에 더 많은 로직을 포함 시키면 더 길어질 수 있지만 일반적으로 모델의 75 %가 여전히 작습니다. 더 큰 것을 구성하기로 선택한 경우 특성을 사용하여 수행 할 수 있습니다 (예 : 필요에 따라 PostScopes, PostAccessors, PostValidation 등의 파일이 더 많은 모델의 폴더 만들기). 나는 이것이 특성이 반드시 필요한 것은 아니지만이 시스템은 문제없이 작동한다는 것을 알고 있습니다.

추가 참고 사항 : 서비스에 모델을 포장하는 것은 스위스 군용 칼을 가지고 많은 도구를 사용하고 기본적으로 똑같은 일을하는 다른 칼을 만드는 것과 같습니다. 예, 때로는 블레이드를 테이핑하거나 두 개의 블레이드를 함께 사용하고 싶을 수도 있지만 일반적으로 다른 방법이 있습니다.

서비스를 사용하는 경우 :이 기사는 서비스를 사용하는시기에 대한 훌륭한 예를 명확하게 설명합니다 ( 힌트 : 자주는 아님). 그는 기본적으로 객체가 수명주기의 이상한 부분에서 여러 모델이나 모델을 사용할 때 의미가 있다고 말합니다 . http://www.justinweiss.com/articles/where-do-you-put-your-code/


2
흥미롭고 유효한 생각. 그러나 궁금합니다. 비즈니스 로직이 Eloquent에 연결된 모델과 연결되어 있고 데이터베이스에 연결된 모델에 대해 어떻게 비즈니스 로직을 단위 테스트합니까?
JustAMartin

code.tutsplus.com/tutorials/… 또는 더 자세히 분석하고 싶은 경우와 같이 이벤트를 사용할 수 있습니다
Sabrina Leggett

1
@JustAMartin 단위 테스트에서 데이터베이스를 사용할 수 없다고 확신하십니까? 하지 않는 이유는 무엇입니까? 많은 사람들이 단위 테스트에서 데이터베이스를 사용하는 것이 좋다는 데 종종 동의합니다. (Martin Fowler, martinfowler.com/bliki/UnitTest.html 포함 : "나는 외부 자원에 대해 복식을 절대 규칙으로 사용하지 않습니다. 그것은 당신의 단위 테스트에서 ")
Alex P.

@ AlexP11223 그렇습니다. SQLite를 테스트 데이터베이스로 통합하려고 시도했지만 일반적으로 SQLite에는 Laravel 마이그레이션 및 사용자 정의 쿼리 (있는 경우)에서 고려해야 할 몇 가지 심각한 제한 사항이 있습니다. 물론, 그것들은 엄격하게 단위 테스트가 아니라 기능 테스트이지만, 훨씬 효율적입니다. 그럼에도 불구하고 모델을 완전 절연 (엄격한 단위 테스트)으로 테스트하려면 상당한 양의 추가 코드 (모의 등)가 필요할 수 있습니다.
JustAMartin

22

컨트롤러와 모델 간의 논리를 만드는 데 사용하는 것은 서비스 계층 을 만드는 것 입니다. 기본적으로 이것은 내 앱 내의 모든 작업에 대한 흐름입니다.

  1. 컨트롤러는 사용자의 요청 된 조치를 받고 매개 변수를 전송하고 모든 것을 서비스 클래스에 위임합니다.
  2. 서비스 클래스는 입력 유효성 검사, 이벤트 로깅, 데이터베이스 작업 등 작업과 관련된 모든 논리를 수행합니다.
  3. 모델은 필드 정보, 데이터 변환 및 속성 검증 정의를 보유합니다.

이것이 내가하는 방법입니다.

이것은 무언가를 만드는 컨트롤러의 방법입니다.

public function processCreateCongregation()
{
    // Get input data.
    $congregation                 = new Congregation;
    $congregation->name           = Input::get('name');
    $congregation->address        = Input::get('address');
    $congregation->pm_day_of_week = Input::get('pm_day_of_week');
    $pmHours                      = Input::get('pm_datetime_hours');
    $pmMinutes                    = Input::get('pm_datetime_minutes');
    $congregation->pm_datetime    = Carbon::createFromTime($pmHours, $pmMinutes, 0);

    // Delegates actual operation to service.
    try
    {
        CongregationService::createCongregation($congregation);
        $this->success(trans('messages.congregationCreated'));
        return Redirect::route('congregations.list');
    }
    catch (ValidationException $e)
    {
        // Catch validation errors thrown by service operation.
        return Redirect::route('congregations.create')
            ->withInput(Input::all())
            ->withErrors($e->getValidator());
    }
    catch (Exception $e)
    {
        // Catch any unexpected exception.
        return $this->unexpected($e);
    }
}

작업과 관련된 논리를 수행하는 서비스 클래스입니다.

public static function createCongregation(Congregation $congregation)
{
    // Log the operation.
    Log::info('Create congregation.', compact('congregation'));

    // Validate data.
    $validator = $congregation->getValidator();

    if ($validator->fails())
    {
        throw new ValidationException($validator);
    }

    // Save to the database.
    $congregation->created_by = Auth::user()->id;
    $congregation->updated_by = Auth::user()->id;

    $congregation->save();
}

그리고 이것은 내 모델입니다.

class Congregation extends Eloquent
{
    protected $table = 'congregations';

    public function getValidator()
    {
        $data = array(
            'name' => $this->name,
            'address' => $this->address,
            'pm_day_of_week' => $this->pm_day_of_week,
            'pm_datetime' => $this->pm_datetime,
        );

        $rules = array(
            'name' => ['required', 'unique:congregations'],
            'address' => ['required'],
            'pm_day_of_week' => ['required', 'integer', 'between:0,6'],
            'pm_datetime' => ['required', 'regex:/([01]?[0-9]|2[0-3]):[0-5]?[0-9]:[0-5][0-9]/'],
        );

        return Validator::make($data, $rules);
    }

    public function getDates()
    {
        return array_merge_recursive(parent::getDates(), array(
            'pm_datetime',
            'cbs_datetime',
        ));
    }
}

이 방법에 대한 자세한 내용은 Laravel 앱의 코드를 구성하는 데 사용합니다 : https://github.com/rmariuzzo/Pitimi


서비스가 내 게시물에서 라이브러리라고하는 것 같습니다. 여러 ORMS를 사용할 필요가 없다면 이것이 저장소보다 낫다고 생각하지만 문제는 전체 프로젝트를 마이그레이션해야한다는 것입니다 (이벤트와 관련이 없음). 그것은 단지 Model 구조를 미러링하기 때문에 결국 모든 여분의 파일을 얻었습니다. 왜 모델에 포함시키지 않습니까? 최소한 그 방법으로 여분의 파일이 없습니다.
Sabrina Leggett 2014 년

흥미로운 질문 @ @SabrinaGelbart, 모델이 데이터베이스 엔터티를 나타내도록하고 논리를 유지하지 않도록 배웠습니다. 이것이 바로 서비스라는 이름의 추가 파일을 만든 이유입니다. 모든 논리와 추가 작업을 수행합니다. 이전에 설명한 이벤트의 전체 의미가 무엇인지 확실하지 않지만 서비스를 사용하여 Laravel의 이벤트를 사용하여 시작 및 종료시 이벤트를 시작하는 모든 서비스 방법을 만들 수 있다고 생각 합니다. 이런 식으로 모든 이벤트를 로직에서 완전히 분리 할 수 ​​있습니다. 어떻게 생각해?
Rubens Mariuzzo

나는 모델에 대해서도 너무 배웠습니다 ... 이유에 대한 좋은 설명을 얻는 것이 좋을 것입니다 (종속성 문제 일 수 있음)?
Sabrina Leggett

나는이 접근법을 좋아한다! 나는 모델의 논리를 어떻게 다루어야하는지에 대한 아이디어를 얻기 위해 인터넷을 찾고 있었고 저장소를 살펴 보았지만 약간의 사용법으로는 너무 복잡하고 쓸모없는 것처럼 보였습니다. 서비스는 좋은 생각입니다. 내 질문은 응용 프로그램 폴더에 서비스 폴더를 만든 후 부트 스트랩 / start.php 또는 부팅을 위해 어디서나 포함해야합니까? 짤방 백업 봇 앱을 통해 자동으로 사용할 수 있습니까? CongregationService :: getCongregations ();를 사용할 수 있습니다. ??
Oguzhan

1
당신이하고있는 모든 것이 그렇다면 $congregation->save();리포지토리가 필요하지 않을 것입니다. 그러나 시간이 지남에 따라 데이터 액세스 요구가 증가하는 것을 볼 수 있습니다. 당신은에 대한 요구 사항을 가지고 시작할 수 있습니다 $congregation->destroyByUser()또는 $congregationUsers->findByName($arrayOfSelectedFields);등등. 데이터 액세스 요구에서 서비스를 분리하십시오. 나머지 응용 프로그램은 repos에서 반환 된 객체 / 배열로 작업하고 조작 / 서식 지정 등을 처리하십시오 ... repo가 ​​커질 것입니다 (그러나 다른 파일로 분할하면 궁극적으로 프로젝트의 복잡성이 어딘가에 있어야합니다).
prograhammer

12

제 생각에는 라 라벨에는 이미 비즈니스 로직을 저장하기위한 많은 옵션이 있습니다.

짧은 답변:

  • laravel의 Request객체를 사용 하여 입력을 자동으로 확인한 다음 요청의 데이터를 유지합니다 (모델 생성). 요청 에서 모든 사용자 입력을 직접 사용할 수 있으므로 여기서 수행하는 것이 좋습니다.
  • laravel의 Job객체를 사용하여 개별 구성 요소가 필요한 작업을 수행 한 다음 파견하십시오. 나는 Job서비스 클래스를 포괄 한다고 생각 합니다. 비즈니스 로직과 같은 작업을 수행합니다.

긴 답변 :

필요한 경우 리포지토리 사용 : 리포지토리가 과장되어 바인딩되는 경우가 많으며 대부분의 accessor경우 모델 로 사용됩니다 . 나는 그들이 확실히 사용하고 있다고 생각하지만 라 라벨을 완전히 버릴 수있는 유연성을 요구 하는 대규모 응용 프로그램을 개발하지 않는 한 저장소에서 멀리 떨어져 있어야합니다. 나중에 스스로에게 감사 할 것이며 코드는 훨씬 더 직설적입니다.

PHP 프레임 워크를 변경 하거나 laravel이 지원하지 않는 데이터베이스 유형 으로 변경 될 가능성이 있는지 자문하십시오.

당신의 대답이 "아마도 아닙니다"라면, 저장소 패턴을 구현하지 마십시오.

위 외에도 Eloquent와 같은 멋진 ORM 위에 패턴을 두드리지 마십시오. 필요하지 않은 복잡성을 추가하기 만하면 전혀 도움이되지 않습니다.

서비스를 조금만 활용 : 서비스 클래스는 비즈니스 로직을 저장하여 주어진 종속성으로 특정 작업을 수행 할 수있는 장소입니다. 라 라벨은이를 '작업'이라고 부르며, 맞춤형 서비스 클래스보다 훨씬 더 유연합니다.

라 라벨에는 MVC논리 문제에 대한 다방면의 솔루션이 있다고 생각 합니다. 문제 나 조직 일뿐입니다.

예:

요청 :

namespace App\Http\Requests;

use App\Post;
use App\Jobs\PostNotifier;
use App\Events\PostWasCreated;
use App\Http\Requests\Request;

class PostRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title'       => 'required',
            'description' => 'required'
        ];
    }

    /**
     * Save the post.
     *
     * @param Post $post
     *
     * @return bool
     */
    public function persist(Post $post)
    {
        if (!$post->exists) {
            // If the post doesn't exist, we'll assign the
            // post as created by the current user.
            $post->user_id = auth()->id();
        }

        $post->title = $this->title;
        $post->description = $this->description;

        // Perform other tasks, maybe fire an event, dispatch a job.

        if ($post->save()) {
            // Maybe we'll fire an event here that we can catch somewhere else that
            // needs to know when a post was created.
            event(new PostWasCreated($post));

            // Maybe we'll notify some users of the new post as well.
            dispatch(new PostNotifier($post));

            return true;
        }

        return false;
    }
}

컨트롤러 :

namespace App\Http\Controllers;

use App\Post;
use App\Http\Requests\PostRequest;

class PostController extends Controller
{

   /**
    * Creates a new post.
    *
    * @return string
    */
    public function store(PostRequest $request)
    {
        if ($request->persist(new Post())) {
            flash()->success('Successfully created new post!');
        } else {
            flash()->error('There was an issue creating a post. Please try again.');
        }

        return redirect()->back();
    }

   /**
    * Updates a post.
    *
    * @return string
    */
    public function update(PostRequest $request, $id)
    {
        $post = Post::findOrFail($id);

        if ($request->persist($post)) {
            flash()->success('Successfully updated post!');
        } else {
            flash()->error('There was an issue updating this post. Please try again.');
        }

        return redirect()->back();
    }
}

위의 예에서 요청 입력은 자동으로 확인되며, persist 메소드를 호출하고 새 Post를 전달하기 만하면됩니다. 가독성과 유지 관리 성은 항상 복잡하고 불필요한 디자인 패턴보다 우선해야한다고 생각합니다.

그런 다음 게시물이 존재하는지 여부를 확인하고 필요할 때 대체 논리를 수행 할 수 있으므로 게시물을 업데이트 할 때에도 동일한 지속 방법을 사용할 수 있습니다.


그러나-대기중인 작업이 "supposed"되지 않습니까? 때때로 우리는 항상 대기열에 넣고 싶지는 않을 것입니다. 대신 명령을 사용하지 않는 이유는 무엇입니까? 명령이나 이벤트 또는 대기열로 실행될 수있는 비즈니스 로직을 작성하려면 어떻게해야합니까?
Sabrina Leggett

1
작업을 대기열에 넣을 필요가 없습니다. ShouldQueueLaravel이 제공 하는 작업에서 인터페이스를 구현하여 지정 합니다. 명령이나 이벤트에 비즈니스 로직을 쓰려면 해당 이벤트 / 명령 내에서 작업을 시작하십시오. Laravels 작업은 매우 유연하지만 결국 일반 서비스 클래스 일뿐입니다.
Steve Bauman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.