Codeigniter - creating views Q - php

I am not too technical but wanted to know since my tech team is implementing this way:
Do we need to create a 'controller' file for each set of views that we need to call on the website OR can we control ALL the views from 1 controller? It seems like more work to have multiple controllers control all the views. I would like to have 1 controller call all the views to cut down on project time but not sure if this is possible or even a good practice?

This is neither good nor bad practice. All that matters is that your code is clear and well structured. After that, Code Igniter gives you lots of flexibility on how you use controllers and views. Personally, I tend to use one view per action (so a controller often controls several views).

Yes, it's possibile; you can easily test it yourself:
class Customcontroller extends CI_Controller {
function index()
{
$data['test'] = 'test';
$this->load->view('header', $data);
$this->load->view('body');
$this->load->view('footer');
}
}
You'll notice that doing this way $data will be available to all views, even if not passed individually while loaded.
I find it a nice way to building pages, using views as blocks. So, you can also present views according to some constraints:
$this->load->view('header');
if($this->form_validation->run() == FALSE)
{
$this->load->view('display_form');
}
else
{
$this->load->view('form_sent');
}
$this->load->view('footer');
for example.
Although MVC stands for Model-View-Controller, and suggest a one-to-one correlation, using different views for a same controller I doubt it can be considered "bad practice"; as already being said, there's no really an ideal way of doing this, what's important is keeping the logic separated and making your code well-structured and organized, especially when working in a team.

It really depends on what your controller is supposed to do. If all you want to do is show blog posts or content pages, for example, you can just use one controller called 'blog' or 'pages'. Controllers handle the logic. If you have many features you'd like to run (such as accounts, events, photos, etc.) it's usually always wise to give each their own controller so they can handle operations suitably with their model.
If you use frameworks like CodeIgniter, you can use their routes feature to automatically route certain URLs through a particular controller. For example, if you wanted pages to have a URL of http://example.com/page/page-title - you'd need to use this line in your routes config file:
$route['page/(:any)'] = 'page/get_page';
Any URI request that contains 'page' will be handled by the 'page' controller and the 'get_page' method. You can they grab the page-title or page-id by using $this->uri->segment(2).

I will have a single controller using multiple views. Here is how. My webpages have common header, footer and navigational structure, so these views will be common to all the web page calls hence a controller may inherit a method that takes content and assembles a page using header/footer/common views. For displaying grids I may have a common grid view that I can keep using in multiple controllers for displaying tabular data. Different use cases can reuse some views. So it makes sense that you can use multiple views within one controller.

codeigniter itself does not restrict you on how many controllers you use.
but as a basic idea, i tend to seperate controllers into modules.
for example, if your site have a front end and a back end, i would separate them, so i got 2 controllers (each with their own views).
this way, if you have more than 1 person working on the site, you can assign 1 person with the front end, and the other with the back end.
further more, you can break them apart into smaller modules. for example, in the front end, there is a home page and an article page (certainly you have different views for those), you can also break them down if you feel they are complex enough. but if you think they are simple, then it is fine if you use 1 controller for those views.

Related

How should I divide my code using CodeIgniter?

I have searched the web and found only styling code posts. I want to write site using Code Igniter and I wonder how should I maintain my code.
For example:
Should I use one class for static pages and methods for each page or separate file for every static page. Should I use the same file to load dynamic pages or different one?
Can I use some common code and include it automatically to every class?
How can I have lets say header_view footer_view etc and then just load->view('whatever') and footer, header and other files would load automatically. Maybe there is better way to do that?
In generall what are the best practices when coding using CodeIgniter.
You can use one single class for static pages (and use one method for each page).
You can use the same one to load dynamic pages, but it is better IMO to load them with a separate class. It will be easier to maintain later.
Using common code: You can always override the CI_Controller with your own, and instantiating controllers from yours. Here is an example about how to do it.
You can load multiple views in a single controller function. A view doesn't have to be a full html document. You can also load the same view multiple times (for example in a loop).
Best practices: CodeIgniter is an MVC framework. IMO, MVC is a best practice. Always use the framework's documented features if they are suitable for what you want to achieve (CodeIgniter's documentation is very good. That link is momentarily offline, so please try this one).
Codeigniter is a MVC based framework, MVC is basically used for organizing your code, so at last its up to you how you are going to use it so ease you on the long term.
Basically when I design large projects in codeigniter I tried to to make unit of functionality at one place lets take example of any simple users, messages based project.
I tried to make functionality by grouping main topics, in this example user will be a controller, in that controller there will be methods like login, register, edit, listing, forgot_password now I'll create single model with all the methods which will give data for these above methods. by using this methods our urls will be also meaningfull like /user/login, /user/register etc
like that if its messages I will create controller message and add all related methods in it so that my related functionality will be in a single group.
as far as the question of static pages you can also group them in a single controller if they can be a part of group.
you can also use codeigniter's caching technique for static pages so that your pages will load faster

What could I do to improve my MVC?

I'm thinking of re-working my MVC before I get to far along with it. At the moment it uses a sinle controller which takes the user input and determines the model. The model has maby differ methods which I call actions, because one is called automatically. The model loads its view file, which again holds many different methods. The model can set properties which can be used in the view. Then the controller calls th template classwhich parses the output for display.
Is this the bst way to do it?
Or should each different part (news, contact, about) have its own controller, which loads a specific model and view. Essentially, instead of grouping methods into a single file, it uses multipe files.
I'm kind of lost as to how I should do it.
Cheers
Start using a MVC that works and is well-known like in Symfony or Cake. From that you will decide:
what do to in your own, knowing the best practices;
to drop your own if you feel like you can save time by using theses.
If you are thinking of advancing your own MVC model, like #e-satis have said, you will need to experience what is happening in already developed systems. However, as based on my experience in designing MVC model and determining what is there in opensource community, I stick back to my own MVC for two good reasons. One reason is the flexibility of customization and the other is own MVC privacy.
I used the following approach for MVC design pattern.
A Router.php file identifying user-request urls. This router will be able to fetch controllers and include the file and call the controller default method.
The loaded controller is also able to load other controllers if required to function. This is done using a global method, where all controller Class will extend to a MainController Class which is able to call to other controllers.
I do use a global registry to set and get variables from one controller to the other.
The Models are used to get the Data from Table, and most of my Models will represent Database functions which includes CRUD (Create Read Update Delete). So that a controller can easily manipulate database table data using a model.
Naming conventions in all controller, models, and views is also important, if you want to system to be more intelligent to identify the required action knowing the file name.
I use the Views separately for each type of controller. And these views will be sent to a Master Template View file.
Same as models, the controller will be able to set Views to Master View.
There are other customizations which you can do, like applying security methods before calling a class, or after calling a class/controller/model/view etc.
This is done by the MainController, which it will always look into a folder with autoload class which states what files should be loaded before and after of different actions during the process of building the content and delivering the output.
MVC is not a small scale idea, but it is a design idea which can always be developed. There are so many PHP MVC open source frameworks to be found if you know how to search the major search engines like google.com
But I do advice you that, MVC is not a good solution if you are simply developing a small dynamic website, as it will consume more time in developing compared to developing small websites. MVC is ideal, if you have business logic and needs system automation in order to avoid most routine tasks of developing, and like that I would say MVC is most ideal for larger applications.
The model loads its view file
The Controller should act as a Mediator between the Model and the View.
The Model shouldn't be aware of the way the view renders it, and also the View shouldn't be aware of any kind of logic of the Model.
In theory, if your MVC is well structured, you should be able to represent the same Model with different types of Views (HTML, XML, JSON for example).
Build FrontController which parses request uri and decides which controller to load and which method to run. With .htaccess rewrite all request to index.php
//index.php
class FrontController{
function run(){
//parse request uri here /comment/new
//load controller comment
//run controllers method new and pass some request attributes
}
}
// ../controllers/comment.php
class Controller_Comment extends Controller{
function new($request){
//do stuff here
}
}

Breadcrumbs logic in MVC applications

Where should a breadcrumbs path be declared (in other words, in which letter of MVC)? So far I've been declaring it in Controllers, but I've recently started to work with CakePHP, where it is all made in Views and it surprised me.
I'm going to throw an answer out here, because there's a lot of confusion about what should and shouldn't be done with breadcrumbs.
The Model
The Model is a layer that contains your business logic consisting of domain objects, data mappers and services. You can read more about the model here.
The Controller
Remember: fat model, skinny controllers. Your controller / method is accessed from your routing mechanism. Once you're in the controller, you want to get your model object, perform whatever logic is required in the model, have the result of this returned to a variable in your controller, and then you use this to display data in your view.
The Breadcrumbs
That being said, your breadcrumbs need different parts to work. Let's think about this:
They need the current page
They need a list of pages
They (may) need a custom "class=current" added
Breaking those down:
In my framework, the current controller is also the page name (login controller maps to /login). So, we already have the current page.
The list of pages.
If your parent/child relationship of the pages are tied directly to the datamodel, then in your controller you pull the list of pages from the model. So use the model if the breadcrumbs can be automatically generated.
If the framework you're using allows breadcrumbs created entirely by user choice, then you are just choosing what to put in the breadcrumbs manually. Either way, you state your breadcrumbs in the controller, and if you need to get them from somewhere, use the model.
Finally, the "class=current". Although you shouldn't really contain significant 'logic' in your view, small things like loops or if statements are pretty standard. Here, you would check your breadcrumbs for the title equalling the current controller name (passed through as a variable to the view), and add a class=current if found.
Code Example
Note: untested
/**
* So we're in the home controller, and index action
*
* #route localhost/home or localhost/home/index
* (depending on .htaccess, routing mechanism etc)
*/
class Home extends Controller
{
public function index()
{
// Get current class name, so we have the current page
$class = __CLASS__;
// Let's say the page heirachy is tied to the model, so get pages for current method, or however you want to implement it
$pages = $model->getPages($class);
// So the TEMPLATE handles the breadcrumbs creation, and the controller passes it the data that it needs, retrieved from the model
// (new Template) is PHP 5.4's constructor dereferencing, also included is some lovely method chaining
// setBreadcrumbs() would assign variables to the view
// Render would do just that
(new Template)->setBreadcrumbs($currentPage, $pages)->render();
}
}
And now, the view... note, I use PHP 5.4, so I can use short echos...
<body>
<?php foreach($breadcrumbs as $b) { ?>
<li <?=($b['current'])?'class="current"':''?>>
<a href="<?=$b['page']['url']?>">
<?=$b['page']['title']?>
</a>
</li>
<?php } ?>
</body>
And that's how I would do it. Some of this is down to personal preference, but I hope this shows one way of doing it and is at least a little useful.
I actually came across this answer googling "php mvc breadcrumbs", and writing out my brain has really helped me to figure this out too. So thanks!
Whenever you see words "logic" and "view" together you should start worrying. My vote is for Controller because breadcrumbs is typical example of application-level logic, so putting it to the view violates MVC in my opinion.
Breadcrumbs should be in the controller. I use CodeIgniter and do something like
$data['breadcrumb'][0] = array("title" => "Home", "alt" => "Home Page", "path" => "home/");
$data['breadcrumb'][1] = array("title" => "About", "alt" => "About Me", "path" => "home/about");
And then in the view loop through and display them as a list.
<ul class="breadcrumbs">
foreach($breadcrumb as $b)
{
?>
<li><?php echo $b['title']; ?></li>
<?php
}
</ul>
You can then also declare simple things like classes, current pages, etc. The only downside is you have to set the breadcrumbs in every page.
ALL logic should be in the controller. Access databases through the models, perform logic in the controller, and pass it to the view.
Simple stuff like
<?php echo ($loggedin)?"Logged in as" . $user->firstname:"Not logged in";?>
can be in the view. But you shouldn't be setting up complex flow patterns. Leave that to the controller. Views are cheap. You can have a half dozen slightly different views and no one will care. It's not like static HTML where you would have to maintain a half dozen pages.
Include common things in the views (like headers, footers, script files, javascript files, etc) and then let them be.
IMO, the breadcrumb relates to the set of controller actions taken to get to the current page or the action's place in the hierarchy of the site, depending on your interpretation. From that perspective, the controller seems the natural place to construct the data for it, though the rendering should occur in the view. In order for it to be completely generated in the view, you would need to either expose details about what controller action is being invoked by the view or have a fixed view-per-action model so that the breadcrumb for each could be precalculated. Moving the logic for computing the breadcrumb to the view itself seems to violate the separation of concerns in MVC and may preclude reusing views for different actions, which would violate DRY>
In my opinion, generating data for the breadcrumb is a cross-cutting concern in the controller, i.e., you have some shared code that runs regardless of the action that uses the url to construct the breadcrumb data. There is also some shared view code that takes the controller-supplied data and renders it consistent with the design.
Note that I'm speaking from a purely architectural perspective. I'm not familiar enough with CakePHP (or other PHP frameworks, for that matter) to even judge whether your observation about it is correct. From a pattern perspective, putting it in the controller seems like the right thing to do. In a given implementation, though, it might make sense to violate the pattern.
$this->Html->addCrumb('Home', '/pages/home');
$this->Html->addCrumb('Contacts', '/pages/contacts');
echo $this->Html->getCrumbs('ยป', 'StartText');

Zend Framework-does every webpage have it's own controller and indexAction and view?

I'm wanting to be sure that I am setting things up correctly. On a typical website with 10 pages, would each page have it's own controller with it's own IndexAction and it's own View folder with it's own index.phtml as a view?
Or do you have one controller with multiple Page1Action, Page2Action, etc and have multiple differently named view.phtml pages within view/index folder?
I'm leaning toward the former because then I can have a cleaner controller for each page...
Is there a standard, or is it subjective?
Your sitemap would play a major role in this question. But, in lieu of that, here's a few examples.
Example 1. Flat
/foo
/bar
/baz
You'll probably want to use separate controllers: Foo/IndexController.php, Bar/IndexController.php, and Baz/IndexController.php with each having an indexAction() method to pass information to your view (once again separate).
Example 2. A Little Bit Lower Now
/foo/bar
/baz
You'll only need two controllers: Foo/BarController and Baz/IndexController. If /foo needs a landing page you'll have to throw in a Foo/IndexController.php to be safe. Your actions are still indexAction(). Because you've not gone deep enough to hit that third level, your views are still index.phtml.
Example 3. Straight Line
/foo/bar/baz
You're down to onc controller: Foo/BarController.php. If you need landing pages for /foo and /foo/bar you'll need another controller for /foo (Foo/IndexController) and an indexAction() for both. With /foo/bar/baz you're actually down to a slightly different action now too - bazAction() (inside Foo/BarController.php). Your view is now baz.phtml.
Summary.
The wider the sitemap the more controllers you have and fewer actions. The more narrow the sitemap the fewer the controllers and more actions.
Postscript.
I should also state, this is also contingent on using default routing patterns. If you do something a little more sophisticated in routing patterns, this is all shot out the window. Sometimes we use routes to keep the number of classes manageable. When we have a wide sitemap it's possible to create some custom routes and use __call() within a controller to hand-off view data appropriately. Just another way to skin this cat.
Typically you would create one Controller for a related group of Actions. What related means is subjective.
Very roughly speaking, a group of related Actions operates on the same Model. At least that's a good starting point, but it rarely works out that simply, because few real-world applications consist solely of CRUD operations on each Model.
If you decouple the Model from being simply a data access component, you can more sensibly define a logical grouping of Controller Actions for a Model. A Model is where the majority of your code exists for business logic. Database persistence is just an (optional) internal detail of the Model, to preserve state from request to request. But a Model doesn't necessarily use a database. It could be standalone, or it could be an aggregation of other Model objects.
By default, each Action has its own View script. But this is also just a starting point, because you could use Layouts to make many View scripts share some if their markup in common, and you could use View Helpers and Partials and so on.

Can I call a Model from a View?

Rather than use a full-blown PHP MVC, I'm designing one that will best-fit my uses. I have the basic framework done, and have coded the models and controllers I'll need to run my website.
Now I'm moving onto the Views, and I've encountered a small dilemma. My approach is working fine for me, but for future reference, I want to know if what I'm doing is a bad habit to get into.
What I'm trying to do:
In my View, I'm calling a Model that runs my authentication system, and requesting the login status of a user. I then use that boolean to decide whether to show certain elements within the view, and where to place others.
Should I be designing separate views for each login status, or is this approach fine? However, if I'm going to be implementing this MVC into the work I'm doing for my clients, I need to use the best practices.
Any advice would be appreciated!
Can I call the model from the View?
Yes, you can. As long as you maintain the separation of concerns between M,V and C, you are free to call upon the Model (or the Controller) from the View. Most MVC diagrams show a bidirectional connection at least between View and Model. What you don't want to do though, is place logic/code from the Model (or the controller) into the View and you don't want to modify the model from there.
For example, you might have a widget on your page that aggregates the latest ten blog posts headlines from your favorite blogs on each page of your website. You get the headlines by calling, say MyFavFeeds::getLatest(); in your model. What are your options now?
You could add the code to fetch the headlines into the controller, but that would require you to replicate it in each and every controller action, which is against the DRY principle. Also, the controller's concern is handling user input for specific actions and fetching the headlines on each call is likely not even related to these actions.
If your architecture supports it, you could fetch that data in some sort of preDispatch hook, that is, the headlines get loaded and injected into the View from a plugin or callback. That would be DRY, but a second developer might not be aware of that plugin and accidently overwrite the variable holding the headlines from his controller action. And there might be cases in which you wouldn't want to load the headlines, e.g. when just rendering confirmation pages for form submissions, so you'd have to have mechanism for disabling the plugin then. That's a lot to consider.
You place the call to (not the code of) MyFavFeeds::getLatest() into the View or Layout template or, better, a ViewHelper, that encapsulates the call to your model class and renders the widget. This way you don't have to worry about overwriting any variables or repetition. And when you don't need the headlines on your view, you simply don't include it.
About your other question:
In my View, I'm calling a Model that
runs my authentication system, and
requesting the login status of a user.
I then use that boolean to decide
whether to show certain elements
within the view, and where to place
others.
Authentication is something you will want to do early in the application flow, before any controller actions are called. Thus, you should not run your (entire) authentication system in the View. The actual authentication is not View-related logic. Just requesting the user status after authentication, on the other hand, is okay. For instance, if you want to render a widget showing the user name and giving a login/logout button, it would be fine to do something like
<?php //UserHelper
class UserMenuHelper
{
public function getUserMenu()
{
$link = 'Logout';
if(MyAuth::userHasIdentity()) {
$link = sprintf('Logout %s',
MyAuth::getUsername());
}
return $link;
}
}
If you got larger portions of your GUI to be modified by a User's role, you might want to break your View apart into partial blocks and include them based on the status, instead of writing all the HTML into a View Helper.
If you are only looking to render a navigation based on the user role, have a look at Zend Framework's Zend_Navigation and Zend_Acl to see how they do it.
You can, but you shouldn't. Except for a few extreme cases (and branching your view based on logged-in status is definitely not an "extreme case"), it's pretty much always A Bad Idea to call model stuff from a view.
What you probably want to do in your situation is pass the boolean to the view through the controller. That way, if you change something about the User model, the view doesn't have to know, so long as the controller keeps the behavior the same.
While I only know enough about MVC to get myself in trouble, I've always lived by the fact that unless your view is STRICTLY user interface, then it shouldn't be there.
Also, I've also ran with the idea of thin controllers, fat models.
Going off of these, I'd suggest adding a method to your authentication system model that returns the appropriate view to render and passes that to the view.
Okay, I would really try to keep my Views as logic-free as possible. If you need to switch anything based on e.g. the result of a model method, put a controller in place that delegates the rendering.
Just make sure you follow the basic idea: Do your stuff in the models, Tell your models what to do from your controllers and also tell your views what to show from your controllers.

Categories