MVC'de, Modelden temel veri alımı Görünümde yapılabilir mi?


10

'Sıska kontrolörler, yağ modelleri' kavramı ve Görünümlerin çıktı için veri gerektiğinde Modelleri doğrudan çağırabileceği genel kabulü göz önüne alındığında, taleplerin Kontroller yerine Görünümler içindeki 'alma ve görüntüleme' bölümlerini ele alması düşünülmeli mi? Örneğin (kodu oldukça genel tutmaya çalıştı):

kontrolör

<?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');

    }

}

Görünüm

<?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>

Bana göre, bu, bir talebin sadece bir Görüş olduğu durumlarda en azından bir anlam ifade eder. Denetleyici neden sadece kendisini alabildiği zaman verileri toplamalı ve Görünüm'e aktarmalıdır? Bu, Denetleyiciyi tamamen 'Uygulama seviyesi' işleme (örneğin GET / POST isteklerini işleme, erişim haklarını ve izinlerini yönetme vb.) Ve Modellerin tekrar kullanılabilir olmasını ve diğer tüm iyi şeyleri açık tutmaya açık bırakır.

Bu örnek, kullanıcının sonuçları filtrelemesine izin vermek için genişletildiyse, Denetleyici POST'u formdan işleyecek ve filtreleri Görünüm'e geçirecek ve daha sonra verileri bu kez filtrelerle tekrar isteyecektir.

Bu bir MVC uygulaması geliştirmek için geçerli bir yaklaşım mı? Yoksa Denetleyicinin oynaması gereken rolün önemli bir bölümünü mi görüyorum?

Yanıtlar:


17

Evet, teknik olarak yapılabilir. Hayır, yapılmamalı. Ve evet, denetleyicinin orada ne için biraz eksik.

Denetleyici, Görünümü Modelden ayırmak için oradadır. Ayrıştırma faydalıdır, çünkü View'a neredeyse atma kodu olarak bakmalısınız. Kullanıcı arayüzü teknolojiniz değiştikçe, yeni bir Görünüm oluşturmak için gereken yeniden çalışmayı en aza indirmek istersiniz. Denetleyici bu ayrıştırmayı sağlar ve kodunuz için UI teknolojileri aracılığıyla yaşayacak bir yer sağlar.

Modelinize eklemeniz veya Modelinizi değiştirmeniz gerekirse ters yönde de çalışır. Tüm yukarı akış değişiklikleri Denetleyici içinde yer alacak ve Görünümleriniz tek başına bırakılacaktır.

Diğer risk Görünümü çok basit iken olmasıdır şimdi , bunu ömrü boyunca bu kadar basit kalacağını az garantisine sahiptir. Modeli doğrudan (çok basit) Görünümden çağırarak, çok basit Görünümün çok basit olmaması gerektiğinde daha sonra kötü uygulamaların sürünmesine izin vermek için kapıyı biraz açtınız. Gelecekteki bir geliştirici, kodu yeniden düzenlemek ve bir Denetleyici ile etkileşim kurmak yerine çok basit olmayan Görünüm'den daha fazla Model çağrısı yapmaya cazip gelecektir.


1
Harika cevap, teşekkür ederim. 'Geleceğe bakış' senaryonuzu biraz genişletmek; bir sayfada talep edilenlerden ayrı olarak ortak bilgiler varsa (örneğin, kullanıcı belirli bir ürünü görüntülüyorsa, 'en son özel teklifler' genel bir listesi yanda gösterilir) çağrı nasıl / nerede yapılmalıdır offers_model->get_latest()? Bunu kontrolördeki her yönteme eklemek (daha önce aptalca denediğim gibi) aşırı doldurma ve belirgin olarak KURU gibi görünmüyor.
Adam Westbrook

2
@AdamWestbrook MVVM'ye bir göz atın. Bunun ViewModel kısmı bu özel sorunu çözebilir. offers_model->get_latest()Bir ProductViewModeltemel sınıfa veya benzer bir şeye ekleyebilirsiniz .
Zachary Yates

1
Harika, kesinlikle MVVM'ye bakacağım, tekrar teşekkürler.
Adam Westbrook

Çok iyi bir cevap, meydan okurcasına bunu yıldızlı tutacak. Şahsen ben de MVVM büyük bir hayranıyım :)
Benjamin Gruenbaum

@BenjaminGruenbaum PHP'de MVVM mi kullanıyorsunuz? Varsa, bunun için belirli bir çerçeve mi kullanıyorsunuz?
Adam Westbrook

6

'Sıska kontrolörler, yağ modelleri' kavramı ve Views'ın çıktı için veri gerektiğinde doğrudan Modelleri çağırabileceği genel kabulü göz önüne alındığında

Hayır. Bu doğru değil. Görünüm Modellere doğrudan çağrı yapamaz. Herhangi bir nedenle programcı bu nesneleri Görünüme maruz bırakmadıkça, görünümlerin Model nesnelerine erişimi olmamalıdır.

taleplerin Kontroller yerine Görünümler içinde 'al ve görüntüle' bölümlerini ele almalı mı?

Bu temel olarak Kontrol Cihazı siler ve sahip olma noktasını yener.

Denetleyici neden sadece kendisini alabildiği zaman verileri toplamalı ve Görünüm'e aktarmalıdır?

Denetleyici veri toplamıyor. Model verilerin toplanmasını yapar. Kontrolör , bu verinin görünüme geçirilip geçirilmeyeceğine karar verir . Görünüm yalnızca verilerin sunumunu yapar.

Bu örnek, kullanıcının sonuçları filtrelemesine izin vermek için genişletildiyse, Denetleyici POST'u formdan işleyecek ve filtreleri Görünüm'e geçirecek ve daha sonra verileri bu kez filtrelerle tekrar isteyecektir.

Hayır.

Denetleyici, POSTed verilerinin geçerli olup olmadığını kontrol eder, daha sonra bu verileri Model'e seçenekler olarak iletir, bu da veri kaynağını sorgulayıp verileri döndürür ve Denetleyici bunu Görünüm'e iletir.

Bu bir MVC uygulaması geliştirmek için geçerli bir yaklaşım mı? Yoksa Denetleyicinin oynaması gereken rolün önemli bir bölümünü mi görüyorum?

Denetleyici, tarayıcıdan gelen isteklere bir işleyici olarak çalışır. Bir dağıtım programı, isteği bir denetleyicinin eylemine gönderir ve bu da isteği Modellere yayar. Modeller tüm iş mantığını içerir (bu yağ kısmıdır) ve verileri kontrolöre geri verir. Ardından denetleyici, Görünümü daha kolay sunabilmesi için verileri basitleştirebilir ve ayarlayabilir.

Görünümün amacı HTML'nin sunumu ile DataSource arasındaki yapı ve bağımlılığı ayırmaktır. Bu zor olsa da. Görünümler her zaman doğrudan bir Modelden gelen verileri sunmaz. Denetleyici genellikle ilgili ek veriler ekler.

MVC üzerinde orada bir sürü öğreticiler olduğundan eminim. Bazılarını okumanızı tavsiye ederim.


Teşekkürler Mathew. Açıklığa kavuşturmak için, şimdiye kadar Görünüm ve Modeli her zaman Denetleyici ile okundu ve önerildiği gibi ayırdım. Bununla birlikte, 'sıska' Kontrolörleri tutmaya okumaya başladığımdan beri, neyin ondan çıkarılması / taşınması gerektiğini merak ediyordum, beni bu soruya yönlendiren düşünce süreci bir iki adımdı!
Adam Westbrook

Modelleri birçok denetleyici tarafından kullanmaya başladığınızda. Şişman olma ihtiyacı çok netleşiyor. Görünüm çok fazla PHP içermeye başladığında, denetleyicinizin inceleceğini bilirsiniz. Kontrol cihazlarınız çok şişman olduğunda. Diğer denetleyicilerin aynı şekilde çalışmasını sağlamak zordur (örneğin, bir API hizmeti eklemek).
Reactgular

3

Sorunuzu çok ilginç buldum çünkü son zamanlarda Python'u öğrenirken aynı sorunla karşılaştım.

Verilen cevaplar ikna edici bir argüman oluştururken, View'un Kontrolörden geçmeden Model'in durumunu aldığı bir görüş daha ekleyeceğimi düşündüm.

MVC

Hem görünümün hem de denetleyicinin modele bağlı olduğunu unutmamak önemlidir. Ancak, model ne görünüme ne de denetleyiciye bağlıdır. Bu, ayrımın en önemli faydalarından biridir. Bu ayırma, modelin görsel sunumdan bağımsız olarak oluşturulmasına ve test edilmesine olanak tanır. Görünüm ve denetleyici arasındaki ayrım birçok zengin istemci uygulamasında ikincildir ve aslında birçok kullanıcı arabirimi çerçevesi rolleri tek bir nesne olarak uygular. Web uygulamalarında ise görünüm (tarayıcı) ve denetleyici (HTTP isteğini işleyen sunucu tarafı bileşenler) arasındaki ayrım çok iyi tanımlanmıştır.

Model-View-Controller, kullanıcı arayüzü mantığının iş mantığından ayrılması için temel bir tasarım modelidir. Ne yazık ki, kalıbın popülaritesi bir takım hatalı açıklamalarla sonuçlanmıştır. Özellikle, "kontrolör" terimi, farklı bağlamlarda farklı şeyleri ifade etmek için kullanılmıştır. Neyse ki, Web uygulamalarının ortaya çıkışı, görünüm ve denetleyici arasındaki ayrımın çok açık olması nedeniyle bazı belirsizliğin giderilmesine yardımcı oldu.

Smalltalk-80'de Uygulama Programlama: Model-View-Controller (MVC) [Burbeck92] nasıl kullanılır? Steve Burbeck, MVC'nin iki varyasyonunu açıklar: pasif bir model ve aktif bir model.

Pasif model, bir kontrolör sadece modeli manipüle ettiğinde kullanılır. Kontrolör modeli değiştirir ve daha sonra görünümü modelin değiştiğini ve yenilenmesi gerektiğini bildirir (bkz. Şekil 2). Bu senaryodaki model, görünümden ve denetleyiciden tamamen bağımsızdır, yani modelin durumundaki değişiklikleri rapor etmesinin bir yolu yoktur. HTTP protokolü buna bir örnektir. Tarayıcıda sunucudan eşzamansız güncellemeler almanın basit bir yolu yoktur. Tarayıcı görünümü görüntüler ve kullanıcı girişine yanıt verir, ancak sunucudaki verilerdeki değişiklikleri algılamaz. Yalnızca kullanıcı açıkça bir yenileme istediğinde, sunucu değişiklikler için sorgulanır.

MVC - Pasif Model

Hangi görüşlerin "doğru" olduğunu söyleyecek bir konumda değilim ve dürüst olmak gerekirse, buradaki yanıtları ve bağlantılı makaleyi okuduktan sonra biraz daha kafam karıştı.

Makalenin tam metni burada .


Doğru ve karışıklık ekleyen diğer şey, orijinal SmallTalk MVC'nin gerçekten hesaba katmadığı istemci sunucusudur. İstemci-sunucuda (örneğin, javascript ile), istemcide sunum odaklı modeller, görünümler ve denetleyiciler ve sunucu üzerinde etki alanı odaklı görünümler ve denetleyiciler vardır, ancak sunucu aynı zamanda bazı karışıklık ekleyerek sunum odaklı işlem yapar. Ayrıca, bazen bir alan adı görünümünün kalıcılığı olmasını isteriz, yani görünüm parametreleri kendi modelini oluşturur, yani alan modelinin bir parçası değildir.
Erik Eidt

Bağlantı için teşekkürler, bunu düşünmek için deli olmadığımı biliyordum! Modelin hiçbir şeye bağımlı olmadığı sürece, fikri biraz fazla ileri götürmeden önce bu benim gittiğim şeydi. Bir sonraki gelişime nasıl bir yaklaşım getireceğime henüz karar vermedim, ama bu kesinlikle yardımcı oluyor.
Adam Westbrook

1

Dikkate alınması gereken başka bir şey, otomatik olarak yüklediğiniz user_modelve invoice_modelgörünümün bunlara erişmesine izin verdiğinizdir. Bunun güvenilir bir şekilde çalışması için, muhtemelen tüm modellerinizi otomatik olarak yüklersiniz (çünkü $this->load->model()bir görünümde yanlış görünüyor, değil mi ...)

Bunu yapmak gereksiz yere asla kullanılmayacak bir sürü şey yükleyerek yığınınızı şişirir. Birden fazla modele sahip olmanın nedeninin bir kısmı, ilgili mantığı kapsüllemenize ve yalnızca belirli bir görev için ihtiyacınız olanı yüklemenize izin vermektir.

Bu CodeIgniter gibi görünüyor. Çok fazla CI geliştirme yaptım ve gerçekten deneyimlemekten daha fazlasını otomatik olarak yüklemek istemediğiniz kişisel deneyimlerinizi paylaşabilirim. $this->output->enable_profiler(TRUE);Bir denetleyicinin yapıcısını eklemeyi deneyin ve otomatik databaseyüklerle uğraşın (yardımcılar gibi ): büyük olasılıkla yük ve yürütme sürelerinde, ancak özellikle bellek ayırmada önemli bir değişiklik göreceksiniz .


1
İyi puanlar, haklısın, bu CI'ye dayanıyor, ancak netlik için bazı sözdizimini kaldırdım. Ben büyük ölçüde zaman ve KURU nedenlerle hemen hemen her şeyi 'otomatik yükleme' alışkanlığı edindim load->model, çoğu kontrolör ve yöntem aynı şey çok var biraz deli gibi görünüyordu . Uygun bir otomatik yükleme işlevi kullanmamak, CI'nin geriye dönük uyumluluğu hakkında en sevmediğim şeylerden biri, ancak bu başka bir tartışma ...
Adam Westbrook

0

Kısa cevap, kod örneğinizin biçiminin aldatıcı bir şekilde sezgisel olmasıdır. Bu "akılda kolay" bir yol gibi görünüyor.


Sorun # 1

Sizin Modelve Viewnesneleriniz sıkıca birleştirilir.

'De yöntem eklemek veya kaldırmakModel zorunda kalırsanız, Viewbuna göre değiştirmeniz gerekebilir .

Temel olarak, MVC Komuta ve Gözlemci kalıplarından mahrumdur . Bir istemek bağımsız bir yoluyla manipüle edilir 'Model' arayüz / API olduğunu Controller(yani heyet) içine kanca.

Sıklıkla, bu, a'nın içine enjekte edilmesiModel ve Viewörnekler Controllerverilmesi ve bunların bir özelliği olarak depolanması anlamına gelir Controller. Daha sonra, bir yöntem kullanarak Controllerçalışma alanı (yani bir komut), bir veri geçmek View gelen Model ( daha sonra `model bitmiş güncellenen uygulama durumu vardır ).

Veri iletme (diziler, yinelenebilir nesneler, her ne olursa olsun) arasındaki bağlantıyıModel ve Viewörnekleri gevşek tutar . Örneği Modeliçine enjekte ederseniz View, yukarıdaki Sorun # 1'e bakın.

Unutmayın, Viewsbir temsil durumu aktarım metodolojisini (REST) ​​izleyerek HTML, JSON, Metin, XML, HTTP üstbilgileri, YAML veya hemen hemen her şey olabilir .

Böylece arasındaki ilişkiyi nasıl yönetileceğini anlamanın anahtarı Modelve Viewsne için ilişkiyi, görmektir birini çoğa (potansiyel olarak)! Bu tam olarak Gözlemci modelinin başarmak için tasarlandığı şeydir .

Çoğu kurulum aynı anda yalnızca tek bir görüşe sahip olsa da, MVC mimari modelinin aynı anda birden çok görünümü güncellemesini engelleyen hiçbir şey yoktur! Geleneksel CRUD web uygulamalarıyla çalışmak insanların bire bir şekilde düşünmesini sağlar , ancak bu Observer modelinin nasıl çalışabileceğinin en küçük örneğidir ( birebir diğeri ).

Böylece, bir Modelveya birden çok varsa, API / yöntemlerinde bir şeyi değiştirdiğiniz için tüm uygulama kodunu güncellemenin Viewspotansiyel baş ağrısı artık akut hale gelir .Views'Model's

Verileri iletin Views , değil örneklerini Models .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.