I'm not sure if I'm interpreting this wrong but please correct me if I am. I'm using Code Igniter's Loader class to load an application "package". It is working fine for the most part. However, one thing that's tripping me up is how the view paths are working (or not working).
In the documenta开发者_StackOverflow中文版tion (http://codeigniter.com/user_guide/libraries/loader.html), it says:
"By Default, package view files paths are set when add_package_path() is called. View paths are looped through, and once a match is encountered that view is loaded.
In this instance, it is possible for view naming collisions within packages to occur, and possibly the incorrect package being loaded. To ensure against this, set an optional second parameter of FALSE when calling add_package_path()."
This is the example code they give:
$this->load->add_package_path(APPPATH.'my_app', TRUE);
$this->load->view('my_app_index'); // Loads
$this->load->view('welcome_message'); // Will not load the default welcome_message b/c the second param to add_package_path is TRUE
// Reset things
$this->load->remove_package_path(APPPATH.'my_app');
// Again without the second parameter:
$this->load->add_package_path(APPPATH.'my_app', TRUE);
$this->load->view('my_app_index'); // Loads
$this->load->view('welcome_message'); // Loads
I think there is a typo in the example code and they mean to pass in FALSE to the second call to add_package_path(). My interpretation of this is that, if you pass in FALSE, the view path of the package should be skipped and the original view path should be used.
However, when I actually try to pass in FALSE, I am still getting the view from the external package (the view name exists in both the external package and the current application). Looking at the Loader class in /system/core/Loader.php, this is the definition of add_package_path():
public function add_package_path($path, $view_cascade=TRUE)
{
$path = rtrim($path, '/').'/';
array_unshift($this->_ci_library_paths, $path);
array_unshift($this->_ci_model_paths, $path);
array_unshift($this->_ci_helper_paths, $path);
$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
// Add config file path
$config =& $this->_ci_get_component('config');
array_unshift($config->_config_paths, $path);
}
What it does is add the package view path to the front of the view paths array, with a value of TRUE or FALSE. In the function that actually loads the views, also in the Loader class and called _ci_load($_ci_data), this is the segment where it chooses the path of views to look in:
foreach ($this->_ci_view_paths as $view_file => $cascade)
{
if (file_exists($view_file.$_ci_file))
{
$_ci_path = $view_file.$_ci_file;
$file_exists = TRUE;
break;
}
if ( ! $cascade)
{
break;
}
}
It seems to me that if the view exists in the external package (since it will be at the from of the array from the call to add_package_path), it will be loaded regardless of whether the 2nd parameter in add_package_path is TRUE or FALSE. There's not too much documentation on this and I didn't see any bug reports filed for this. Again, my interpretation is that if the 2nd parameter passed in to add_package_path() is FALSE, the view path of the package should be skipped. I'm thinking that in _ci_load(), inside the check for cascade should be a continue instead of a break, and it should come before the check for the file.
Is this a bug that I should report or am I interpreting something incorrectly here and the function is working as it should be?
The typo exists to this date as well! The second argument in the second code example should have been FALSE.
My interpretation of the usage is:
If the second argument is TRUE, then the view will ONLY be loaded from the external package.
If the second argument is FALSE, then the view will be loaded from the external package or the local repo depending on where it is found (checking the external package first). The idea being that if it's not in the external package, the search should continue in the local repo.
精彩评论