[eluser]Dave Stewart[/eluser]
Excellent - I've done it, and made it pretty flexible as well!
You can now grab a fragment of any view in the usual CI way, with a method call such as:
Code:
$this->load->fragment($view, $vars, $pattern, $return);
Just like load->view() it parses any data sent to it, and can either be output straight to the page, or can be returned to be passed to any other view.
The main difference between load->view() is you now specify a pattern such as:
1 - A two-element array, consisting of a starting string and an ending string
2 - A regular expression
3 - A single tag name
Here's some example code:
Code:
.
// insert the div with an id of "users", using a regular expression
$this->load->fragment('master', $vars, '%<(div) id="users"(.+)</$1>%', true);
// grab the HTML between 2 comments, using an array, then insert into a view
$data['range'] = $this->load->fragment('master', $vars, array('<!--start-->', '<!--end-->'), true);
$this->load->view('blog', $data);
Here's the code for the actual class:
Code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Loader extends CI_Loader{
function MY_Loader()
{
parent::CI_Loader();
}
// --------------------------------------------------------------------
/**
* Load Fragment
*
* This function is used to load a fragment of a "view" file. It has four parameters:
*
* 1. The name of the "view" file to be included.
* 2. An associative array of data to be extracted for use in the view.
*
* 3. A pattern to delimit the start and end of the fragment to be grabbed. It can be:
* 1. A two-element array, consisting of a starting string, and an ending string
* The start and end string are included in the return value
* 2. A regular expression
* 3. A single tag name
*
* 4. TRUE/FALSE - whether to return the data or load it. In some cases it's advantageous
* to be able to return data so that a developer can process it in some way.
*
* @access public
* @param string
* @param array
* @param array / string
* @param bool
* @return void
*/
function fragment($view, $vars = array(), $pattern = '', $return = FALSE)
{
// ----------------------------------------------------------------------------------------------------
// grab the view using the existing CI functions
$output = $this->_ci_load(
array(
'_ci_view' => $view,
'_ci_vars' => $this->_ci_object_to_array($vars),
'_ci_return' => TRUE
)
);
// ----------------------------------------------------------------------------------------------------
// determine the delimiter type, and grab a fragment accordingly
// regular expression
// eg: "%<(body)(.+)</$1>%"
if(is_string($pattern) && preg_match('/^(\W).+\1[imsxe]*$/', $pattern)){
// make the pattern multiline and dot compatible
$pattern .= 'sm';
// do the match
preg_match($pattern, $output, $matches);
if(count($matches) >= 1)$output = $matches[0];
else trigger_error ("The fragment delineated by the regular expression <strong>'$pattern'</strong> was not found in the supplied view");
}
// single tag name
// eg: "body"
else if(is_string($pattern) && preg_match('%\[A-Za-z]+%', $pattern)){
$pattern = array("<$pattern", "</$pattern>");
}
// array - start delimter & end delimiter
// eg: array('<body', '</body>')
if(is_array($pattern)){
// start and end delimiter positions
$start = strpos($output ,$pattern[0]);
$end = strpos($output, $pattern[1]) + strlen($pattern[1]);
// check that delimiiters exist in output
if($start === false || $end === false){
trigger_error ("The delimiters <strong>'{$pattern[0]}'</strong> and/or <strong>'{$pattern[1]}'</strong> do not exist in the supplied view");
}
else{
$output = substr($output, $start, $end - $start);
}
}
// ----------------------------------------------------------------------------------------------------
// output & return
if($return == FALSE){
echo $output;
}
return $output;
}
}
And if you're using PHP4 you'll need to update the codeigniter/base4.php file, as detailed here:
http://ellislab.com/forums/viewthread/83614/
Cheers,
Dave