Quote:I am trying to read the source code of CI 2, I am confused about this In view method of core/Loader class:
I can't get the point of this fragment,
* Flush the buffer... or buff the flusher?
* In order to permit views to be nested within
* other views, we need to flush the content back out whenever
* we are beyond the first level of output buffering so that
* it can be seen and included properly by the first included
* template and any subsequent ones. Oy!
if (ob_get_level() > $this->_ci_ob_level + 1)
1st: The code comment says it is for nested views, but I think it will be flushed in the following case:
Every time we run the view method, a buffer will be opened, so if we load two views, even if they are not nested, the first one will be flushed, is that right?
If you load a view which does not contain a nested view, it is loaded into the buffer, the buffer's contents are appended to the output, the buffer is cleaned, and output buffering is turned off. This whole process is the same every time you call $this->load->view(), unless the loaded view contains another call to $this->load->view().
If you call $this->load->view() from within a view (which was itself loaded by a call to $this->load->view()), you end up with a stack of buffers (depending on the nesting of the views) which has to be flushed to be processed properly by the output handler. No matter how the views are nested, the code you are looking at is always dealing with the buffer of the current view. If it's a nested view, it's flushed with ob_end_flush(), if it's a top-level view, it is passed to the output handler via ob_get_contents() and the output buffer is closed with ob_end_clean().
The reason this works is that nested views will cause the Loader's method to be called when the view is placed in the buffer, so the Loader waits for the nested views to be processed before it finishes processing the original view.
Quote:2nd: why we need to flush the earliest buffer instantly?
Since they will be flushed automatically in the end, in fact I found there are no 'ob_end_flush' in the final render method,Output->_display(), that means CI still rely on the auto flushing function , right?
Each buffer is flushed when the loader is done with it, there's no auto-flushing going on. The loader uses output buffering to ensure the views are loaded and processed in the proper order and suppresses the output by flushing the buffer to a string stored in the Output class until output is started by the framework.
Quote:3rd: Why the condition is the current ob level greater than the default level +1?
If I load two views, the second view will trigger the flushing, right?
The loader always closes the buffer after a view has been completely processed. ob_end_flush() is only called for nested views, because the buffer has to remain open until it gets back to processing the original view.
Quote:4th: If a view is flushed manually here, would it still be adjusted by Output->_display()?
I was trying my best to speak it clearly, I hope you can help me. Thank you.
More than likely, if you start manually flushing the buffer, you'll create an error somewhere. It is possible to use output buffering in a CI application without causing problems, but you have to be extremely careful, and, in most cases, avoid using $this->load->view() until you've finished dealing with the buffer.
If you want Output->_display() to handle the output, you have to use Output->append_output() or Output->set_output() for anything which isn't processed by $this->load->view().
It's usually best to let CI manage the output buffer by only performing output in your views.