i know that this question already has been asked. But i still dont understand it.
Right now im trying to understand how to make use of the MVC Modell.
But i dont get how to integrate everything and right now I am hesitating to use a framework before i really get it.
What I try to achieve:
I want to have a header, a footer and a menu which remain the same all the time.
Like this:
HEADER
MENU
{CONTENT}
FOOTER
So my thinking is:
My Controller gets some Information, lets say its a User-ID.
Controller calls a method from the Model:
Get all DATA from USER with ID: 1
Then the controller passes the DATA into a view, lets say a list.
So where to go from here?
Should the controller pass this view into another view?
Like:
$site = new View(); <br>
$site->wholeSite($content);
and then site is something like:
HEADER
MENU
{$content}
FOOTER
Please excuse my simple approach, im just trying to get the basic idea behind it and i already read the first 20 pages of googling it.
Just cant get my head around it.....
It would be really nice if you would explain it for an Beginner :)
Thanks in advance!
you can call multiple views from the control like:
$this->load->view('header',$data);
$this->load->view('menu',$data);
$this->load->view('content',$data);
$this->load->view('footer',$data);
If you have a nested div then you can use regular include function like from a particular view file.
include('footer.php');
According to the path of the view file. The data also gets transferred from parent view to the included file.
Generally MVC apps have a universal layout view which contains the header, footer and menus. Sometimes data required for that is handled outside the controller, in say your init script or bootstrap.
An MVC purist might pass all data the layout requires from the controller, but that can be repetitive, although setting the data in an abstract controller construct might alleviate that.
On the question of views and sub-views there are generally two solutions:
A.) You have one principle view which all required data is passed to. In that view sub-views (partials) are called, and data is passed down into them.
B.) You instantiate all your views in the controller, passing all the data they need directly into the view, you would then pass views as parameters into other views.
Both methods have their pros and cons. I find the first option leads to less Fat Controllers, so I usually go with that.
I'd recommend you learn an existing MVC framework ( CodeIgniter, now defunct is basic enough to make it a good entry point), as that will show you how things are done.
Related
I'm building a small PHP MVC, and I've hit a wall with a small area of the coding. I think I need "partial views", but I might be able to achieve something with the existing code.
My controller in it's simplest form currently:
Instantiates an object
Checks if a POST variable isset
Displays view 1 or displays view 2 as necessary
The view(s) currently:
Displays HTML markup
Use and echos the models get functions such as getUserInfo()
Everything is working great, however the code is now getting fairly large in both the controllers and views, and I've reached a situation where I need to include "modules" or sub views inside the main views (1 and 2).
For example if view2 is loaded, then I need to display (as part of the view2) another view, say a 3 part sign up registration form. This registration form comes with it's own controller file too.
I can do something like this, which will work and give you some idea of what I am trying to do, but I acknowledge this breaks MVC design patterns.
View
<div id="mydiv">Some content</div>
<div id="mysignup"> <?php include('controller_signup.php'); ?></div>
<div id="content"> The views main page content </div>
The view is then pulled in from the controller, in the right place.
As mentioned, I think I need to use partial views, however most of the info I've found is for ASP, and I'm slightly lost!
I would have thought this is a fairly common problem, so I assume there is an obvious solution!
Thanks!
The root of you problem is fact that you do not have views. What you call a "view" is a actually a template. This in turn forces the presentation logic in the controller.
In proper MVC views are instances, which contain all of presentation logic. They acquire information from model layer and then, based in data, choose how to display this information. Each view manipulates multiple templates.
Also, it seems that your controller has gained extra responsibilities. It is supposed to change the state of model layer and current view, instead of rendering templates.
Can't say I agree with tereško. Having the presentation logic in a separate view class might seem more proper, however it does add another layer of complexity. In many cases, this additional layer is not necessary - often a view can directly render whatever model or data you inject. So you end up with empty View classes that only pass the model from the controller to the template.
I'd say, Keep It Simple, you can do pretty complex (and maintainable) websites with simple MVC, without introducing the notion of templates.
To handle subviews, you can simply have the main view inject data into the subviews, this should be transparent to the controller (who just provide the main data without caring how it should be rendered). So in practice, you could have something like this:
Controller:
public function someAction() {
// ...
$view = new View('name');
$view->data = $someList;
}
View:
<?php foreach ($someList as $item): ?>
<?php echo (new View('subview', $item))->render();
<?php endforeach; ?>
I don't know if I'm wrong. But all I know is that in MVC, is that the Controllers is always responsible for calculating the data, and the View to print them.
The problem
I have a poll that I need use a model to get your data and I use a view to print. Currently I can access this poll by use the url "poll/last". This works fine.
My problem is that I need print this info on some pages (like in "site" controller).
The Dilemma
If I simple load the poll view on page, nothing data is get from model. Onetime that it is work of Controller.
If I move all controller part to view, this works fine. The low point is that turn the application in a "non-MVC compatible".
The Solution
So how can I solve this dilemma?
Actually the CodeIgniter not is a HMVC, and the HMVC module don't works fine -- only locally.
There are some viable solution to solve this problem?
Controllers are not always responsible of all calculations. When those calculations are part o fthe 'business or data model' they should go into the model. My english is not good sometimes but i'll try to explain with an example: Let's say we have a table with persons data, and a column birth_date. Age() function should be in Model, because is another way of seen birth_date.
In your case, I would try to move calc into the model, and write a partial who shows the result, and pass the resulting partial view to the main one. Something like
$data['poll_view'] = $this->load->view('poll_partial',$this->poll_model->getPollData(),true);
$this->load->view('current_view', $data ); //that includes poll subview
I may be misunderstanding your question, forgive me if I'm wrong. I can't comment yet on posts, so consider that this may be an answer.
You're wanting to use the data that is in the poll/last controller in another one?
Why not have the same code that you're doing on the controller, in a method/function in the model?
That way, when you call your model just like in the poll controller, the same code and data is available to the site controller.
That's the main function of models.
In my opinion it goes like this:
View - Displays the data, formats the data, and puts the data where you want it.
Controller - Takes the data and determines what exactly to show and on what URL / location to show it, and in which view.
Model - Gets the data from the database, does any calculations that you need to, and returns it.
Hope this helps!
It sounds like you are trying to load the poll view into other views? If so, take a look here: http://codeigniter.com/forums/viewthread/189935/
The same question has been asked/answered
Forgive me if that wasn't your question... can't comment on posts...
I am a beginner with CodeIgniter still struggling to get a complete grasp on how to use the MVC ideology most cleanly.
I am writing a basic CMS system with the ability to vote on entries and follow people etc, consequently, I have found myself using the same or similar pieces of code across multiple views here and there consisting of various pieces of html and logic such as:
Voting panel
Follow/Unfollow panel
Login/Logout panel
Code to check if a user is logged in etc...
I am wondering where to put this code so it can be unified? I am thinking a helper is the way to go? If I declare the helper in the controller, it can be called from the corresponding view right?
Some of the elements are dynamic - such as a follow/unfollow button - It would need to check if you are already following the user or not and display the appropriate button, which would require a model to check. What I have now is that all the logic is in the controller and it returns an appropriate button, but it seems weird to be returning formed html code in a controller return as well. Should it be more like:
controller checks if you are following someone
the controller passes a boolean to the view
the view calls the helper with this value to draw the appropriate button
Also, as a secondary question, I have been doing a fair bit of looping through mysql arrays in foreach loops to process mysql results returned from the view. It seems like my views are getting somewhat complicated, but I can't think of another way to do it, although perhaps this should be done in another helper as well?
Apologies if this is a naive or repetitive question, there is indeed a lot of discussion surrounding this subject but it is not always easily relatable to another project.
Helpers are certainly one way to modularize anything that isn't DRY. Another is to use Partial Views. CodeIgniter looks like it supports partial views. Here's a good breakdown - not PHP specific but the discussion should be agnostic.
As far as handling user logins is concerned, you will probably want to use a static class and the singleton design pattern, which will allow you to check to see if a particular user is logged in or not anywhere in your application. There is a good tutorial here
http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login
Loading the helper, I don't believe loading it in your controller will automatically load it in your view. I think you have to re load the helper in your view file, or you have to autoload the helper. (cant remember off top of head but Im pretty sure).
Regarding looping through the mysql results, you should be using a model for this, always. Any functions which are grabbing or sorting information from your applicaiton, should be done within the model. Then, in your view file you loop through the results and format the data how you choose to.
When developing http://newspapair.com which has the vote functionality you mentioned I used helpers and custom classes to spread the functionality across multiple views.
Helper - has functions without a class. So a standalone function or group of functions can be placed in a file and saved as a helper.
For instance I used a helper with generic form processing functions for NewsPapair, instead of a static class. But this is not the "best practices" thing to do. I did it this way because I already had the functions from a previous project.
As far a looping through MySQL results, try to write a query that allows the DB Server to do the heavy lifting. This will make your code more efficient. Perhaps ask a question about a specific query with example code. Plus do all of the data gathering in your Model.
I'm about to do a PHP website using the MVC pattern. I am not using a framework as the site is fairly simple and I feel that this will give me a good opportunity to learn about the pattern directly. I have a couple questions.
Question 1: How should I organize my views? I'm thinking of having a Page view which will have the header and footer, and which will allow for a Content view to be nested between them.
Question 2: If I have 5 Content pages, should I make 5 different views that can be used as the content that is nested within the Page view? Or, should I make them all extend an abstract view called AbstractContent?
Question 3: What about controllers? I think there should be one main controller at least. But then where does the request go from there? To another controller? Or should I just call the Page view and leave it at that? I thought that controllers were supposed to handle input, possibly modify a model, and select a view. But what if one of the views nested within the view that a controller calls requires additional input to be parsed?
Question 4: Are controllers allowed to pass parameters into the view? Or should the controller simply modify the model, which will then affect the view? Or is the model only for DB access and other such things?
1 - This is a matter of preference. The simplest way would be to have a separate header and footer file. Then you could do something like this in your page controller
$title="Page Title";
$var1 = 'var1';
$var2 = 'var2';
$var3 = array("asdf","adsfasdf","234");
include(HEADER); //$title is in header
include(DIR_VIEWS . 'page.php'); //$var1/2/3 are in page.php
include(FOOTER);
// variable were created before pages were included so they will be set in the templates
If you were to go the nested route you would have to start fiddling with str_replace and that starts heading towards a template engine, out of scope for this answer.
2 - No need to make views objects. A "view" can just be a file on your filesytem that contains the html for that view. Like my example above. These pages can contain basic php to loop/echo variables as well.
3 - You are describing a front controller (sometimes called dispatcher or router). This is really the way to go. There are a couple methods for creating a front controller.
You can have an array of urls that point to controllers.
$routes = array (
'~^/home/$~' => 'home.php',
'~^/contact/$~' => 'contact.php',
'~^/blog/.*?$~' => 'blog.php'
);
or you can use the first "directory" in the url as the controller name and load that file form your controller directory.
4 - The entire point of the controller is to get info from the model and pass the data to the view.
Edited for comment
If you want a bunch of views to have a sidebar you just include that view in the other view. For example:
<div id="content">
<p>lorem ispum stuff</p>
</div>
<?php include(DIR_VIEWS . 'sidebar.php');
Just make sure that in controllers that "control" pages with sidebars you include some code for sidebar functions:
if ( $_GET['keywords'] ) {
$sidebar_search_results = get_search_results($_GET['keywords']);
}
// this code should be in a file that you include
$sidebar_search_results could be an array of results that your sidebar view parses and displays.
Think about what ways you'd want your HTTP responses to look like: full pages with/without nav, stripped pages for printing, JSON & XML responses, an index/sitemap. After you feel the site is forming, add more and more shortcuts for getting your response out there with as little code as possible.
If the page layout is similar, I would use the same view and load content into it from a model (possibly a database).
Check out the Front Controller pattern: you should always be able to intersect the request in a single point of entry. I would put something hierarchally in front of your controllers and then have one controller per "main page" (forum, blog, news). This is sufficient to control, but you'd have to decide what chunks are large/small enough for you.
Controllers are responsible for everything that gets passed into the views. Controllers should fetch data & settings & what-not from models and pass on to the views.
Question 1:
This is indeed a way to do this, and one which I allways use.
Question 2:
Just keep views as simple as possible. I tend to create just 5 separate views (plain php files).
Question 3:
In the normal mvc pattern, there is one front controller (which OS just a bootstrap file, the index.php) which executes one controller.
In HMVC, controllers can send additional request to other controllers.
Question 4:
The normal MVC pattern applies on normal apps, where views are persistent, and can observe the models. With web applications this is not possible, because every request everything is reloaded. So the most used pattern is to let the controller pass the parameters to the 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.