Zend Framework görünümü veya denetleyicisi değişkeni ayarlamak için daha iyi mi?

7 Cevap php

Benim soru kurulum biraz ihtiyacı, yani ayı ile beni lütfen:

Ben model veri alma Görüntüle Yardımcıları kullanarak yerine deneticilere hepsini yağmurlama bir dönüştürmek oldu (şapka ipucu Eric Clemmons). Bu çok daha yeniden ve esnek var. Ben sadece onu seviyorum!

Ben genellikle ne, index.phtml şablonu ortaya koymak, ve ben bir model şey almak gerektiğinde, sonra bir detail.phtml bu pasajı koymak, bu yüzden mantık mümkün olduğunca dışına kadar olduğunu.

Ancak, yeniden olsun değişkenler için ihtiyacını görmeye başlarsınız. Örneğin, kategori adı. Şimdi tekrar tekrar bir model kedi adını almak için bir görünüm yardımcısı kullanmak istemiyorum. Bunu önbelleğe rağmen, açıkça bir güçlük yol çok büyük.

Yani değişkenleri ayarlamak için detail.phtml phpin birkaç satır kullanmaya başladı. Ve o artık doğru kokmuyor. İzlenme çok fazla mantığı olmamalıdır.

Peki tüm demek? Var tekrar alırsa, denetleyicisi koymak? Ya da bir çift görünümünde ayarlamak vars umursamıyorum?

EDIT: Alan Fırtına viewhelpers bir örnek için sordu:

detail.phtml:

<ul id="productList">

<? foreach($this->getProductById($id) as $product) : ?>
    <li><?= $this->escape($product['name']) ?></li>
<? endforeach; ?>

</ul>

(Anti-kısa-KIRILMASI saldırı için kendimi hazırlayarak)

ANOTHER EDIT: I see there can't be 2 right answers. Oh well...

7 Cevap

Ben bahsettiğin tam tekniği emin değilim. Aşağıda size modelin "get data" yöntemleri aramaları sararak bilgi dönmek View Helpers yöntemlerini oluştururken varsayar. Bu uzak diğer birçok PHP MVC Altyapıları tarafından istihdam Passive View desen sizi alır. Gösterim kendi veri modellerine doğrudan gidiyoruz. Sizin ilgilendiren konuları görünüm yardımcı için birden çok çağrı modeli iki veri getirmek için neden olacaktır. Bu kolayca önlenebilir görünüyor potansiyel bir performans sorundur.

//example of how I'm assuming you're using view helpers
echo $this->viewHelperName->modelName->getDataIWant('key');

Bu doğru bir sorunu açıklar, muhtemelen yanlış biridir yaklaşım "Ben aksi takdirde sadece görünümü yardımcı kullanmak, denetleyici bir görünüm değişken ayarlamak, iki kez kullanmanız gerekiyorsa." Bu daha benim kişisel tercihi olduğunu, ancak görünümüne modellerinden veri almak için seçtiğiniz yaklaşım hangisi, sizin uygulama boyunca ayrılmamak gerekir.

Burada çözmeye çalışıyoruz sorun "modellerinden verileri doğrudan getiriliyor yüksek performanslı bir maliyeti vardır" dir. Bu model implementation düzeltmek gereken bir sorundur. Bu janky kodlama stili tarafından sabit gereken bir şey değil :)

En iyi çözüm, zaten bahsettiğim gibi, önbelleklemesidir. Önbelleğe alma akıllı bu konuda eğer "bir güçlük çok büyük" olmak zorunda değildir.

public function getDataIWant($key, $clear_cache=false)
{
	if(!array_key_exists($key, $this->_cache) || $clear_cache)
	{
		$this->_cache[$key] = parent::getDataIWant[$key];
	}

	return $this->_cache[$key];
}

Önbelleğe alma modellerini kullanarak konum yol için uygun değilse, o zaman istediğiniz veri alma ve görünümü kapsamında değişkenleri tanımlamak için ekstresi kullanarak için model bir yöntem ekleyerek öneririm.

class MyModel
{
	...
	function getDataForFooView
	{
		return Array(
			'company_name'=>$this->getCompanyName
		);
	}
	...
}

...
//top of the view file
<?php extract($this->viewHelper->modelName->getDataForFooView()) ?>
<h1><?php echo $company_name; ?></h1>

Bu tür janky hala var, ama daha az koku olacaktır view dosyası bir tutarlılık (üstünde tek bir satır) olsun. O dedi, bu önbelleğe alma yapmak için "Sağ ™" yoludur. Kaçınarak sadece başka bir koku işlem görüyor. Sadece gelişigüzel bir şekilde, zaten önbelleğe kullanmakta olduğunuz (ya doğrudan görünümünde veya denetleyicisi olarak ayarlayarak) bir görünüm değişken tanımlamak zaman düşünmek için bir yoldur.

Kontrol ne Görünüm Ne uygulama durumunu saklamak içindir. Bu model için budur.

MVC bir "model" bir veritabanı tablo değil unutmayın! Model uygulama için iş mantığını uygulamak nerede, ve bir veritabanında saklayarak Bir Modelin bir iç uygulama ayrıntı. Ama bir veritabanı ile ilgisi yok app Modelleri olabilir.

Kısa cevap: IMHO, evet denetleyicisi koydum.

Nedenleri:

1) görüşlerini içine değişkenleri geçen kontrolör MVC daha tipiktir.

2) İdame: ben 3 ay sonra tekrar görünümü yeniden ziyaret ettiğinizde, ben değişkenleri arayan komşu views / şablonları etrafa bakmak zorunda istemiyorum. Şimdi belirli bir değişken kökenli nerede tahmin zorunda, geri spagetti kod vardır.

Ben gerçekten bu değişkenler fikrini sevmiyorum: bu görünümünde veya denetleyicisi ya daha kodu eklemek ve güzel gelmiyor.

Öte yandan, ben önbellek bu fikir gibi ... Olay Eğer çok karmaşık / overkill düşünüyorsanız.

Why not find some way in the middle ? Not use some cache like file/APC/memcache, but just keep the data in memory for the execution of the script ?
you can use a static variable for that ; either in your class, or directly in the method (depending on "does it make sense to share that cache between methods of the class ?")

Bu fikir göstermek için, kodu buraya hızlı bir bölümü var; Bu sınıf düşünün:

class A {
    public function test($param) {
        static $cache = array();
        if (isset($cache[$param])) {
            var_dump("cache hit : $param = {$cache[$param]}");
            return $cache[$param];
        } else {
            // Fetch from DB (here, simulated ^^ )
            $cache[$param] = mt_rand(0, 9999);
            var_dump("cache miss : $param = $cache[$param]");
            return $cache[$param];
        }
    }
}

test yöntem, statik bir değişken (orada olmak ve herhangi bir sınıfın örnekleri tarafından paylaşılan bu değişkenin, yalnızca bir örneği olacak) DB getirilen olmuştur veri depolamak için kullanır.

Eğer bu böyle dersek:

$a = new A();
$b = new A();

$a->test(10);   // miss
$a->test(15);   // miss
$b->test(10);   // hit
$b->test(25);   // miss
$a->test(25);   // hit

Bu alırsınız:

string 'cache miss : 10 = 3745' (length=22)
string 'cache miss : 15 = 7800' (length=22)
string 'cache hit : 10 = 3745' (length=21)
string 'cache miss : 25 = 8623' (length=22)
string 'cache hit : 25 = 8623' (length=21)

Yöntem, yeni bir parametre ile her çağrıldığında, bir bayan var, ve DB gidin. Bir parametre zaten bir kez kullanıldığında deniyor ama ne zaman, veri belleğinde - ve DB gitmez ;-)

Bu yardımcı olmaz? Ben tahmin ediyorum, senin durumunda, A sınıf btw, görünümü yardımcısıdır ;-) ve mt_rand ^ ^ DB sorgu olurdu

Bir dipnot düşmek gibi: Bu bazı RAM kullanmak gibi, çok büyük nesneler için yapılmamalı ... ve bu çok yok ...


Edit : as you are using Zend Framework, you might be interested in using Zend_Memory instead of that static variable : it deal with stuff like the amount of RAM taken (it can delete data from the "cache" if needed, for instance), if I remember correctly.

Ayrıca: evet, hala yöntemini birçok kez çağırıyor ... Ama bu sorgu yaparken daha iyi ... ve bu şekilde, Görünüm ne de Controller "önbellek" her türlü umurumda vardır: o değil onların iş.

Ve ayrıca: ben (onlara çok fazla değil sürece ben sadece küçük nesneleri bu şekilde saklamak gibi ve) herhangi bir sorun olmadan yıllardır bu tekniği kullanarak ettik; Ve ben bunu kullanarak tek ben değilim; Drupal Örneğin, çok kullanır.

I am using this in my controllers: $this->view-> someVariable = 1;

.... in the view

view-> someVariable

Ben denetleyicisi hemen hemen tüm değişken atar yapmak. Neden? Ben her eylem için mevcut çoklu manzarasına sahiptir. Ben ATOM, RSS ve sonra düz HTML sayfaları için beslemeleri kadar hizmet ContextSwitch kullanıyorum. Birçok yönden ben bir API (json veya xml) ve oEmbed kullanım için bu genişletmek olabilir. Farklı görüşleri benim modellerden farklı veri ihtiyacı olduğundan, ben, model nesneleri listemde atıyorum, ama ben sadece atadık ne erişen ediyorum.

Güzel bir şey o zaman ben veri sunmak istediğiniz şekilde görünüm senaryo yazmaya kez kontrolör yazabiliriz. Ben daha görünüme dayalı mantık için burada ve orada birkaç görünümü yardımcıları kullanıyorum.

Şimdi daha karmaşık görünümü yardımcıları ile bunu (ve isteği / önbellek memoize isteyen veri kayıt çeşit kullanabilirsiniz) sanırım, ama o zaman belki daha derin ihtiyacınız daha malzeme gizleme, ancak şu konum gibi görünüyor görüş meselesi.

So I started using a couple of lines of php in the detail.phtml to set variables. And it doesn't smell right anymore. Views shouldn't have too much logic.

Views can contain as much display logic as you like. Business logic should be in the model and/or controller, depending on if you prefer heavy or light models.

Kendi iş olarak, ben görünüm yardımcıları sitenin birçok yerinde yeniden kullanım olacak şeyler için gerçekten, vb navigasyon işlemek için reklamları bir görünüm yardımcısı vardır kullanıyorum sürece, denetleyici tüm değişkenleri atamak için eğilimindedir.

Görünümüne denetleyicisi değişkenleri atama, ve ben bir kayıt var, ben bu kayıt döngü eğilimindedir ve bir ilişkisel dizi üzerine onları itmek. Bunun yerine görünümüne gerçek kayıt geçirmeden, ben bu diziyi geçmektedir.

Bunun nedeni I can böylece:

  1. Kontrolör, değil görünümü ekran değerlerini (: 1234567890 123-456-7890 olur telefon) işleyin
  2. Herhangi katılır veya başka denetleyicisi getiriliyor mı
  3. (Yani vs, hatta ve tek satır için css sınıfını ayarlama) görünümü dışında önemsiz ekran mantığı tutun

Örnek Denetleyici:

$count = 0;
$list = array();
$result = mysql_query("select * from items limit 10");
while($item = mysql_fetch_object($result))
{
   if($count % 2 ==0){ $css_class = 'even'; } else { $css_class = 'odd'; }
   $count++;
   $item->css_class = $css_class;

   if($item->first_name && $item->last_name)
   {
      $item->name = $item->first_name.' '.$item->last_name;
   }
   else
   {
      $item->name = $item->username;
   }

   $list[] = $item;
}
$this->view->list = $list;

Örnek Görünüm:

<?foreach($this->list as $item):?>
<tr class="<?=$item->css_class?>">
    <td><?=$this->escape($item->name)?></td>
</tr>
<?endforeach;?>