Here is how the MODx - CodeIgnitor bridge works:
The MODx index.php processes all requests.
1) If a page is not found, then send the request to CodeIgnitor, and let CodeIgnitor handle it.
2) If the page is found, and cacheable is UNCHECKED, then CodeIdgnitor gets to process the request, but MODx will serve the page. So if CodeIgnitor want’s to display anything, it needs to load its output into $modx->documentContent for display.
3) If the page is found and cacheable is checked, then just serve the regular MODx page.
Setup:
install MODx
turn on friendly urls
best to also use friendly alias paths
install CodeIgnitor in a separate directory, outside of webroot
For CI:
Edit application/config/config.php
Find these settings, and update them:
$config['base_url'] = "http://www.yourmodxwebsite.com";
$config['index_page'] = "";
$config['url_suffix'] = ".html";
Edit system/codeignitor/Codeignitor.php
Find the first four lines, comment them out, and add the next 8 lines after (this is necessary because of the way MODx wraps CI)
//$CFG =& load_class('Config');
//$URI =& load_class('URI');
//$RTR =& load_class('Router');
//$OUT =& load_class('Output');
$GLOBALS['CFG'] =& load_class('Config');
$CFG = &$GLOBALS['CFG'];
$GLOBALS['URI'] =& load_class('URI');
$URI = &$GLOBALS['URI'];
$GLOBALS['RTR'] =& load_class('Router');
$RTR = &$GLOBALS['RTR'];
$GLOBALS['OUT'] =& load_class('Output');
$OUT = &$GLOBALS['OUT'];
In MODx, create a new plugin called CIBridge
On the System Events tab check the events:
OnLoadWebDocument
OnPageNotFound
Paste in this code (modify first line in necessary):
define('CI_DISPATCHER', '../ci/index.php');
$e = &$modx->Event;
if($e->name=='OnLoadWebDocument') {
if($modx->documentObject['cacheable'])
return;
}
if($e->name=='OnLoadWebDocument' || $e->name=='OnPageNotFound') {
$cibridge['error_reporting'] = ini_get('error_reporting');
$cibridge['display_errors'] = ini_get('display_errors');
if(isset($_SERVER['PATH_INFO'])) $cibridge['PATH_INFO'] = $_SERVER['PATH_INFO'];
if(isset($_SERVER['REQUEST_URI'])) $cibridge['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
if(isset($_SERVER['QUERY_STRING'])) $cibridge['QUERY_STRING'] = $_SERVER['QUERY_STRING'];
if(isset($_GET['q'])) $cibridge['q'] = $_GET['q'];
$path = isset($_GET['q']) ? $_GET['q'] : '';
$path = '/' . $path;
$_SERVER['PATH_INFO'] = $path;
$_SERVER['REQUEST_URI'] = $path;
unset($_GET['q']);
ob_start();
include(CI_DISPATCHER);
$output = ob_get_contents();
ob_end_clean();
ini_set('error_reporting', $cibridge['error_reporting']);
ini_set('display_errors', $cibridge['display_errors']);
if(isset($cibridge['PATH_INFO'])) $_SERVER['PATH_INFO'] = $cibridge['PATH_INFO'];
if(isset($cibridge['REQUEST_URI'])) $_SERVER['REQUEST_URI'] = $cibridge['REQUEST_URI'];
if(isset($cibridge['QUERY_STRING'])) $_SERVER['QUERY_STRING'] = $cibridge['QUERY_STRING'];
if(isset($cibridge['q'])) $_GET['q'] = $cibridge['q'];
}
if($e->name=='OnPageNotFound') {
echo $output;
exit;
}
Now it is time for some simple testing.
1) Go to a MODx page and make sure it loads normally.
2) Go to welcome.html and make sure you get CodeIgnitor’s welcome page.
3) Go to a non-existent page, and you should see a CodeIgnitor 404.
Now there are two ways of creating a new CodeIgnitor page...
The first way is to just create a controller (and view and model) in CI. Your page will be accessible at yourcontrollername.html
The second way is to create a controller in CI, and create the view in MODx. For example, create a controller called myblog, and create a page in MODx called myblog and be sure to uncheck the cacheable attribute.
In the controller, don’t load the view the normal way.
$this->load->view('myblog_view', $data);
Instead you load the view like this:
$content = 'Sample content';
$this->loadmodxview('',array('content'=>$content));
(you can load pieces of output into any [*placeholder*] you want)
or like this:
$content =$this->load->view('myblog_view', $data, true);
$this->loadmodxview('',array('content'=>$content));
Of course you will also need to add this code into your controller:
function loadmodxview ($_ci_view = '', $_ci_vars = array(), $_ci_return = FALSE)
{
global $modx;
$_ci_vars = $this->load->_ci_object_to_array($_ci_vars);
/*
* Extract and cache variables
*
* You can either set variables using the dedicated $this->load_vars()
* function or via the second parameter of this function. We'll merge
* the two types and cache them so that views that are embedded within
* other views can have access to these variables.
*/
if (is_array($_ci_vars))
{
$this->load->_ci_cached_vars = array_merge($this->load->_ci_cached_vars, $_ci_vars);
}
$_ci_placeholders = array();
foreach($this->load->_ci_cached_vars as $_ci_key => $_ci_val)
{
$_ci_placeholders[$_ci_key] = '[*'.$_ci_key.'*]';
}
$buffer = str_replace($_ci_placeholders,$this->load->_ci_cached_vars,$modx->documentContent);
$modx->documentContent = $buffer;
// Return the file data if requested
if ($_ci_return === TRUE)
{
return $buffer;
}
/*
* 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->load->_ci_ob_level + 1)
{
echo $buffer;
}
else
{
// PHP 4 requires that we use a global
global $OUT;
$OUT->set_output($buffer);
}
}
This is all beta stuff. I would like to move some of the code to CI hooks, and make other improvements, but at least it works.
If you use MODx pages as views, you can output things like [!Wayfinder!] from CI and have it processed by MODx. Later I hope to run CI output through the MODx parser even for CI pages that don’t have a corresponding MODx page.