We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 15170
    • 90 Posts
    Thanks Everett.
    Waiting for Revolution!
      • 17499 ☆ A M B ☆
      • 872 Posts
      Quote from: Everett at Sep 19, 2009, 02:08 PM

      CodeIgniter is a PHP framework... MODx is a CMS. Lots of overlap here, but they’re not the same. Revolution is built on a new framework: xPDO, and it looks really promising. Jason has been doing a lot of work on this and I’m excited to try it out. However, it’s very young, so there is precious little documentation, whereas CodeIgniter has videos and books etc.

      I thought that xPDO was more an ORM like Propel than a php framework like CodeIgniter.

      If the capabilities going to be extended, then it’s really a good news.

      Is it confirmed?
        • 22303 MODX Staff
        • 10,725 Posts
        Quote from: lossendae at Sep 20, 2009, 04:00 AM

        Quote from: Everett at Sep 19, 2009, 02:08 PM

        CodeIgniter is a PHP framework... MODx is a CMS. Lots of overlap here, but they’re not the same. Revolution is built on a new framework: xPDO, and it looks really promising. Jason has been doing a lot of work on this and I’m excited to try it out. However, it’s very young, so there is precious little documentation, whereas CodeIgniter has videos and books etc.

        I thought that xPDO was more an ORM like Propel than a php framework like CodeIgniter.

        If the capabilities going to be extended, then it’s really a good news.

        Is it confirmed?
        xPDO is an O/RM similar to Propel or PHPDoctrine. As I understand CodeIgniter has some O/RM-like capabilities available as well, though they are limited to the ActiveRecord pattern or what are called table-classes in the more capable O/RMs. xPDO + MODx (Revolution) together starts to become an MVC-based framework for content management, but xPDO is still there for just it’s purpose. Similarly, xPDO + Smarty becomes a framework for simple templating without the content management features. And xPDO can also be used in stand-alone PHP pages, which is in and of itself already a "templating" language.

        TBH, I don’t like single-source frameworks like CodeIgniter or CakePHP, because they dictate too much in exchange for the convenience of all the various capabilities they make available to you. For this reason, we will not be extended xPDO to do everything; it is there to manage data persistence and should be limited to that role, and without dictating what other code you can use it with. Zend FW is much better at decoupling it’s various classes and features from the others, and as such it is a much better fit for "integrating" with xPDO and MODx already; I’ve used various pieces of Zend FW in several deployments, both with Revolution and Evolution.

        I find it funny that one of the things on CodeIgniter’s home page says "You are not interested in large-scale monolithic libraries like PEAR." PEAR is anything but monolithic, regardless of how much contempt I have for the actual code and implementations in it. You use what you need from PEAR and leave the rest alone, just like with Zend FW. But I will end my critique there as I have never actually used CodeIgniter myself, and their documentation is definitely good. I just don’t see a good fit for using it within MODx as it seems there is a lot of duplication of purpose (i.e. they are both MVC frameworks, just with different approaches as CI is not focused on Content Management).

        So, MODx is an extension of xPDO for Content Management purposes. Beyond that, you can use whatever classes and libraries you want with them (if they are decoupled from the central core of a "framework").
          • 29774
          • 386 Posts
          FWIW, Codeigniter is quite a bit ’lighter’ than Cake (and featherweight compared to Symfony or Zend FW considered as a whole) in that it is essentially a front controller with helper classes - no built in ACL, no Authentication, no ORM (CI’s Active Record is not a true AR implementation), no strict conventions. I like that, it doesn’t force you into a single paradigm which is much the same as the Modx ’philosophy’ in my view. The CI community has developed some very interesting solutions to fill the gaps; for example, DMZ is an easy to use ORM with form validation/generation capabilities.

          I know xPDO offers very similar capabilities - and the combination with the Modx Revo API is almost irresistible - I *really* want to use it but thus far I’ve been too nervous to dive in; if there was a user guide like the one for DMZ I’d feel much more confident. wink
            Snippets: GoogleMap | FileDetails | Related Plugin: SSL
            • 24935
            • 160 Posts
            Over the past few weeks I have been working on creating a package to integrate MODx and CodeIgnitor. I have a lot of it working, but I would like to implement some more features before releasing it. Specifically I want to finish implementing a feature to use MODx templates as CodeIgnitor views. However, I may just need to release what I have since I won’t have much time in the next month to work on it.
              • 5340
              • 1,624 Posts
              Nice one rfoster.

              Can you tell us more about it. Maybe I can help with those views. Unfortunately I’m not sure how they will work.

              I hope that Revo will remove my need for Codeigniter in my applications. As I get more and more familiar with modx I realize that at least half of the things done with codeigniter could have been done with modx(at least on the frontend).
                • 29774
                • 386 Posts
                Specifically I want to finish implementing a feature to use MODx templates as CodeIgnitor views. 
                


                Now that really would be amazing! I can’t wait grin
                  Snippets: GoogleMap | FileDetails | Related Plugin: SSL
                  • 24935
                  • 160 Posts
                  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.
                    • 9207 ☆ A M B ☆
                    • 2,475 Posts
                    This is brilliant! Thanks for sharing! Bookmarked!

                    One question... couldn’t the MODx related tasks be installed as custom CI libraries or helpers? E.g. the function to load a MODx template could be easily written in CI to fetch a particular row out of the MODx database table... saving it as a helper would make it easily available to any controller that needed it.

                    Or... I also wonder if you couldn’t do something similar that instantiated a new MODx object within a CI library or helper, then just use the same MODx API stuff within that object right inline with your CI controller or model code.

                    I wonder if you couldn’t make fewer edits to CI and make the router react just to GET commands, then somehow install a CI Snippet that acts as a CI application. E.g. if you have a page for books in your MODx site: yoursite.com/books -- and on that page you have a Snippet that passes a default controller to a CI "books" application, then you could manipulate your CI app using standard GET parameters, e.g. ?action=view_single_book&id=123

                    Then your CI controller could contain something like this (TOTALLY UNTESTED):
                    // CI Controller code:
                    	function view_single_book($id) {
                    		$this->load->database();
                    		$this->db->where('book_id', $id);
                    		$query = $this->db->get('books');
                    		$data = $query->row_array();
                    		// The following could be in a CI helper
                    		include_once($base_path."manager/includes/document.parser.class.inc.php");
                    		$modx = new DocumentParser;
                    // OR, if this is for sure called from a MODx snippet, just grab the parent instance of the $modx object:
                    		global $modx;
                    // WHAT NEXT?  How to fetch a template and render it?
                    //		$output .= $modx->parseChunk('recordList', $chunkArr, '[+', '+]');
                    
                    		print $output;
                    	
                    	}



                    I don’t know if this has a place in Revolution or not... I’m waiting for Jason to weigh in. xPDO is an ORM, and Revo has a much more developed API...

                    The main reason I’m looking at this very seriously at the moment is I have to connect with an Oracle database, and CodeIgniter’s active record API would allow for that.
                      • 29774
                      • 386 Posts
                      This really is rather brilliant, thank you! I’m going to be starting on a new CI project shortly - an extranet for an existing modx site - and it will be so useful to be able to pass data into modx pages. Regarding having CI pages with no corresponding modx page also pass through the parser - that would be the icing on the cake smiley
                        Snippets: GoogleMap | FileDetails | Related Plugin: SSL