【问题标题】:Does CodeIgniter have to load view in the final step?CodeIgniter 是否必须在最后一步加载视图?
【发布时间】:2010-05-23 18:40:20
【问题描述】:

我有一个函数

function do_something() {
    // process
    $this->load->view('some_view', $data);
    exec('mv /path/to/folder1/*.mp3 /path/to/folder2/');
}

我的目的是在输出视图后移动文件。但显然它是在渲染视图之前完成的。我的问题是,$this->load->view(); 必须是函数的最后一步吗?

我做了一些研究,似乎我的问题类似于this topic。对吗?

【问题讨论】:

    标签: php codeigniter asynchronous task


    【解决方案1】:

    为什么不直接使用post_system 挂钩?它在最终页面发送到浏览器后调用,这样您就可以正常加载视图,而不会回显它们。

    这是一个示例控制器:

    class Home extends Controller {
    
        function index()
        {
            $this->move_audio = TRUE;
            $this->old_folder = "/path/to/folder/";
            $this->new_folder = "/path/to/folder2/";
    
            $this->load->view("some_view");
        }
    
    }
    

    还有一个示例钩子:

    function post_system()
    {
        $CI =& get_instance();
    
        if( isset($CI->move_audio) && $CI->move_audio === TRUE)
        {
            // Trim, then add trailing slash for consitency
            $old_folder = rtrim($CI->old_folder, "/")."/*.mp3";
            $new_folder = rtrim($CI->new_folder, "/")."/";
    
            exec("mv {$old_folder} {$new_folder}");
        }
    }
    

    查看hooks user guide 了解有关设置它们的信息。他们是你的朋友!

    编辑:我刚刚想到的东西......

    如果您只打算在一个控制器方法中执行此操作...使用 Phil 的方法可能会更好。这样可以避免对每个请求都进行钩子调用,如果您只需要一次,这将是不必要的。

    如果您只需要一次,您可以做的另一件事是使用 CI 的 _output() 控制器处理程序 (info here)。这将像这样工作:

    class Home extends Controller {
    
        // Initalize the var to avoid having to
        // check if it's set or not
    
        var $move_audio = FALSE;
    
        // CONTROLLER METHOD    
        function index()
        {
            $this->move_audio = TRUE;
            $this->old_folder = "/path/to/folder/";
            $this->new_folder = "/path/to/folder2/";
    
            $this->load->view("some_view");
        }
    
        // OUTPUT HANDLER
        function _output($output = "")
        {
            echo $output;
    
            if($this->move_audio === TRUE)
            {
                // Trim, then add trailing slash for consitency
                $old_folder = rtrim($this->old_folder, "/")."/*.mp3";
                $new_folder = rtrim($this->new_folder, "/")."/";
    
                exec("mv {$old_folder} {$new_folder}");
            }
        }
    }
    

    【讨论】:

    • 应该有帮助,但我稍微编辑了我的答案,因为如果你只需要一个控制器和一个方法的功能,那么这种方法就没有意义
    【解决方案2】:

    在运行命令之前将输出发送到浏览器:

    function do_something()
    {
        // process
        echo $this->load->view('some_view', $data, TRUE);
        exec('mv /path/to/folder1/*.mp3 /path/to/folder2/');
    }
    

    否则,您只是将数据提供给将在控制器完成后立即运行的输出类。

    【讨论】:

    • 知道为什么这是-1吗?在 CodeIgniter 方法中使用 echo 没有任何问题。
    【解决方案3】:

    没有。 实际上对于一些网络服务,我刚刚使用了这样的东西:

    function get_json_search() {
        $results = $this->My_model->get_stuffs();
        echo json_encode($results);
    }
    

    您还可以拥有完全不属于网络的控制器功能。只需在它们前面加上'_'。您永远不会将这些视为页面。

    function _upload_photo($filepath) { //resize it and so on
    

    也许你对 MVC 有误解。控制器是模型和视图之间的中介。同样,您也不需要使用模型。控制器只是从模型中获取内容并使用视图将其打印出来。没有理由(尽管这会是不好的风格)您不能使用控制器内部或其他来源的数据或从控制器打印出您的页面。

    如果您先加载视图,我不明白为什么它不起作用。尽管我会以相反的方式进行操作,以便您可以向用户提供反馈。如果文件无法移动,您应该向他们显示错误。如果它是性能密集型的,请考虑使用队列或 cron 作业。

    【讨论】:

      【解决方案4】:
      <?php
          while (ob_get_level()) {
              ob_end_flush();
          }
          // start output buffering
          if (ob_get_length() === false) {
              ob_start();
          }
      
          class Something extends Controller {
      
              function do_something() {
                  $this->load->view('some_view', $data);
                  ob_flush(); flush();
                  exec('mv /path/to/folder1/*.mp3 /path/to/folder2/');
              }
          }
      ?>
      

      【讨论】:

        猜你喜欢
        • 2021-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-07
        • 2015-10-26
        相关资源
        最近更新 更多