如何在代码点火器中取消设置视图范围内的变量


How can I unset variables from a View's scope in Codeigniter

在我看来,我测试if (isset($winner)) .但是,该视图是循环重新打印的,我无法清除它以进行后续测试。

如何实例化新视图或清除/取消设置其控制器给出的变量?

我很欣赏视图的范围很广,但这似乎是 Codeigniter 中的一个错误。

控制器:

for($i=0; $i < 100; $i++) {
    $test = $this->prizedistributor->isWinner();
    echo $this->load->view("simulateResponse", $test, TRUE);
    unset($test['winner']); // this does not work
}     

视图:

<? if (isset($winner)):?>
    WINNER!
<? else: ?>
    LOST!
<? endif; ?>
<?php unset($winner); // this does not work! ?>

结果:

假设$i==40是唯一的赢家,视图会将所有$i> 40 报告为赢家,尽管控制器始终默认布尔值为假。

更新

我知道测试是否(空($test))允许视图正确报告。但是,我的问题是如何取消设置该变量(并将其从内存中清除)。这个问题很大程度上源于使用HMVC(模块化代码点火器)时的其他类似问题。但是,在此处发布该代码将过于复杂,无法说明相同的范围问题。


许多人一直在质疑上面无关紧要的奖品分销商。因此,这里有一个更简单的代码示例来说明 sampe 问题

控制器

function testScope() {
    for($i=0; $i < 10; $i++) {
        if($i == 5)$winner = array('winner' => true);
        else $winner = array();
        echo $this->load->view("testScope", $winner, TRUE);
    }        
}  

视图

<?= (isset($winner))  ? "WINNER!<br>" : "LOST!<br>"; ?>

输出

失去!失去!失去!失去!失去!胜利者!胜利者!胜利者!胜利者!胜利者!

可能的答案:

我已经研究了 codeigniter 的system/core/Loader.php,并找到了_ci_load第 800 行周围缓存变量的函数。他们的推理是:

您可以使用专用的 $this->load_vars() 设置变量 函数或通过此函数的第二个参数。我们将合并 两种类型并缓存它们,以便嵌入到其他中的视图 视图可以访问这些变量。

这提出了一个非常好的观点,也是我对codeigniter的欣赏。但问题仍然存在,我们怎样才能两者兼得?可能是跳过此捕获的第 4 个可选参数?

前任。 loader->view("testScope", $winner, TRUE, FALSE); ????

使用 TRUE/FALSE 可能比 isset 更好。

此外,您在发布的代码中加载视图的方式不会将名为 $winner 的变量发送到视图,除非isWinner()返回类似 array('winner' => 'someval') 的内容,这可能是这种情况。

TRUE/FALSE可能看起来像

for($i=0; $i < 100; $i++) {
    $test = $this->prizedistributor->isWinner();//isWinner() returns either array('winner' => '') or array('winner' => 'somevalue')
    echo $this->load->view("test_view", $winner, TRUE);
}   

视图

<?php if ($winner):?>
    WINNER!<br>
<?php else: ?>
    LOST!<br>
<?php endif; ?>

for($i=0; $i < 100; $i++) {
    if($i == 50){
        $winner = array('winner' => 123);
    }else{
        $winner = array('winner' => '');
    }
    echo $this->load->view("test_view", $winner, TRUE);
}     

指纹

...
LOST!
LOST!
LOST!
LOST!
LOST!
LOST!
WINNER!
LOST!
LOST!
LOST!
LOST!
LOST!
LOST!
...

如果您包括isWinner()中发生的事情或至少提及它正在返回的内容,则可能会有所帮助。

在 Codeigniter 3 中,您可以使用方法

$this->load->clear_vars();

在文档中查看

好的,

所以你似乎知道CI缓存传递给视图的变量。变量名称取决于您传递给 $this->load->view() 的数据的

// $myvar will be cached as "true"
$this->load->view('myview', array('myvar' => true));
// $myvar will still be there
$this->load->view('myview');
// $myvar will still be there, because myvar has not changed
$this->load->view('myview', false);
$this->load->view('myview', array());

要取消设置$myvar,您必须显式执行此操作:

$this->load->view('myview', array('myvar' => null));

您的代码:

$test = $this->prizedistributor->isWinner();
echo $this->load->view("simulateResponse", $test, TRUE);

如果$test只是 false 或 null,则不会取消设置或更改已缓存的变量。它实际上什么也没做。你可以使用更像这样的东西:

$test = $this->prizedistributor->isWinner();
echo $this->load->view("simulateResponse", array('winner' => $test), TRUE);

isWinner()返回真/假而不是数组。

不幸的是,我认为您无法真正取消设置变量,但您可以将其设置为 null/false。

如果$var === nullisset($var)将返回 false。

您可以创建一个帮助程序函数来加载视图并在之后销毁参数。

if (!function_exists('load_cleaned_view'))
{
    function load_cleaned_view($view, $data = NULL, $return_as_string = FALSE)
    {
        $CI =& get_instance();
        $content = $CI->load->view($view, $data, $return_as_string);
        if(!empty($data))
        {
            foreach ($data as $key => $value) $data[$key] = NULL;
            $CI->load->view($view, $data, TRUE);
        }
        return $content;
    }
}

可以处理空变量的视图一起使用,而不是与由于性能问题而调用的每个视图一起使用。

clear_vars(); 很有趣,但它取消设置所有变量,而不是当前视图中的变量。

您是否尝试过直接从视图中获取数据?

控制器

for($i=0; $i < 100; $i++) {
    $this->load->view("simulateResponse");
}    

视图

<? if($this->prizedistributor->isWinner()): ?>
    WINNER!
<? else: ?>
    LOST!
<? endif; ?>

如果您正在寻找 MVC 解决方案:

控制器

<?php
    for($i=0; $i < 100; $i++)
        $data['winner_array'][$i] = $this->prizedistributor->isWinner();
    $this->load->view("simulateResponse", $data);
?>

视图

<? foreach($winner_array as $win): ?>
    <? if($win): ?>
        WINNER!
    <? else: ?>
        LOST!
<? endif; endforeach; ?>

首先,您的问题不清楚两件事:

  1. $this->prizeddistributor->isWinner() 如何运作
  2. $winner是否设置为在某个时候$test?

现在,有了这个...您的控制器不知道"在视图中"会发生什么。 您只需回显文本,控制器将继续运行。

考虑到这一点...我假设$winner是由 $test 中的值设置的,这意味着您的 isWinner() 函数生成了错误的值。 根据您的问题,它应该为除 40 之外的所有 $i 值提供 null。

我认为重点是您的视图范围不会像您希望的那样影响控制器范围。 而且你可能需要更深入地了解isWinner()是如何工作的。