【问题标题】:How can I unset variables from a View's scope in Codeigniter如何在 Codeigniter 中取消设置视图范围内的变量
【发布时间】:2013-10-24 23:39:28
【问题描述】:

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

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

我很欣赏 View 的范围很广,但这似乎是 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 为赢家。

更新

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


许多人一直在质疑上面无关的奖品分发者。所以这里有一个更简单的代码示例来说明示例问题

控制器

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。但问题仍然存在,我们怎样才能两者兼得?可能是第四个可选参数来跳过这个捕获?

例如。 loader-&gt;view("testScope", $winner, TRUE, FALSE);????

【问题讨论】:

  • 尝试给获胜者一个值并与之进行比较。 $winner == 这个迭代次数。满足条件时设置为0。
  • @KaiQing,这在我的情况下不起作用。获胜者在图书馆内确定。我想我可以传递 $i 和另一个变量,但坦率地说,这并不能回答我的问题。
  • @stormdrain,哈哈。很公平。但是,这里甚至没有回答如何取消设置。除非 wesley murch 的陈述是真的,否则它不可能是真的。无论如何,我在这里为你和其他人加分。
  • 我们回答它:“要取消设置 $myvar,你必须明确地这样做:$this->load->view('myview', array('myvar' => null));” ;您必须将 null'd var 发送到视图,否则之前的值将保留在缓存中。
  • @EliATaylor 很有趣。在您发布的链接中,接受的答案是:“如果您正在执行 $whatever = null; 那么您正在重写变量的数据。您可能会更快地释放/缩小内存,但它可能会从真正需要它们的代码中窃取 CPU 周期更快,从而导致更长的整体执行时间。”。无论如何,无效化似乎是更好的选择-如果关注的是内存。即 nullifying 一个 var 将使 PHP 的 gc 比 unset() 更快地对其采取行动。

标签: php codeigniter scope codeigniter-2


【解决方案1】:

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

此外,您在发布的代码中加载视图的方式不会将名为$winner 的变量发送到视图,除非isWinner() 返回类似array('winner' =&gt; '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() 中包含正在发生的事情或至少提及它返回的内容,可能有助于获得更好的答案。

【讨论】:

  • “获胜者”确实由奖品发行商定义(或未定义)。此外,是的,测试为 (!empty($winner)) 确实允许视图正确测试。但是,这同样不能回答我的问题,该问题来自我使用 Codeigniter 遇到的几个范围问题。
  • 您最后一次在控制器中取消设置的建议也不起作用。另外,在我的实际代码中,$test 是一个单独函数的局部变量,它对实际的 echo 语句没有作用域。
【解决方案2】:

在 Codeigniter 3 中你可以使用方法

$this->load->clear_vars();

See it in documentation

【讨论】:

    【解决方案3】:

    好的,您似乎知道 CI 缓存了传递给视图的变量。变量名称取决于您传递给$this-&gt;load-&gt;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。

    【讨论】:

    • 这样的变量无效化是不可能的。同样,我对 unset 的坚持很大程度上与记忆有关。我想在大多数情况下,这将是微不足道的节省。在我看来,我相信不是。
    • 我不完全确定你的意思,但不要猜测你应该只检查 CI 分析器。我几乎可以肯定,无论采用哪种方式,这里都不会有瓶颈,如果存在的话,差异也将是微不足道的。
    【解决方案4】:

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

    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(); 很有趣,但它会取消设置所有变量,而不是当前视图中的变量。

    【讨论】:

      【解决方案5】:

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

      控制器

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

      【讨论】:

      • 我更愿意保留 MVC,即使这确实有效。
      • 查看编辑,此解决方案假定 isWinner() 返回布尔值
      【解决方案6】:

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

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

      现在,不碍事了……您的控制器不知道“在视图中”会发生什么。您只是在回显文本,然后控制器继续运行。

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

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

      【讨论】:

      • 对您的问题: 1. 它做了很多事情,包括可能用数据设置关键“赢家”。 2. 是的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 2018-08-04
      • 2015-03-22
      相关资源
      最近更新 更多