Welcome Guest, Not a member yet? Register   Sign In
What is best structure for a big application?
#1

[eluser]Edemilson Lima[/eluser]
I still didn't figured out how to better define the structure of an application with Code Igniter... Before I was used to call PHP scripts within PHP scripts, using includes or requires. By this way, the first script loads the website main template and the sub scripts loads sub templates that are the blocks inside. For example, the main template have a header, an empty space and the footer. This empty space is then filled with a sub template, which can be the home or another sub page. Also the sub templates can have empty spaces that are filled with the contents.

Personally, I don't like to separate the header from the footer in different files, because if you open them in Dreamweaver, they will be unvalid HTML code. The header will not have closing tags and the footer will miss the opening tags. So, I like to put everything into the same file, and then inject the content using PHP include or require. By this way, I don't need to load the main template every time, in every sub page. The content is changed only changing few variables, which points to the filenames that will be loaded. So, PHP do the task automatically. In the sub pages I don't need to worry about headers and footers, they will be already there.

With CI, I got this placing a "$this->load->view($file);" into the main view. But this only allow me to load views inside views, not controllers inside controllers. When I do load a view inside another view, how do I generate dynamic content for the sub views?

Looking at the blog demo video, I understood that I will need to build the header and the footer in each function. Isn't there another better way to do that? I would like to see how is a big website, with lots of nested views was done with CI. Does somebody here know where can I download a sample?
#2

[eluser]xwero[/eluser]
You don't like to put the header and footer in different files but you are going to use the load->view method to load the header and footer ???

Anyway the easiest solution to have a layout that can load anything you want in it is creating a base page.
Code:
<?php echo $header.$content.$footer; ?>
This is the essential code. If you want to add html you can do it. Here you can have the header and footer html. If you want more columns you can add them too.

In your controllers you fill those variables with whatever you want to be displayed on the page.
Code:
function somepage()
{
   $data['header'] = $this->load->view('header','',true); // partial view file
   $content['text'] = $this->somemodel->text();
   $data['content'] = $this->load->view('content',$data,true); // partial view with dynamic data
   $data['footer'] = ''; // no footer for this page
   $this->load->view('basepage',$data);
}
#3

[eluser]Edemilson Lima[/eluser]
Quote:You don’t like to put the header and footer in different files but you are going to use the load->view method to load the header and footer ???

No, what I do is to load a base view, with the header and the footer in the same file. It is something like your base page example, but with the HMTL code for header and footer together.

Code:
$data['content'] = $this->load->view('content',$data,true); // partial view with dynamic data

Hmmmm... I have placed the load->view command inside the view file. Your example keep it in the controller, which is much better and give more control. Thank you for the tip! Smile

But, what the third parameter does? I did not found anything about it in the user guide. Does it tell the function to return the view instead of print it?

Well, now I have a more clear picture. First I need to build every sub page block and after pass them to my base view. So, I must call my base view in the end of each function that produces a sub page in my application.

Anyway, I will need to load the main view in each function. But at least this give me more flexibility (for example, to change the page title to something related to the sub page). May be is possible to reduce code duplication by creating functions to load the header and footer views. What do you think?
#4

[eluser]a tired machine[/eluser]
Edemilson Lima, check this out, it'll get you going in the right direction:
http://www.maestric.com/wiki/doku.php?id...r_template
#5

[eluser]Edemilson Lima[/eluser]
Thank you for the answer! Your template class is nice, but I don't know if it is exactly what I need. I will try to demonstrate my problem with some examples.

In the old days, I was used to load everything using include() or require(), like this:

index.php:
Code:
<?php
require('mylibrary/index.php'); // starts session, validades user, load helpers, etc.
if(!$section) $section='Home';
?>
<html>
<head>
<title>Web Site Title - <?=$section?></title>
<style rel="stylesheet" href="layout/mystyles.css" type="text/css" />
</head>
<body>
<div id="header">&lt;?php require('header.php'); ?&gt;</div>
<div id="lateral">&lt;?php
if(!$lateral) $lateral='categories';
require('lateral.php');
?&gt;</div>
<div id="contents">&lt;?php
if(!$contents) $contents='home.php';
require("{$contents}.php");
?&gt;</div>
<div id="footer">&lt;?php require('footer.php'); ?&gt;</div>
&lt;/body&gt;
&lt;/html&gt;

header.php:
Code:
<img src="layout/logomark.gif"><br />
&lt;?php require('menu.php'); ?&gt;

lateral.php:
Code:
blah blah blah<br />
&lt;?php require("{$lateral}.php"); ?&gt;

categories.php:
Code:
&lt;?php
// code to load a list of categories from a database and display it
?&gt;

home.php:
Code:
<div id="news">&lt;?php require('news.php'); ?&gt;</div>
<div id="offers">&lt;?php require('offers.php'); ?&gt;</div>

news.php:
Code:
&lt;?php
// code to load news from a database or RSS and display them
?&gt;

offers.php:
Code:
&lt;?php
// code to load offers from a database and display them
?&gt;

footer.php:
Code:
<div id="footer">Credits, some links, etc</div>

products.php:
Code:
&lt;?php
if($action=='add') {
  // code to include a new product
}
if($action=='update') {
  // code to update a product
}
if($action=='remove') {
  // code to remove a product from the database
}
if(!$action or $action=='list') {
  // code to show the product list
}
?&gt;

As you can see, when index.php is executed, it loads the blocks, which loads their sub blocks and so on. Everything is done automatically, as one is inside another. I don't need to rebuild every block at every request.

If I pass to the variable $content the value 'products', the index.php will include the 'products.php' instead of 'home.php'. In the case of product.php, I can choose which process will be executed, changing the $action variable in some way. I know, this is pure procedural, but it works.


Well, lets do it in the CodeIgniter way:

welcome.php:
Code:
&lt;?php
class Welcome extends Controller {

    function Welcome() {
        parent::Controller();
        $this->load->model('categories');
        $this->load->model('news');
        $this->load->model('offers');
    }

    function index() {
        $header['menu']=$this->load->view('menu_view','',true);

        $categories=$this->categories->list();
        $lateral['lateral']=$this->load->view('categories_view',$categories,true);

        $news=$this->model->news->list();
        $home['news']=$this->load->view('home_view',$news,true);

        $offers=$this->model->offers->list();
        $home['offers']=$this->load->view('offers_view',$offers,true);

        $data['section']='Home';
        $data['header']=$this->load->view('header_view',$header,true);
        $data['lateral']=$this->load->view('lateral_view',$lateral,true);
        $data['contents']=$this->load->view('home_view',$home,true);
        $data['footer']=$this->load->view('footer_view','',true);
        $this->load->view('main_view',$data);
    }
}
?&gt;

main_view:
Code:
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Web Site Title - &lt;?=$section?&gt;&lt;/title&gt;
&lt;style rel="stylesheet" href="layout/mystyles.css" type="text/css" /&gt;
&lt;/head&gt;
&lt;body&gt;
<div id="header">&lt;?=$header?&gt;</div>
<div id="lateral">&lt;?=$lateral?&gt;</div>
<div id="contents">&lt;?=$contents?&gt;</div>
<div id="footer">&lt;?=$footer?&gt;</div>
&lt;/body&gt;
&lt;/html&gt;

header_view:
Code:
<img src="layout/logomark.gif"><br />
&lt;?=$menu?&gt;

lateral_view:
Code:
blah blah blah<br />
&lt;?=$lateral?&gt;

home_view:
Code:
<div id="news">&lt;?=$news?&gt;</div>
<div id="offers">&lt;?=$offers?&gt;</div>

Well, I think is not necessary to show news_view, offers_view or footer_view here. Please continue reading the next post.
#6

[eluser]Edemilson Lima[/eluser]
The problem begin now:

products.php:
Code:
&lt;?php
class Products extends Controller {

    function Products() {
        parent::Controller();
        $this->load->helper('form');
        $this->load->model('categories');
        $this->load->model('products');
    }

    function index() {
        $header['menu']=$this->load->view('menu_view','',true);

        $categories=$this->categories->list();
        $lateral['lateral']=$this->load->view('categories_view',$categories,true);

        // generates a list of products with links to add, update or remove
        $products=$this->products->list();

        $data['section']='Products';
        $data['header']=$this->load->view('header_view',$header,true);
        $data['lateral']=$this->load->view('lateral_view',$lateral,true);
        $data['contents']=$this->load->view('products_view',$products,true);
        $data['footer']=$this->load->view('footer_view','',true);
        $this->load->view('main_view',$data);
    }

    function add() {
        $header['menu']=$this->load->view('menu_view','',true);

        // generates a list of categories for the lateral
        $categories=$this->categories->list();
        $lateral['lateral']=$this->load->view('categories_view',$categories,true);

        // gererates a form to include new products, etc.
        $product_data=product_add_function();

        $data['section']='Products - Include';
        $data['header']=$this->load->view('header_view',$header,true);
        $data['lateral']=$this->load->view('lateral_view',$lateral,true);
        $data['contents']=$this->load->view('product_include_view',$product_data,true);
        $data['footer']=$this->load->view('footer_view','',true);
        $this->load->view('main_view',$data);
    }

    function update($id) {
        $header['menu']=$this->load->view('menu_view','',true);

        $categories=$this->categories->list();
        $lateral['lateral']=$this->load->view('categories_view',$categories,true);

        // generates a form filled with a product data
        $product_data=product_update_function($id);

        $data['section']='Products - Update';
        $data['header']=$this->load->view('header_view',$header,true);
        $data['lateral']=$this->load->view('lateral_view',$lateral,true);
        $data['contents']=$this->load->view('product_update_view',$product_data,true);
        $data['footer']=$this->load->view('footer_view','',true);
        $this->load->view('main_view',$data);
    }

    function remove($id) {
        $header['menu']=$this->load->view('menu_view','',true);

        $categories=$this->categories->list();
        $lateral['lateral']=$this->load->view('categories_view',$categories,true);

        // ask to remove and deletes products from the database
        $product_data=product_remove_function($id);

        $data['section']='Products - Remove';
        $data['header']=$this->load->view('header_view',$header,true);
        $data['lateral']=$this->load->view('lateral_view',$lateral,true);
        $data['contents']=$this->load->view('product_remove_view',$product_data,true);
        $data['footer']=$this->load->view('footer_view','',true);
        $this->load->view('main_view',$data);
    }

}
?&gt;

As you can see, I must to reuse the same code to rebuild the entire web site in every class and every function... This is a lot of redundant code.

What am I missing? Should I do create functions to do this and put them as plug-ins? And then load these functions again, in every class and every function? Is there another way to do this more easily?

The main problem here is that I can load views inside of views, but not controllers inside of views, which in their turn can load another views and controllers.
#7

[eluser]pims[/eluser]
Did you take a look at this thread ? http://ellislab.com/forums/viewthread/44916/
This way you don't have to load each view within each controller, just load one "main controller" and pass the data to the views...
#8

[eluser]Edemilson Lima[/eluser]
Quite long thread... I find an example there which simplify the thing, but still is not the perfect world. The products.php controller could be:

Code:
&lt;?php
class Products extends Controller {

    function Products() {
        parent::Controller();
        $this->load->helper('form');
        $this->load->model('categories');
        $this->load->model('products');

        $header['menu']=$this->load->view('menu_view','',true);
        $categories=$this->model->categories->list();
        $lateral['lateral']=$this->load->view('categories_view',$categories,true);
        $this->data['header']=$this->load->view('header_view',$header,true);
        $this->data['lateral']=$this->load->view('lateral_view',$lateral,true);
        $this->data['footer']=$this->load->view('footer_view','',true);
    }

    function index() {
        // generates a list of products with links to add, update or remove
        $products=$this->model->product->list();
        $this->data['section']='Product List';
        $this->data['contents']=$this->load->view('products_view',$products,true);
        $this->load->view('main_view',$this->data);
    }

    function add() {
        // return a form to include new products, etc.
        $product_data=product_add_function();
        $this->data['section']='Product - Include';
        $this->data['contents']=$this->load->view('product_include_view',$product_data,true);
        $this->load->view('main_view',$this->data);
    }

    function update($id) {
        // generates a form filled with a product data
        $product_data=product_update_function($id);
        $this->data['section']='Product - Update';
        $this->data['contents']=$this->load->view('product_update_view',$product_data,true);
        $this->load->view('main_view',$this->data);
    }

    function remove($id) {
        // ask to remove and deletes products from the database
        $product_data=product_remove_function();
        $this->data['section']='Product - Remove';
        $this->data['contents']=$this->load->view('product_remove_view',$product_data,true);
        $this->load->view('main_view',$this->data);
    }

}
?&gt;

In this example, the common views be in the constructor and are passed to the main_view by $this->data variable.

Well, I could place these common views in a function and just load it everytime I need.

I take a brief look at the examples there, but what I really want (I guess) was a way to load controllers within views or load constructors instead. We could have something like:

Code:
$this->load->constructor('[folder/]file','function'[,$data][,true/false]);

Such method could load the file and execute the function, passing the optional $data array and print or return the output to the caller constructor or view. Loaded constructors could also load another views or constructors.

Well, I don't know the impact of this or even if it is possible, but I think it could solve this issue.
#9

[eluser]Pascal Kriete[/eluser]
I don't see why you can't do the stuff you used to do in php. You can call views from another view.

So your main view is something like this:
Code:
$this->load->view('menu_view');
$this->load->view('header_view');
$this->load->view('footer_view');

If any of those contain variables set them here.
Code:
function index() {
        // generates a list of products with links to add, update or remove
        $data['products']=$this->model->product_list();
        $data['categories']=$this->model->categories_list();
        $data['section']='Product List';
        $this->load->view('main_view',$data);   //Any data you pass in will be available to all views in the main view.
    }
#10

[eluser]Pascal Kriete[/eluser]
Scrap this...i have no idea how I managed to quote myself.




Theme © iAndrew 2016 - Forum software by © MyBB