在Zend Framework中的视图或控制器中设置变量是否更好?

时间:2009-08-12 22:05:22

标签: php model-view-controller zend-framework view-helpers

我的问题需要一些设置,所以请耐心等待:

我成为了一个转换,使用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个正确的答案。哦,好吧......

7 个答案:

答案 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来设置变量。     它再也闻不到了。观点不应该有太多的逻辑。

  

视图可以包含任意数量的显示逻辑。 业务逻辑应该在模型和/或控制器中,具体取决于您是喜欢重型还是轻型型号。

在我自己的工作中,我倾向于在控制器中分配所有变量,除非我使用视图助手来渲染导航,广告等。视图助手真的是你可以在很多部分重复使用的东西。该网站。

当在控制器中将变量分配给视图时,我有一个记录集,我倾向于遍历该记录集并将它们推送到关联数组。我没有将实际的记录集传递给视图,而是将它传递给了这个数组。

这样做的原因是我可以:

  1. 操纵控制器中显示的值,而不是视图(电话:1234567890变为123-456-7890)
  2. 在控制器中进行任何连接或其他提取
  3. 将琐碎的显示逻辑放在视图之外(即设置偶数和奇数行的css类等)
  4. 示例控制器:

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