Build a module : No tags

Even they are very useful, tags add one abstraction layer.
So for some complex module, it could be easier to not use tags.

This part will explain how to code one module frontend with a more classical approach, wherein controllers load views and output them.

What we want to do :

  • Add other methods to the main Demo module controller (demo.php)
  • Create other controllers for the demo module

Prepare the moduleTop of Page

Each module which has one one frontend (see config.php) has one URI part.

The default call to the module URL calls the index() method of the default module's controller.
For the Demo module, it is the method in the controller : /modules/Demo/controllers/demo.php

To be able to handle other controllers, we need to modify the module's route.

Modify the module's Route

  1. Open the file /modules/Demo/config/routes.php
  2. Edit it so it looks like :
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 

$route['default_controller'] = "demo";
$route[''] = 'demo/index';
$route['(.*)'] = "/$1";

What means this route config :

  1. The default controller for the module is "demo"
  2. If no controller is givven through the URL, the method index() from the controller "demo" will be used
  3. Every other URL call will be handled by the module's corresponding controller
In other words, if the corresponding controller exist, the following URLs can be handled by the module :
  • http://my_website.tld/demo/author
  • http://my_website.tld/demo/author/get_list
  • http://my_website.tld/demo/author/get/3
Remember the first part of the URL (here "demo") is always the module's URI :
http://my_website.tld/<module_uri>/<controller>/<method>/<param_1>/<param_2>

Create one module's controllerTop of Page

Create the file /modules/Demo/controllers/author.php :

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');


class Author extends Base_Controller
{
public function __construct()
{
parent::__construct();
}

public function index()
{
echo 'Author Controller > Index()';
}

public function get_list()
{
// This will outputs the author's list
echo 'Author Controller > List()';
}
}

Let's call this controller from the browser with the URLs :

http://my_website.tld/demo/author : Displays "Author Controller > Index()"
http://my_website.tld/demo/author/list : Displays "Author Controller > List()"
 

Display the author's listTop of Page

Adapt the controller

Modify the author's controller :

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');


class Author extends Base_Controller
{
public function __construct()
{
parent::__construct();

// Models
$this->load->model('demo_author_model', 'author_model', TRUE);
}

public function index()
{
echo 'Author Controller > Index()';
}

public function get_list()
{
$authors = $this->author_model->get_lang_list();

$this->template['authors'] = $authors;

$this->output('author_list');
}
}

We added :

  • The load of the model called "demo_author_model" in the constructor.
    We tells the loader that the module will be used in the code as "author_model"
  • The function get_list(), which gets the authors and outputs the view "author_list".

Create the view "author_list"

Create the file : /modules/demo/views/author_list.php :

<?php
/**
* Ionize Author Demo Module
* Frontend Authors List view
*
* Receives :
* $authors : Array of authors
*/
?>

<ul>
<?php foreach($authors as $author): ?>
<li>
<?php echo $author['name'] ?>
</li>
<?php endforeach ;?>
</ul>

One call to the URL http://my_website.tld/demo/author/get_list displays the authors list.

We're now able to build as much controllers as we need for our modules !

The module has the same behavior than one standard CodeIgniter app : As many controllers you wish displaying as an views you wish. 

But...
We do not have the website's design, and of course the navigation menu isn't displayed !
This job is done by the Tag Manager of ionize and no easy lib gives today access to the same functionalities (this will certainly be developed in the future).  

One solution to this problem is to create just one tag which will outputs the first view of the author module.
Other views of the module will then be loaded through Ajax.

At least... one tagTop of Page

Purpose :

  • Create one tag to load through the standard CI way one main front view for the module
  • Make Ajax calls to load other controllers of the module

Create the "main" tag

Open the file /modules/demo/librairies/demo_tags.php :

public static $tag_definitions = array
(
// ...
// Add this line :
"demo:main" => "tag_demo_main",
);

Create the method tag_main() :

  /**
* Loads the main Front module's view
* Because the parent tag (index) is expanded, the result of this method will be displayed
*
* @param FTL_Binding $tag
*
* @return mixed
*/
public static function tag_demo_main(FTL_Binding $tag)
{
$view = self::$ci->load->view('index', '', TRUE);

return $view;
}

Create the called index view :

Create the file /modules/demo/views/index.php :

<?php
/**
* Ionize Author Demo Module
* Frontend Main view
*
* Loaded by the tag : <ion:demo:main />
*
* Receives : no vars
*/
?>

<!-- Container for the Authors List -->
<div id="moduleDemoAuthorList"></div>


<script type="text/javascript">

// Controller URL to call
var url = 'demo/author/get_list';

// Ajax request
jQuery.ajax(
url,
{
type:'post',
// Get the result (the view HTML string)
// and display it in the Authors List container
success: function(result)
{
$('#moduleDemoAuthorList').html(result);
}
}
);

</script>

Of course the javascript part should be located in one script and one JS class to be really clean...

Use this tag in one page of the website

To use this tag in one view of the website :

  1. Create one view and link it to the page of your choice,
  2. Call the tag we just created in this view : <ion:demo:main />

Example (we used the home_page view of the "foundation" theme for this example) :

<ion:partial view="header" />

<!-- ... -->

<div class="row">
<div class="eight columns">

<ion:demo:main />

</div>
</div>

<!-- ... -->

<ion:partial view="header" />

Going further

In this example, we saw that only one main tag is needed to display the main view of the module.

All other calls can be done through Ajax.

The <ion:demo:main /> tag could display one submenu, and each item of this submenu could call one controller of the module.