Does CodeIgniter have to load view in the final st

2019-02-20 09:49发布

问题:

I have a function

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

My intention is to move files after outputting the view. But apparently it is done before rendering the view. My question is, does $this->load->view(); have to be the final step in a function?

I did a little research, and seems like my question is similar to this topic. Correct?

回答1:

Why don't you just use a post_system hook? It's called after the final page is sent to the browser, that way you can load views normally, without echoing them out.

Here's an example controller:

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");
    }

}

And an example hook:

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}");
    }
}

Check out the hooks user guide for info on setting them up. They are your friends!

EDIT: Something I just thought of...

If you're only going to be doing this inside one controller method... it would probably be better to use Phil's approach. This would avoid having a hook call for every request which would be unnecessary if you only need it once.

Another thing you could do, if you only need it once, is use CI's _output() handler for Controllers (info here). That would work like this:

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:

Send the output to the browser before you run the command:

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

Otherwise you are just giving data to the Output class that will run as soon as the Controller is finished.



回答3:

No. Actually for some web services I have just used something like this:

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

You can also have controller functions which are fully private from the web. Just prefix them with '_'. You would never view these as pages.

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

Perhaps you are misunderstanding MVC. The controller is an intermediary between the model and view. Likewise you don't need to use models either. The controller just getting stuff from models and using the view to print it out. There is no reason (although it would be bad style) you cannot use data from within the controller or from other sources or print out your page from the controller.

I don't see why it won't work if you load the view first. Although I would do it the other way around so you can offer feedback to the user. You should display an error to them if the files fail to move. If it is performance intensive consider using a queue or cron jobs.



回答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/');
        }
    }
?>