Php 在视图中设置变量还是在Zend框架中设置控制器更好?
我的问题需要一点设置,请耐心听我说: 我变成了一个使用视图助手从模型中获取数据的人,而不是把数据洒在控制器上(帽子尖到)。它的可重用性和灵活性更高。我就是喜欢 我通常做的是在index.phtml中布置模板,然后当我需要从模型中获取一些东西时,将该片段放入detail.phtml中,这样逻辑就尽可能地不受影响了 然而,我开始看到需要重用变量。例如,类别名称。现在,您不希望使用视图辅助对象一次又一次地从模型中获取cat名称。虽然你可以缓存它,但这显然是一个很大的麻烦 因此,我开始在detail.phtml中使用几行php来设置变量。而且闻起来也不对劲了。视图不应该有太多的逻辑 你们大家怎么说?如果var被重用,是否将其放在控制器中?或者不介意在视野中设置几个VAR 编辑:Alan Storm询问查看帮助程序的示例: detail.phtml:Php 在视图中设置变量还是在Zend框架中设置控制器更好?,php,model-view-controller,zend-framework,view-helpers,Php,Model View Controller,Zend Framework,View Helpers,我的问题需要一点设置,请耐心听我说: 我变成了一个使用视图助手从模型中获取数据的人,而不是把数据洒在控制器上(帽子尖到)。它的可重用性和灵活性更高。我就是喜欢 我通常做的是在index.phtml中布置模板,然后当我需要从模型中获取一些东西时,将该片段放入detail.phtml中,这样逻辑就尽可能地不受影响了 然而,我开始看到需要重用变量。例如,类别名称。现在,您不希望使用视图辅助对象一次又一次地从模型中获取cat名称。虽然你可以缓存它,但这显然是一个很大的麻烦 因此,我开始在detail.p
<ul id="productList">
<? foreach($this->getProductById($id) as $product) : ?>
<li><?= $this->escape($product['name']) ?></li>
<? endforeach; ?>
</ul>
(准备迎接反短贴者的攻击)
另一次编辑:
我知道不可能有两个正确答案。哦,好吧…控制器和视图都不是用来存储应用程序状态的。这就是这个模型的用途
请记住,MVC中的“模型”不是数据库表!模型是实现应用程序业务逻辑的地方,将其存储在数据库中是模型的内部实现细节。但是你的应用程序中可以有与数据库无关的模型。简短回答:嗯,是的,把它放在控制器中 原因: 1) 将变量传递到视图中的控制器是更典型的MVC
2) 可维护性:当我在3个月后再次访问视图时,我不想在相邻的视图/模板中查找变量。现在您又回到了意大利面代码,必须猜测特定变量的来源。我真的不喜欢这种变量的想法:它在视图或控制器中添加了更多代码,感觉不太好 另一方面,我喜欢缓存的想法。。。如果您认为它太复杂/过火,则会发生此事件 为什么在中间找不到路?不使用像file/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。但是,当一个参数已经使用过一次时调用它时,数据就在内存中,而您不需要转到DB;-)
那不会有帮助吗?我猜,在你的例子中,A
类是视图助手,顺便说一句;-)而mt_rand
将是一个DB查询^^
作为旁注:这不应该做太大的对象,因为它将使用一些RAM。。。而且没有太多的这些
编辑:当您使用Zend Framework时,您可能会对使用而不是静态变量感兴趣:它处理诸如占用的RAM量之类的事情(例如,如果需要,它可以从“缓存”中删除数据),如果我没记错的话 另外:是的,您仍然多次调用该方法。。。但这总比查询好。。。这样,视图和控制器都不必关心任何类型的“缓存”:这不是他们的工作
而且:我多年来一直在使用这种技术,没有任何问题(只要我只以这种方式存储小对象,而不是太多);我不是唯一一个用这个的人;例如,Drupal也使用这种技术。我不确定您所说的确切技术。下面假设您正在通过包装对模型的“get data”方法的调用来创建返回信息的方法。这使您摆脱了许多其他PHP MVC框架所采用的模式。视图将直接转到模型以获取其数据。您的问题是对视图助手的多次调用将导致模型两次获取数据。这是一个似乎很容易避免的潜在性能问题
//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>
classmymodel
{
...
函数getDataForFooView
{
返回数组(
“公司名称”=>$this->getCompanyName
);
}
...
}
...
//顶视图文件
$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;?>