MVC에서 모델에서 기본 데이터 검색을 View에서 수행 할 수 있습니까?


10

'스키니 컨트롤러, 뚱뚱한 모델' 의 개념 과 출력을 위해 데이터를 요구할 때 뷰가 모델을 직접 호출 할 수 있다는 일반적인 수용을 감안할 때 컨트롤러가 아닌 뷰 내에서 요청의 'get and display'부분을 처리해야합니까? 예를 들어 (코드를 상당히 일반적으로 유지하려고 시도했습니다) :

제어 장치

<?php

class Invoice extends Base_Controller {

    /**
     * Get all the invoices for this month
     */

    public function current_month() {

        // as there's no user input let's keep the controller very skinny,
        // DON'T get data from the Model here, just load the view

        $this->load->view('invoice/current_month');

    }

}

전망

<?php

// directly retrieve current month invoices here

$invoices = $this->invoice_model->get_current_month();

// get some other display-only data, e.g. a list of users for a separate list somewhere on the page

$users = $this->user_model->get_users();

?>

<h1>This month's invoices</h1>

<ul>
<?php foreach ($invoices as $invoice) { ?>

<li><?php echo $invoice['ref']; ?></li>

<?php } ?>
</ul>

나에게 이것은 요청이 본질적으로 단지보기 인 경우 적어도 의미가 있습니다. 컨트롤러가 데이터를 검색 할 수있을 때 데이터를 수집하여 뷰에 전달해야하는 이유는 무엇입니까? 이를 통해 컨트롤러는 순전히 '애플리케이션 레벨'처리 (예 : GET / POST 요청 처리, 액세스 권한 및 권한 관리 등)를 위해 모델을 재사용 할 수있을뿐 아니라 모델을 재사용 가능하고 다른 모든 좋은 것들로 유지할 수 있습니다.

이 예제가 사용자가 결과를 필터링 할 수 있도록 확장 된 경우 Controller는 양식에서 POST를 처리하고 필터를보기로 전달한 다음 이번에는 필터와 함께 데이터를 다시 요청합니다.

이것이 MVC 응용 프로그램 개발에 유효한 방법입니까? 아니면 컨트롤러의 역할에서 중요한 부분을 간과하고 있습니까?

답변:


17

예, 기술적으로 가능합니다. 아니요, 수행하면 안됩니다. 그리고 네, 컨트롤러가 무엇인지 약간 누락되었습니다.

컨트롤러는 모델에서 뷰를 분리합니다. 디커플링은 뷰를 거의 버리기 코드로보아야하기 때문에 유리합니다. UI 기술이 변경되면 새보기를 생성하는 데 필요한 재 작업을 최소화하려고합니다. 컨트롤러는 이러한 분리를 가능하게하고 UI 기술을 통해 작동하는 코드를위한 장소를 제공합니다.

모델에 추가하거나 모델을 변경해야하는 경우에는 반대로 작동합니다. 모든 업스트림 변경 사항이 컨트롤러에 포함되며 조회수는 그대로 유지됩니다.

다른 위험은 지금 보기가 매우 단순 하지만 수명 기간 동안 그렇게 단순하게 유지 될 것이라는 보장이 적다는 것입니다. (매우 간단한) 뷰에서 모델을 직접 호출하면 문이 약간 열리므로 나중에 매우 간단한 뷰가 그리 간단하지 않아야 할 때 추가적인 잘못된 연습이 발생할 수 있습니다. 미래의 개발자는 코드를 리팩터링하고 컨트롤러와 상호 작용하는 대신 간단하지 않은 View에서 더 많은 모델 호출을 원할 것입니다.


1
좋은 답변, 감사합니다. '미래 예측'시나리오를 약간 확장; 요청한 내용과 다른 페이지에 공통 정보가있는 경우 (예 : 사용자가 특정 제품을보고있는 경우 '최신 특별 제안'의 일반 목록이 측면에 표시되어 있음) 어떻게 / 어떻게 전화를해야 offers_model->get_latest()합니까? 이것을 어리석게 시도했던 것처럼 컨트롤러의 모든 메소드에 이것을 추가하는 것은 과잉이고 분명히 건조하지 않은 것처럼 보입니다.
Adam Westbrook

2
@AdamWestbrook MVVM을 살펴보십시오. 이것의 ViewModel 부분은이 특정 문제를 해결할 수 있습니다. 당신은 추가 할 수 있습니다 offers_model->get_latest()A를 ProductViewModel기본 클래스 또는 이와 유사한.
Zachary Yates

1
다시 한 번 감사드립니다.
Adam Westbrook

아주 좋은 대답은이 별표를 거꾸로 보여줄 것입니다. 개인적으로 나는 또한 MVVM의 큰 팬입니다 :)
Benjamin Gruenbaum

@BenjaminGruenbaum PHP에서 MVVM을 사용하고 있습니까? 그렇다면 특정 프레임 워크를 사용하고 있습니까?
Adam Westbrook 2013

6

'스키니 컨트롤러, 뚱뚱한 모델'의 개념과 출력을 위해 데이터를 요구할 때 뷰가 모델을 직접 호출 할 수 있다는 일반적 수용

아니요. 정확하지 않습니다. 뷰는 모델을 직접 호출 할 수 없습니다. 어떤 이유로 든 프로그래머가 해당 객체를 뷰에 노출시키지 않는 한 뷰는 Model 객체에 액세스 할 수 없습니다.

컨트롤러가 아닌 뷰 내에서 요청의 'get and display'부분을 처리하는 것을 고려해야합니까?

기본적으로 컨트롤러가 지워지고 컨트롤러를 사용하는 시점이 무너집니다.

컨트롤러가 데이터를 검색 할 수있을 때 데이터를 수집하여 뷰에 전달해야하는 이유는 무엇입니까?

컨트롤러는 데이터를 수집하지 않습니다. 모델은 데이터 수집을 수행합니다. 컨트롤러 이 데이터가보기로 전달되어야하는지 결정 합니다. 뷰는 단지 데이터의 표현을 수행합니다.

이 예제가 사용자가 결과를 필터링 할 수 있도록 확장 된 경우 Controller는 양식에서 POST를 처리하고 필터를보기로 전달한 다음 이번에는 필터와 함께 데이터를 다시 요청합니다.

아니.

컨트롤러는 POST 된 데이터가 유효한지 확인한 다음이 데이터를 옵션으로 모델에 전달한 다음 데이터 소스를 쿼리하고 데이터를 반환하며 컨트롤러는 해당 데이터를 View에 전달합니다.

이것이 MVC 응용 프로그램 개발에 유효한 방법입니까? 아니면 컨트롤러의 역할에서 중요한 부분을 간과하고 있습니까?

컨트롤러는 브라우저의 요청에 대한 처리기로 작동합니다. 디스패처는 요청을 컨트롤러의 동작으로 보내고, 요청은 모델로 요청을 분산시킵니다. 모델은 모든 비즈니스 로직 (이 부분은 핵심 부분)을 포함하고 데이터를 컨트롤러에 다시 제공합니다. 그러면 컨트롤러는 데이터를 단순화하고 조정하여 View에서보다 쉽게 ​​데이터를 표시 할 수 있습니다.

뷰의 요점은 HTML과 데이터 소스의 표현 간의 구조와 종속성을 분리하는 것입니다. 이것은 어려울 수 있지만. 뷰가 항상 모델에서 직접 가져온 데이터를 나타내는 것은 아닙니다. 컨트롤러는 종종 관련있는 추가 데이터를 추가합니다.

MVC에 대한 자습서가 많이 있다고 확신합니다. 나는 그들 중 일부를 읽는 것이 좋습니다.


감사합니다 매튜. 명확히하기 위해 지금까지는 항상 View와 Model을 Controller와 분리하여 읽거나 제안했습니다. 그러나 '스키니'컨트롤러를 유지하는 것에 대해 읽기 시작한 이래로 나는 무엇을 제거 해야하는지 궁금해했습니다.이 질문으로 이끄는 사고 과정은 한두 단계 너무 먼 것 같습니다!
Adam Westbrook

많은 컨트롤러에서 사용하는 모델을 가져 오기 시작하면 그들이 뚱뚱해질 필요는 매우 분명해집니다. View에 많은 PHP가 포함되기 시작하면 컨트롤러가 얇다는 것을 알 수 있습니다. 컨트롤러가 매우 뚱뚱 할 때. 다른 컨트롤러가 동일한 방식으로 작동하는 것은 어렵습니다 (예 : API 서비스 추가).
Reactgular

3

최근 Python을 배우면서 같은 문제가 발생했기 때문에 귀하의 질문이 매우 흥미 롭습니다.

주어진 대답이 설득력있는 주장을하는 동안 View가 Controller를 거치지 않고 모델의 상태를 얻는다는 또 다른 의견을 추가 할 것이라고 생각했습니다.

MVC

뷰와 컨트롤러는 모두 모델에 따라 다릅니다. 그러나 모델은 뷰나 컨트롤러에 의존하지 않습니다. 이것이 분리의 주요 이점 중 하나입니다. 이러한 분리를 통해 시각적 프리젠 테이션과 상관없이 모델을 빌드하고 테스트 할 수 있습니다. 많은 리치 클라이언트 응용 프로그램에서 뷰와 컨트롤러의 분리는 부차적이며 실제로 많은 사용자 인터페이스 프레임 워크가 역할을 하나의 개체로 구현합니다. 반면에 웹 응용 프로그램에서는보기 (브라우저)와 컨트롤러 (HTTP 요청을 처리하는 서버 측 구성 요소) 간의 구분이 매우 잘 정의되어 있습니다.

Model-View-Controller는 사용자 인터페이스 로직과 비즈니스 로직을 분리하기위한 기본 디자인 패턴입니다. 불행히도, 패턴의 인기로 인해 많은 설명이 잘못되었습니다. 특히, "컨트롤러"라는 용어는 다른 상황에서 다른 것을 의미하는 데 사용되었습니다. 다행히도 웹 응용 프로그램의 출현은 뷰와 컨트롤러 사이의 분리가 분명하기 때문에 일부 모호성을 해결하는 데 도움이되었습니다.

Smalltalk-80의 응용 프로그래밍 : MVC (Model-View-Controller) 사용 방법 [Burbeck92]에서 Steve Burbeck은 MVC의 두 가지 변형 인 수동 모델과 활성 모델을 설명합니다.

수동 모델은 한 컨트롤러가 모델을 독점적으로 조작 할 때 사용됩니다. 컨트롤러는 모델을 수정 한 다음 모델이 변경되었으며 새로 고쳐야한다는 것을 뷰에 알립니다 (그림 2 참조). 이 시나리오의 모델은 뷰 및 컨트롤러와 완전히 독립적이므로 모델의 상태 변화를보고 할 수있는 방법이 없습니다. HTTP 프로토콜이 그 예입니다. 브라우저에서 서버에서 비동기 업데이트를 얻는 간단한 방법은 없습니다. 브라우저는보기를 표시하고 사용자 입력에 응답하지만 서버의 데이터 변경 사항을 감지하지 않습니다. 사용자가 명시 적으로 새로 고침을 요청한 경우에만 서버가 변경을 요청합니다.

MVC-패시브 모델

나는 어떤 의견이 "옳은지"라고 말할 수있는 입장에 있지 않으며, 솔직히 말해서, 여기의 답변과 링크 된 기사를 읽은 후에 조금 더 혼란스러워합니다.

기사의 전문은 여기에 있습니다 .


그리고 혼란을 더하는 또 다른 것은 원래 SmallTalk MVC가 실제로 설명하지 않은 클라이언트-서버입니다. 클라이언트 서버 (예 : 자바 스크립트)에는 클라이언트에 프리젠 테이션 지향 모델,보기 및 컨트롤러가 있으며 서버에는 도메인 지향보기 및 컨트롤러가 있지만 서버는 혼동을 추가하여 프리젠 테이션 지향 처리를 수행합니다. 또한 도메인 뷰에 지속성을 갖기를 원할 수도 있는데, 이는 뷰 매개 변수가 자체 모델을 형성한다는 것을 의미하며, 반드시 도메인 모델의 일부는 아닙니다.
Erik Eidt

링크 주셔서 감사합니다, 나는 이것을 생각하는 것에 화 내지 않았다는 것을 알고 있었다! 이것은 모델이 어떻게 / 어디서 액세스되는지에 관한 것이 무엇인지에 의존하지 않는 한, 아이디어를 너무 멀리 가져 오기 전에 필연적으로 나갔던 것입니다. 다음 개발에 어떤 접근 방식을 적용할지 결정하지 않았지만 이는 확실히 도움이됩니다.
Adam Westbrook

1

고려해야 할 또 다른 점은 당신이를 자동으로 적재 한 것으로 나타날 것입니다 user_modelinvoice_model액세스 그들에게보기를 허용 할 수 있습니다. 이것이 안정적으로 작동하려면 아마도 모든 모델을 자동로드 할 것입니다 ( $this->load->model()보기에서 잘못 보였기 때문에 그렇지 않습니다 ...)

이 작업을 수행하면 결코 사용되지 않을 수있는 많은 항목을로드하여 스택을 부 풀릴 수 있습니다. 여러 모델을 사용하는 이유 중 하나는 관련 논리를 캡슐화하고 주어진 작업에 필요한 것만로드 할 수 있기 때문입니다.

이것은 CodeIgniter처럼 보입니다. 나는 많은 CI 개발을 해왔으며 실제로는 필요 이상으로 자동로드를 원하지 않는 개인적인 경험을 공유 할 수 있습니다. $this->output->enable_profiler(TRUE);컨트롤러의 생성자를 추가 하고 자동로드 (예 database: 와 같은 도우미 포함)로 바이올린을 추가 하십시오.로드 및 실행 시간이 크게 변경되지만 특히 메모리 할당이 변경 될 수 있습니다 .


1
좋은 점은 CI를 기반으로하는 것이 맞습니다. 그러나 명확성을 위해 특정 구문을 제거했습니다. 나는 대부분의 시간과 DRY 이유로 거의 모든 것을 '자동 로딩'하는 습관을 겪었 load->model으며 대부분의 컨트롤러와 메소드에서 거의 같은 것을 가지고있는 것처럼 보였습니다 . 적절한 자동로드 기능을 사용하지 않는 것은 CI의 이전 버전과의 호환성에 대해 내가 가장 싫어하는 것 중 하나입니다. 그러나 그것은 완전히 다른 논의입니다 ...
Adam Westbrook

0

짧은 대답은 코드 샘플의 형식이 믿을 수 없을 정도로 직관적이라는 것입니다. 이것이 "마음에 편한"방법 인 것 같습니다.


문제 # 1

당신 ModelView사물이 단단히 결합됩니다.

에서 메소드 를 추가 하거나 제거Model 해야하는 경우 View그에 따라 메소드 를 변경해야 할 수도 있습니다 .

기본적으로 MVC는 명령관찰자 패턴 에서 파생됩니다 . 인터페이스 / API 를 통해 조작 할 수있는 독립적 인 '모델'을 원합니다 (즉 위임).Controller

종종, 이것은에 인스턴스를 주입 Model 하여 상기의 속성으로서 저장하는 것을 의미한다 . 이어서, 방법하여 작업 영역으로서 (즉, 명령), (A)에 데이터를 전달 로부터 ( 이후 '모델 최종 갱신 프로그램 상태를 갖는다 ).ViewControllerControllerController View Model

데이터 (배열, 반복 가능한 객체 등)를 전달하면 인스턴스 와 인스턴스 간의 연결느슨하게 유지 됩니다. 에 인스턴스를 주입하는 경우 위의 문제 # 1을 참조하십시오.ModelViewModelView

기억 ViewsHTML, JSON, 텍스트, XML, HTTP 헤더, YAML, 또는 표현 상태 전송 방법 (REST) 다음과 같은 거의 모든 될 수 있습니다 .

따라서, 사이의 관계를 관리하는 방법을 이해하는 열쇠 Model와는 Views그것이 무엇인지에 대한 관계를 참조하는 것입니다 일대을 (잠재적으로)! 이것이 바로 Observer 패턴이 달성하도록 설계된 것입니다.

대부분의 설정에는 한 번에 하나의 뷰만 관련되어 있지만 MVC 아키텍처 패턴이 한 번에 여러 뷰를 업데이트하는 것을 막는 것은 없습니다! 기존의 CRUD 웹 응용 프로그램을 사용하면 사람들 이 일대일 방식으로 생각 하지만 관찰자 패턴이 작동하는 방식의 가장 작은 예입니다 ( 일대 다가 다른 것 ).

하나가 있다면 따라서, Model여러 Views잠재적 두통 모든 업데이트 Views'당신이 뭔가를 변경하기 때문에 구현 코드를 Model'sAPI / 방법이 지금됩니다 급성 .

데이터를 전달 Views , 아니 인스턴스 Models .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.