我的问题需要一些设置,所以请耐心等待:
我成为了一个转换,使用View Helpers从模型中获取数据,而不是将其全部洒在控制器上(帽子提示为Eric Clemmons)。它在那里更具可重用性和灵活性。我只是喜欢它!
我通常做的是在index.phtml中布置模板,然后当我需要从模型中获取某些内容时,将该代码段放在detail.phtml中,因此逻辑尽可能地远离可能的。
但是,我开始看到需要重用的变量。例如,类别名称。现在,您不希望使用视图助手来反复从模型中获取cat名称。虽然你可以缓存它,但显然太麻烦了。
所以我开始在detail.phtml中使用几行php来设置变量。它再也闻不到了。观点不应该有太多的逻辑。
那你说的都是什么?如果var被重用,把它放在控制器中?或者不介意在视图中设置几个变量?
编辑:Alan Storm问了一个观察者的例子:
detail.phtml:
<ul id="productList">
<? foreach($this->getProductById($id) as $product) : ?>
<li><?= $this->escape($product['name']) ?></li>
<? endforeach; ?>
</ul>
(支持自己攻击反短标签)
另一个编辑: 我看到没有2个正确的答案。哦,好吧......
答案 0 :(得分:5)
Controller和View都不用于存储应用程序状态。这就是模型的用途。
请记住,MVC中的“Model”不是数据库表! Model是您为应用程序实现业务逻辑的地方,将其存储在数据库中是Model的内部实现细节。但是,您可以在应用中使用与数据库无关的模型。
答案 1 :(得分:2)
简短的回答:恕我直言,是的把它放在控制器里。
理由:
1)将变量传递到视图中的控制器是更典型的MVC。
2)可维护性:当我在3个月内再次访问视图时,我不想在相邻的视图/模板中查找寻找变量。现在你回到意大利面条代码,不得不猜测特定变量的来源。
答案 2 :(得分:2)
我真的不喜欢这个变量的想法:它在视图或控制器中添加更多代码,并且感觉不太好。
另一方面,我喜欢缓存的想法...如果你觉得它过于复杂/过度就会发生事件。
为什么不在中间找到一些方法?不使用像文件/ APC / memcache这样的缓存,只是将数据保存在内存中以执行脚本? 你可以使用静态变量;在你的类中,或直接在方法中(取决于“在类的方法之间共享缓存是否有意义?”)
为了说明这个想法,这里是代码的快速部分;考虑这个课程:
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
方法使用一个静态变量(该类的任何一个实例共享一个,只有该变量的一个实例)来存储从数据库中提取的数据。
如果你这样称呼:
$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
你会得到这个:
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)
每次使用新参数调用方法时,都会错过,然后转到数据库。但是当一个参数已经使用过一次时调用它,数据就在内存中 - 你不会去DB; - )
这不会有帮助吗?我猜,在你的情况下,A
类是视图助手,顺便说一下;-)而且mt_rand
将是一个数据库查询^^
作为旁注:对于太大的物体不应该这样做,因为它会使用一些RAM ......并且没有很多这样的......
编辑:当你使用Zend Framework时,你可能会对使用Zend_Memory
而不是那个静态变量感兴趣:它处理的东西就像所占用的RAM量一样(如果需要,可以从“缓存”中删除数据)例如),如果我没记错的话。
另外:是的,你仍然多次调用该方法......但它比查询更好......而且,这样,View和Controller都不必关心任何类型的“缓存”:这不是他们的工作。
并且:我已经使用这种技术多年没有任何问题(只要我这样存储小物件,而不是太多);而且我不是唯一一个使用它的人;例如,Drupal也使用它。
答案 3 :(得分:2)
我不确定你所说的确切技巧。以下假设您在View Helpers上创建方法,通过将调用包装到模型的“获取数据”方法来返回信息。这使您远离许多其他PHP MVC框架所采用的Passive View模式。视图直接转到模型的数据。您的概念是多次调用视图助手将导致模型两次获取数据。这是一个潜在的性能问题,似乎很容易避免。
//example of how I'm assuming you're using view helpers
echo $this->viewHelperName->modelName->getDataIWant('key');
如果这准确地描述了你的问题,“如果我需要使用它两次,在控制器中设置一个视图变量,否则只使用视图助手”方法可能是错误的。这更多是我个人的偏好,但无论您选择哪种方法从模型中获取数据到您的视图,您都应该坚持使用整个应用程序。
您在此尝试解决的问题是“直接从模型中获取数据具有很高的性能成本”。这是模型实现应该修复的问题。这不应该由janky编码风格来修复:)
正如您已经提到的,最佳解决方案是缓存。如果你对它很聪明的话,缓存不一定是“太大的麻烦”。
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];
}
如果缓存对于使用模型的方式不可行,那么我建议在模型中添加一个方法来获取所需的数据,并使用extract在视图范围中定义变量。
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>
它仍然有些笨拙,但是你的视图文件(顶部的一行)会保持一致性。也就是说,缓存是“正确的”方式。避免这只是为另一种气味换一种气味。一种思考定义视图变量的方法(直接在视图中或通过在控制器中设置它),你已经在使用缓存,只是偶然的方式。
答案 4 :(得分:1)
我在我的控制器中使用它: $ this-&gt; view-&gt; someVariable = 1;
.... 在视图中
视图 - &GT; someVariable
答案 5 :(得分:1)
我在控制器中执行几乎所有变量赋值。为什么?我有多个视图可用于每个操作。我正在使用ContextSwitch为ATOM,RSS和纯HTML中的页面提供提要。在很多方面,我可以将它扩展到API(json或xml)和oEmbed处理。现在,我在我的模型对象列表中进行分配,因为不同的视图需要我的模型中的不同数据,但我只是访问我已分配的内容。
好处是我可以编写一次控制器,然后以我想要呈现数据的方式编写视图脚本。我在这里和那里使用一些视图助手来获得更多基于视图的逻辑。
现在我猜你可以用更复杂的视图帮助程序(并使用某种注册表来处理你想要在请求中记忆/缓存的数据),但似乎你隐藏的东西比你需要的更深,但这可能是一个意见问题。
答案 6 :(得分:1)
所以我开始在detail.phtml中使用几行php来设置变量。 它再也闻不到了。观点不应该有太多的逻辑。
视图可以包含任意数量的显示逻辑。 业务逻辑应该在模型和/或控制器中,具体取决于您是喜欢重型还是轻型型号。
在我自己的工作中,我倾向于在控制器中分配所有变量,除非我使用视图助手来渲染导航,广告等。视图助手真的是你可以在很多部分重复使用的东西。该网站。
当在控制器中将变量分配给视图时,我有一个记录集,我倾向于遍历该记录集并将它们推送到关联数组。我没有将实际的记录集传递给视图,而是将它传递给了这个数组。
这样做的原因是我可以:
示例控制器:
$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;
示例视图:
<?foreach($this->list as $item):?>
<tr class="<?=$item->css_class?>">
<td><?=$this->escape($item->name)?></td>
</tr>
<?endforeach;?>