3

This is a continuation of our basic tutorial on MVC Framework. In this section, we will be creating the template files for both the TBS and the Smarty template engines.

The recap
In part one, we have created application controllers, models, and the one and only lone View class. Once again, please allow me to present few segments of those Classes here.

Main Controller We will use this as our example. All of our application controllers have the method called index(). If we can recall from part one, we made the parent controller as an abstract class with an abstract method called index(). Remember? By doing so, all of our application controllers must have a method with the same name as the abstract method of the parent. As I have already mentioned that the only reason in doing this is to serve like a training wheel. We don't want our application to wonder off the patterns that we want our application to take.

public function index(){
    $this->view->use_tbs($this->main_model->Content(),FileHelper::parse_menu(),'index',FALSE);
    $this->view->use_smarty($this->main_model->Content(),null,'index',FALSE);
}

Let us take those two items inside the method index() above. They may appear odd and with no to little relevance to unsuspecting eyes, but those two lines of codes are the logic carriers/converters. In other words, after the model or other methods in the controllers performed all of their business logic responsibilities, the resultants or the products of those processes must be delivered to the view. The view will then take these products and process it to become a part of what we all know as presentation logic. Isn't it this is the ultimate goal of web develpment and all we want is to deliver the response to the users? When I was in 11th grade, I don't even know the proper terminologies for these type of logic, but I was fully aware about the importance of separating these two.

Simple Elaboration with retrace
Let's retrace this particular line of codes. Please do not underestimate the importance of this. This is the only star gate between our application and the outside world. Of course, the simpleMvc class is the landing area, but the point where the business logic is transform into presentation logic is triggered here. If you watched the Sci-Fi movie entitled Star Gate, this system kind of work like that. First you need to dial the access codes (router), and then if the codes are valid the vortex will open up (landing page), and then you will be sucked and converted into pexilized form ( controllers and model), and finally you will be reassembled to your orignal form as you arrived to your final destination ( View and Template engine).

$this->view->use_tbs($this->main_model->Content(),FileHelper::parse_menu(),'index',FALSE);

This is the instance of our View class

 $this->view

This is the instance of our view class utilizing its method to use TBS template engine

 $this->view->use_tbs

These are the arguments for the method use_tbs().

 ($this->main_model->Content(),FileHelper::parse_menu(),'index',FALSE);

The data output from the Business logic of the main model are introduced to the View model in this form

 $this->main_model->Content()

We added another data from our application helper class called FileHelper.

 FileHelper::parse_menu()

We provide the template file name to where data can be viewed by the users as a response to their requests.

'index'

and this one, is a switch if we want our template file to be cached or not.

FALSE

Template files for TBS and Smarty
First, we create our header template file. I would like to remind you that this is the very basics of implmenting template engine and I choose not to fully cover the subjects about template inhiretance.

Filename: header.tpl Remember in our Set Class? We assigned the template extensions as .tpl.

<!DOCTYPE HTML>
<html>
<head>
<title></title>
<script type="text/javascript" src="http://localhost/tinymce/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
    selector: "textarea"
 });
</script>

<link href="http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<link href="http://localhost/mvctheme/css/style.css" rel="stylesheet">
</head>
<body>

very typical and pretty much nothing in it but the TinyMCE. Lets create the footer

<br/>
<div class="copy">
{% content.copyright %}
</div>
<br/>
</body>
</html>

Wow look at that, we now have something. I want you to focus on this type of syntax

{% content.copyright %}

All data from the view are derived from either the controller or the model and the View class assigned them into an array. In this particular example, the view use_tbs() method merged all the data into a single array called content. Let's take a look at the code segment from the View class

$this->tbs->MergeBlock('content',$data);

The same argument was use in the use_smarty assign method.. please take a look the codes below.

     $this->smarty->assign('content', $data);
     $this->smarty->assign('menu',FileHelper::parse_menu());

The only difference between the smarty and the TBS is that in Smarty, I we can call the assign method anywhere where an instance of of Smarty object is present. While in TBS, you will need to follow a simple convention like this

    $data[] = $someArray();

To better understand how the template engine use the merged function or assign function, let's pretend we are writing the application in procedural form. The above codes is pretty much or closely equivalent to this.

    $content = array('data'=>array(
                     'copyright'=>$copyright,
                     'title'=>$title,
                      'content'=>$content
                                     ));

So, don't be confused with all of these derivatives that are thrown into the mixed. What we should be thankful and must appreciate is the ability to write our arrays in DOT ( dot) notation. e.g. content.copyright gives us the copyright value.

I hope I breakdown pretty much all of the introductory parts an pieces of our application as it applies to the template engine. Let us move on to the index.tpl for both TBS and Smarty.

TBS Index.tpl file

{% onload;file=header.tpl %}

<div class="content">
<h2> This is index.tpl file generated by TBS</h2>
Article Count: {% content.# %}
<div>
<h3 class="title"><a class="title" href="{% content.url %}">{% content.title;block=div %}</a></h3>

{% content.content %}


{% content.poster %}

</div>

<br/>
{% onload;file=footer.tpl %}

Smarty index.tpl file

{% include file="mvctheme/theme/header.tpl"  menu=$menu show="false" %}


<div class="content">
<h2> This is index.tpl file generated by Smarty</h2>

<ul >
{% section name=item loop=$content %}
<li>
<h3 class="title"><a class="title" href="{% $content[item].url|replace:' ':'' %}">{% $content[item].title %}</a></h3>
{% $content[item].content %}... <a class="more" href="{% $content[item].url|replace:' ':'' %}">read more</a>
<br/>
Posted by: {% $content[item].poster %}
</li>
{% /section %}
{% *onload;file=footer.tpl* %}

Let us take a look at the template files called index.tpl above. Notice how pretty it is? I mean common now, everyone could not disagree with me on how pretty the template file above. It is so pretty and safe from all types of harms and danger. I can literally delete this and I have no problem rewritting it. There is nothing in it that cannot be rewrite. However, try doing it on your controller file or the model file.

Now, let us talk about the presented codes above. Not the HTML tags, but the TBS syntax.

In TBS, this is how we include other template files. We are including the header.tpl file and the footer.tpl

    {% onload;file=header.tpl %}

    <!-- The rest of the codes here -->

    {% onload;file=footer.tpl %}

In Smarty, this is how we include other template files. It will function and work as the above

{% include file="mvctheme/theme/header.tpl"  menu=$menu show="false" %}

  <!-- The rest of the codes here -->

 {% include file="mvctheme/theme/footer.tpl" %} 

What is ever worth mentioning between these two template engine is the ability of Smarty to add an argument that needs to be evaluated in the included template file. I could discuss more about this topic, but it will confuse the readers. So, let us set those possible divergence aside for now.

Remember the data array assigned as content on the tbs instance of the View? Here they are;

TBS iteration of the content array

{% content.title;block=div %}

Don't make the code confuse you. It all means is that show the title from the content array and loop the content array inside the div. Please take a look at our index.tpl above. Noticed that all of the items affixed with content are inside the div? So, if want this iteration to happen inside the <li>, what should we put in the block value? block=li, you said? Perfect, now you are getting into this template engine thing.

Smarty iteration of the content array

<ul >
{% section name=item loop=$content %}
<li>
<h3 class="title"><a class="title" href="{% $content[item].url|replace:' ':'' %}">{% $content[item].title %}</a></h3>
{% $content[item].content %}... <a class="more" href="{% $content[item].url|replace:' ':'' %}">read more</a>
<br/>
Posted by: {% $content[item].poster %}
</li>
{% /section %}

In smarty, we can loop an array in many different ways. One is using the section iteration function. First I created a section and define the name and define which array it has to loop. The above codes is a perfect demonstration of how the dot notation can be very useful. Raw PHP just don't have the function that will allow us to use dot notation in handling arrays. I also added a demonstration on how to use string manipulation function in Smarty e.g. replace:' ':'' which is nothing but intended to function like trim(). We can also use foreach in Smarty, if that is the function offering the most convinience for the project at hand. However, we can use the section in simple or multi-dimensional array. For more complex application, I strongly recommends the use of the section function. But if you are going to insert any iteration control or arguments before the end of the loop, you should use foreach function instead, because it is a lot easier to interupt the iteration in foreach loop.

In part One, I mentioned that I might add another templating function that will use plain PHP. I guess I am not too lazy today, so let's do it. As we all know, template engine is pretty much the most criticized innovation in Web develpment. Some says, PHP is already a template engine itself and does not need any type of template engine that suck the life of your server. So, if you are one of those people who thinks PHP is still in the same category as a lower level programming language of the past, here is a sample of using the raw PHP as a template engine.

Remember in part one, where I said that I am using the article class as a demonstration for bypassing the model pattern? Let's use the very same class in demonstrating how to use PHP as a template engine. First we need to make adjustments on the article class.

modified article controller class. This time we will be using the model pattern, but we are not going to use any template engine ONLY PHP.

class Article extends Controller{

        public function __construct(){
            parent::__construct();
            $this->article_model = Init_Object::get_Object('Article_Model');
            }

        public function index(){

        $ar_data = $this->article_model->content();
        return($this->view->set_content($ar_data,$this->settings['no_tbs']));

    }
}

Noticed, there are no instances of view->use_tbs and view->use_smarty? Instead, this particular controller will be accessing the output from the Article model and then pass it on to the view class, and lastly assigned the output to a PHP file named simplemvc_view.php. If you are going to experiment with this kind of approach, make sure the php template file must be assigned for every controller that you will have to make.

simplemvc_view.php was also defined in our class set as. I am aware that I made a typo on part one and listed it as mvcthem/simplemvc_vew.

'no_tbs' => 'mvctheme/simplemvc_view',

Here are the codes for the above template file

<!DOCTYPE HTML>
<html>
<head>
<title></title>

<script type="text/javascript" src="http://localhost/tinymce/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
    selector: "textarea"
 });
</script>

<link href="http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<link href="http://localhost/mvctheme/css/style.css" rel="stylesheet">
</head>
<body>


<div class="content">
<h2> This is mvctheme/simplemvc_view.php file generated by PHP serving as a template file</h2>

<ul>
<?php

    foreach($content as $item){

        echo '<h3 class="title"><a class="title" href="../'.(trim($item['url'])).'">'.$item['title'].'</a></h3>';
        echo $item['content'].'...  <a class="more" href="../'.(trim($item['url'])).'">read more</a><br/>';
        echo 'Poster : '.$item['poster'].'<br/>';



    }
    //print_r($content);

    unset($content);
?>
</ul>
</div>
</body>
</html>  

That's pretty much about templating for our simple MVC. You can always do it with the options you are the most comfortable with.

Below is the screenshots of how the finished framework output will look like

The mainpage will all look the same on all three template files, except for the message describing which template engine is generating the file. For the article controller above the url can be accessed as localhost/simplemvc.php/article/. Url for both Smarty and TBS localhost/simplemvc.php/.

71b9707e726c71ec674bdaa254e2df5e

The output of the add controller localhost/simplemvc.php/add/. This page will allow you to add an article and save it as a text file. I also added the TinyMCE to make it look interesting

3ef084b3ab2b7ba7c51581934b040144

Lastly, this is the output of our read controller. The url is localhost/simplemvc.php/read/

7ad5f2f2720d1848e405e36a3ff75208

Special thanks and credits for the CSS and others: Dynamic drive for the top menu and TinyMCE for the textarea WYSIWYG.

How to set for the framework to use the Smarty Engine?

 /* select template engine to use */
'use_template' => TRUE, // always set to true
'use_smarty'=> TRUE,
'use_tbs_eng'=> FALSE,
'use_twig'=>FALSE,

For TBS, just set use_smarty to FALSE adn use_tbs_eng to TRUE, BUT never TRUE on BOTH.

I hope this tutorial have provided you something valuable. If not, my sincere apology for the lost of your valuable time.

Which Framework Should I use?
After becoming an expert with the operation of MVC pattern in PHP, and you are now looking for what open source PHP MVC framework to use. My answer to this question is simple. Try starting with CI and try creating a simple application similar to the ones we created in this tutorial. Once you finished and tested your application written in CI, jumped into the new framework. Something that is different than the rest of all frameworks. Frameworks that are created by people who are dedicated to solve problems using the latest innovations. I mean, people who can think outside the box and can view the outside the box environment as not a violation of the so called "Why reinvent the wheel" doctrine. Most people have a complete different interpretation of this term. They assumed that we should follow a certain line blindfolded. To me this is just a reason for stopping the younger generations to innovate. They don't have that same crapola when Mr. Jobs and Mr. Gates were growing up. Only in my generation where people would tell me that I cannot do this and do other things that I think can solve something. Overtime, people have begun to think like they are computers, but this is a really bad evolution inside the human brains. Computer are not smart, they are just fast and can do things redundantly with amazing speed.

To make this paragraph short, try looking at the Laravel, Kohana, and FuelPHP.

Which Framework I like
I like all of them, but there are three frameworks that I really like the most.
1. CI
2. Kohana and Symfony2
3. FuelPHP

I listed FuelPHP as the third framework that I like. However, if I will be writting a new application today based on PHP MVC Framework, I will definitely build it on FuelPHP.

What makes FuelPHP the right choice?
1. It is pretty light
2. It was developed by some people who contributed in the develpment of the early CI
3. It is so easy to create a new application throught the use of Oil CLI.
4. It has an excellent migration.
5. Oil can generate all the basic files needed for your new application.

The most important About FuelPHP is that it is one of the only two frameworks that are HMVC (Hierarchical model–view–controller ). So, if you want to run ahead of many people, this is the one you need to learn. The other HMVC framework is Kohana. Both have a really good ORM, but I am heavily leaning towards FuelPHP. I always love being with the underdog.

How does the regular MVC framework compared to HMVC?
The answer is simple. If you think CI can still compete with other well maintained frameworks, inspite of inability of its founder to provide upgrade, CI will look like a Dinasour compared to HMVC like the FuelPHP.

Things I don't Like About Framework?
I don't like the autoloader. The reason I don't like the autoloading is that the application needs to include all of the files at once. So in other words , even if your application is at idle, it has to include all of the files for the application. What I have been experimenting in the past is a reponsible loading as requested.

Here is the code I been using for experimenting the responsible loading of the controller and model files. Let say we have three controller and model files called main, read, and add. Now, I don't want these files to be included by the bootstrap at all times, even when they are not needed.

We create a simple array for all the controllers and models for our application. We just add them as we write them

$app_files = array(
                   'MainController'=>'index',
                   'ReadController'=>'read',
                   'AddController'=>'add',
                   'MainModel'=>'index',
                   'ReadModel'=>'read',
                   'AddModel'=>'add'
                   );

We can now use a simple router to find if the user requests have an existing controller. Can be simple as this

$controller = Route::route();
if(in_array($controller, $app_files) !== false){

$LoadController = Use_Class::loadController($controller,$pagesArray);

## we include the controller file 
Use_Class::autoload($LoadController[0]);

## we create an instance or object of the controller.
## the instance for the view and the model are created inside the controller.
$object = Ini_object::instance($LoadController[1]);
$object->index();

}

By using the above approach, the application will only be carrying the load of system controller, model, and maybe a few libraries. That is a lot of relief that carrying the entire system and application files.

That will conclude my tutorial series on the basics of MVC Framework. I will attached the Zip file for this tutorial sometime later. I was not able to create the zipped file.

Thanks for reading and make sure to come back and check for the zip file later.

5
Contributors
9
Replies
98
Views
3 Years
Discussion Span
Last Post by Geetha_1
0

The entire MVC framework covered in this tutorial is located in just ONE page called index.php. If you will not be using the .htaccess below, use the simplemvc.php. The framework itself is lighter than the template engine files. In fact, the Framework is less than 20KB. While smarty files are more than 1.5MB.

Update:
This morning while creating a zip file, I was not aware that my older brother in Silicon Valley was reading this tutorial to check if I can really screw these things up ( Just Kidding) :). Am I even allowed to say those words? Anyways, he suggested that I should also cover how to pretify the urls of our simple framework.

So, what my brother Mihael was telling me or challenging me to make right now, this very last seconds before I upload the source is to change these urls

simplemvc.php/add/
simplemvc.php/read/
simplemvc.php/article/
simplemvc.php/main/

to something like this

simplemvc/add/
simplemvc/read/
simplemvc/article/
simplemvc/main/

The thing is that I will be leaving for school in like 45 minutes from now. So, I need to think really fast . I came up with this simple .htaccess file directives.

I am not sure this will work accross the board, but I have my fingers crossed hoping it will work. If not let me know and I will test it tonight.

RewriteEngine On
Options -Indexes

RewriteBase /simplemvc/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

The above routing directives should be able to redirect requests similar to the one found in CI.

Installation Instructions
I created this entire MVC framework in just ONE file called index.php ( with .htaccess). simplemvc.php for no .htaccess implementation.

  1. Download and Unzipped attached zipped file.
  2. Move the simplemvc directory to your xampp's htdocs directory or public directory accessible as localhost.
  3. Direct your browser to localhost/simplemvc/main/

If you want to experiment without the help of .htaccess rerouting, you can rename the .htaccess file to something else, and then use this type of url localhost/simplemvc.php/, localhost/simplemvc.php/add/, /read/, /article/.

Inside the mvctheme directory are template files for TBS (tbs) and Smarty (theme). For both template engines there is a file called form.tpl. The action processor is defined from the Add controller as $processor.

<form method="post" action="{% $processor %}" id="add">

Something for you to experiment.
Create a new MVC Classes for editing the article.
Create a new MVC Classes for deleting an article.
Use the Add Controller as a guide. Use the add.tpl and form.tpl files as a guide for writing a template files.

That's it and thank you very much for reading. I apologize if I was not able to meet the standard expected from a tutorial. I hope I can do better next time.

Heading for School and I am out here...........

Edited by veedeoo: info added.

0

v can you further explain the differences between hmvc and mvc?

Second, you talk about moving onto newer frameworks. Now I've started and got to grips with ci I feel very very angst at having to relearn a new framework. Especially as I've got to now rewrite a lot of existing code. Laravel seems very tempting but alas I can't bring myself to learn more stuff when ci seems to do the job nicely - plus it supports older versions of PHP which some hosts/web servers only have.

What incentives would you give for long standing ci to learn yet another framework?

0

MVC is the method of operation or patterns found in CI, Symfony2, Laravel, maybe Cake. The only HMVC framework that were evaluated to function as HMVC framework are Kohana and FuelPHP. In the case of FuelPHP, it can function as MVC and HMVC at the same time. Both Kohana and FuelPHP were developed from the early CodeIgniter. I suspect, that the oil in FuelPHP was inspired by the CI's migration.

HMVC stands for Hierarchical Model–View–Controller. Now, please allow me to explain the difference..

In MVC, we make our application's controller like this.

class mycontroller extends baseController(){

    public function index($request){
        $this->load->model('my_model');
        $data['content1'] = $this->my_model->set_index();
        $this->load->view($templateName, $data);

        }
    public function another_request($request2){
            $this->load->model('another_model');
        $data['content2'] = $this->another_model->set_another();
        $this->load->view($templateName,$data);
        }

The above is pretty much confined into this tight one triad pattern. The limitation is that most Controller in a much bigger application is responsible for initialization of the model and view objects. Although the above still demonstates the separation of concerns, the controller above can be grew exponentially and will eventually meet its limit, then the application will fail.

In HMVC design pattern, the application's separation of concerns are expressed or fullfilled in terms of creating parent module and many sub-modules with their own controller-Model-View.

If we convert our simple our controller above to HMVC, we would now have TWO sub-modules called index and another requests with their very own model and view. If we translate this design into a diagramm, it will appear like this

e10714081f3a8d805a91412e306549eb

By implementing HMVC design patterns to the above basic MVC triad, our code will be something like this

 class mycontroller extends baseController(){

    public function index($request){

        require_once('modules/sub_dir/appname/controllers/'.$request'.php');

        $this->load->sub_controller($request);

        }
    public function another_request($request2){
            require_once('modules/sub_dir/appname/controllers/'.$request'.php');
         $this->load->sub_controller($request2);
        }

Noticed the two new controllers made out from two methods? These two new controllers can have their own model and view.

By creating modules for each request, the application is releived from many requests being served by ony one triad.

The above diagram was for HMVC with template engine. The connections between the views and the template engines are only for the purpose of CSS, JS, parent template inheritance,template cache, and template compiler.

If you want to experiment with HMVC for CI, you can download this .

Edited by veedeoo: info added.

0

Thank you for that great explanation. So effectively what you are saying is that HMVC allows the controllers to be further separated allowing more fine grained control.

I guess my application that I'm building now might not see the benefits of such further separation... Yet.

I'm also finding it difficult to navigate (flow control) with just with the MVC pattern, this further separation of 'sub controllers' would add another level of abstraction.

Can you explain how, using HMVC, you manage to keep the flow clear in your head or for other developers.

Or is it necessary to always draw a flow chart like the one above. Does this extra level of abstraction hinder of help the developer?

Looking forward to your answers.

0

Hi Iamthwee,

Yes, the further separation of sub controllers would add another level of abstraction. This will allow the developers to be able to control their application like a micro-manager . I have known people who would really cut many corners, but later on found out that they cannot easily get out of the problems created by the bloated controllers.

Here is a simple scenario, let us think of a website having 10000 hits for every 5 minutes and all of these hits are routed to a page. The registration, login, and user's account management are all served by just one controller.

Below is a simple controller commonly found on the web. Amazingly, some MVC books are also trying to propagate the same to their readers.

<?php

    Class Users extends Base_controller{

        public function __construct(){
            parent::__construct();
            }

            public function register_user(){
                $data['form_data'] = $this->model->validate_form();
                $this->load_view('load_form',$data);
                }

            public function validate_login(){
                $data['validation_err'] = $this->model->validate_user();
                $this->load_view('load_account_page',$data);
                }

            public function load_user_dashboard(){
                $data['dash'] = $this->model->get_user_account();
                $this->load_view('user_dashboard',$data);
                }

            public function load_content(){
                $data['content'] = $this->model->get_content();
                $this->load_view('main_content',$data);
                }
            /*
            * they normally add more without limits and without evaluation of any possible consequences.
            */

                }

Let us imagine that a 5th are requesting /yourApplication/register_user/, 2/5 are logging in and will then eventually requesting for their dashboards, the remaining 2/5 just want to read the website contents. Imagine how much stress this particular controller must under-take to serve simultaneus requests from 10000 users. How about the sessions generated behind the scene? How can we solve this problem in a real world application? Even my own government's multi-billion dollar website, were not prepared for a 1 million simultaneous requests .

To alleviate the stress load, we can rewrite the application to HMVC pattern, by creating more sub-modules relevant to login, registration, and content delivery. We must always put into consideration how much stress we put on our controllers in handling sessions.

So, in my particular example above, I would use redirect instead of include to make sure users are served depending on the purpose of their visit.

HMVC design pattern is really easy to remember. All we have to do is to think of it as a triad or like a pyramid of which the controller is on top and the view and model being in the bottom. If per requirements HMVC is required by specific application, then we will just have to expand the controller to have its own triad.

Normally, I would design my database first. Once I am happy with my database design, I would evaluate the design in Oracle's MySQL workbench by running many different types of queries and record the time spent. After database testing, I would write all the models responsible for database queries and finally the controllers are written, followed by the creation of the view.

0

The registration, login, and user's account management are all served by just one controller.

In that case why not create separate controllers. Have a registration controller, login controller, dashboard controller?

Would this not guarantee the same effect without having to divide the controller up with the HMVC pattern?

At the moment this is what I am doing... Can you please explain this? And why this is considered bad.

Edited by iamthwee

0

For my opinion and for our practice, we used one controller for a not so complicated program though for much bigger sites we simply used different controllers and different models, our objective for this is a much cleaner code and simply much easier for debugging.

0

This blog is impressive and informative.It clearly explains about the concept and its techniques.Thanks for sharing this information.Please update this type of
information

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.