if I have a page on my site where i have to show 4 or 5 snippets (news feeds, event feed etc), all relating to different data (in different models and db tables), then what is a sensible way to handle the generation of the snippet content and layout? i could use a single snippet controller which contains static functions which each return a view populated with the relevant data. But each function in this snippet controller will be interacting with different data/models, so i'm not sure how OOP this is. Or, I could just add a static function to each of the controllers which are dealing with each associated set of data - e.g in a News_Controller, as well as functions to show all news items, individual news items etc, i could add a static function to generate the news feed by simply returning the view I need. I think this approach might work, as i don't want to instantiate an object for these simple snippets, so having static functions in the relevant controllers makes a bit of sense. Bit of a stream of consciousness here, but am i making any sense?!
Many frameworks have some notion of "partials", which are typically used for this kind of thing.
Since these partials are generally read-only, and are often displayed on every page (or some well-defined set of pages), you can approach them without thinking in terms of controllers like you would for a page.
In other words -- remember that it's fine if your view/layout code talks directly to your models, as long as it's only interrogating them.
I do things like this all the time:
layout.php:
<div id="newsWidget">
<?PHP $news = Model_News::latest(); ?>
<?PHP foreach($news as $newsitem): ?>
<!-- output some news headlines -->
<?PHP endforeach; ?>
</div>
Model_News::latest() might implement some caching, etc, since this is layout code and I probably don't want to hit the db on every request.
No controller-bloat necessary!
You may want to look into Hierarchical Model-View-Controller (HMVC). It's especially suited to making pages with snippets. I believe Kohana implements it.
Basically, you have multiple Model-View-Controller triads each responsible for each snippet. So you could have a controller to access the News database and load a variety of small views for different types of news displays.
You can architect your MVC pattern to provide a mechanism for allowing data that has been set to be returned as an array. For instance, normally a web request to /news/feed/ would result in pertinent data being set and subsequently passed to a view. In addition to web requests, the system should also allow a controller to make such a request, i.e., $vars = $this->call('/news/feed/'); The system will recognize the internal request and return the set vars rather than invoking a view.
This allows you to keep your controllers and models cohesive.
Related
Overview: I am building a CMS using PHP, and I am trying to implement this using MVC. I am trying to extend my code using this structure, as it represents an accurate representation of MVC and it is quite straightforward. To communicate with my database I use Domain Objects and Data Mappers.
Questions:
Is it really necessary to have a 1:1:1 mapping between a model, a view, and a controller?
Example: For a blog system, when displaying a blog entry page I would create a controller called DisplayEntryController, and a View called DisplayEntryView. The view would get its information from the BlogMapper class (which communicates with the DB to retrieve the current blog entry) and a CommentMapper class (which communicates with the DB to retrieve the comments for the current blog entry). Is this good practice, considering that view works with 2 model objects? If not what is the alternative? If yes, how can this be implemented in a generic way?
Can multiple controllers handle one page? For the example above, would it be possible to have a DisplayEntryController and a CommentController handling the relevant parts of a page displaying the blog entry? If yes, how would the 2 controllers coordinate?
Thank you in advance. Examples will be greatly appreciated.
Most PHP MVC implementations I've seen on the web use the page approach to organise their MVC. E.g. for the Home page, you have one view, one controller and one model. Routing for 1:1:1 mapping in MVC is straightforward, as you can enforce the location and naming of your MVC components, and when a request for the Home page comes it automatically looks for the following classes: HomeView HomeController and HomeModel.
This obviously doesn't work well in larger projects. How should routing be handled to support routing to multiple models (DataMappers), multiple views, without creating an overcomplicated router or adding a complex dependency injection layer?
Example: As discussed above, when displaying a blog entry you display
the blog entry code and the comment section. To achieve this, it
communicates with two DataMappers, the one which gets the blog entry,
and the one which returns the comments for the blog. How can the view
be assigned to work with these two datamappers to get the data from
the DB?
There is no requirement to have a 1:1 mapping of the model, controller and view.
MVC works of a concept of a tiered approach to handling your application, with each tier being handled by 'agents' to implement the way they see fit. To explain this further, consider the following scenario.
Assume you process data, then hand them over to someone to store. You don't care where they store it and how they store the data, as long as the information is available again when you need it. You can happily go about processing your data, and then say to them for example 'This is project data for Client X, store it,' and later say 'Can you give me the project data for Client X.'
SO MVC works on this approach, whether the data storage guys dump all data together or pack them away is not important to you. However, what is important is the interface between the two parties when sending and retrieving. For example, you could decide to store the information as either Client data, or Project Data, or both.
Likewise, you could have agents collecting data and handling it to you to process. You don't care how many interfaces they use (for example, phone, web, email, mobile devices), but you care about what data they hand you. (Of course a rule might dictate that only web information must be handled). So the interfaces for collecting data might be different.
Therefore, each agent can use the most efficient method (and even combine or split them) to get the system working in their side, and therefore there is no mapping of the data.
Newbie question about MVC structures here. So in an MVC, I currently have a page in my Views to display a list of results from a database query, in this bit of code I instantiate a class, run a method for sql query, and at last there's a for each loop and then displaying it with divs.
So my question is, if this bit of code is considered business logic and should be in a method in the Model, or is it part of the Views?
I hope you understand what I mean =) Thanks!
$listholder = new Categories_Model();
$data = $listholder->getCategories();
$i = 1;
foreach ($data as $row) {
if ($i & 1) {
echo '<div id="horizontalContainer" style="float: none; height: 50px";>';
echo '<div id="listoverview1">'.$row['catname'].'';
echo '</div>';
} else {
echo '<div id="listoverview1">'.$row['catname'].'';
echo '</div></div>';
}
$i++;
}
No, that code is mainly view code. It only purpose is to allow an external process (a human) to see data in a form it likes. Assuming that the check for the first row is only important to the external process, not to your business logic
Model code shapes, gets, and sets data, some of which is persisted (database etc.) and some of which is calculated on demand
Some generalised, and simplified examples on things a model or view should do:
Model calculates the total of some financial figures
View flags each even numbered row so it can be rendered with a shaded background in the view
Also, in a classical MVC system, your first two lines of code would be in the controller, which would organise the dataset by using models and model methods to get data. The MVC system would then pass that data to the selected view to render
There are plenty of PHP based MVC frameworks like CAKE, KISS etc (not all are very good!). If you have a few dollars in your pocket, save yourself some time and stress, and load up Microsoft MVC
From your question you might have some understanding of MVC that has nothing to do with what other developer think what MVC is. That can happen, especially nowadays as some frameworks have used these three letters as a catchphrase without providing it actually.
From the code you outline in your question I'd say it is a typical Transaction Script and there is no specific kind of model nor view layer involved.
The transaction script transports business logic and you do not need to speculate a lot about view or models, just keep everything inside the transaction script.
Your transaction scripts will tend to become spaghetti code, however, with some little refactorings here and there over time you should be able to reduce duplicate code and I do not think your application will grow that large that it is actually not feasible any longer keep it maintained in transaction scripts.
So why being concerned about MVC if everything is in order with some other, well proven pattern?
Taking as an example Rails or CakePHP, your code doesn't follow the mvc pattern.
Model should only contain business logic (query/do something with fields of an object)
Controller should work "only" with receiving requests of webpage with params and send back the correct page
View Is basically an html page only
Obviusly this is a very short briefing of what html is.
In your case, the idea would be:
$listholder = new Categories_Model();
$data = $listholder->getCategories();
Which is a controller code (usually), getCategories is a Model method (ok as is).
Then the controller will send some parameters to view which will know how to display those to the user, in this case your $data variable.
Imagine something like printMyView($view_file_path, $data)
The view will be something like this:
categories/show/">';
categories/show/">';
See http://php.net/manual/en/control-structures.alternative-syntax.php for alternative control structure syntax (quite nice). Maybe URLS are written better with sprintf or things like that (not how I did).
Basically you need 3 files (to split things logically), and the law is quite easy: don't write ever html in Controller, nor in Model.
The goal of MVC design pattern is to separate the presentation from the domain business logic. For that reason the business logic stays exclusively in model layer (model is a layer not any single class, if you have a class named Model, you are doing it wrong), whole the presentation layer contains views an controllers.
Controller instances are one that deal with user's requests, and change the state of model an view instances.
The view instances are the ones, that contain the presentation logic (just like domain objects contain the business logic in model layer). Views acquire information from model layer and decide, which templates will be used, or even whether template is even necessary. Views generate the response in your web site, and sending of redirect header is form of response too, which does not require any templates at all.
Also, you have to understand, that it is impossible to use classical MVC pattern with PHP (and highly complicated and impractical in the few web development, that would provide such option). Instead you would be using one of the MVC-inspired patterns.
These patterns are mostly distinguishable by how* view acquires information from model layer. The main options are: Model2 MVC, MVP, MVVM and HMVC.
In your case, the view should acquire the set of categories from model layer and then, if list is not empty and no exceptions were thrown, select a template which generates an unsorted HTML list.
The business logic would stay in the the model layer (in the domain object, which deals with categories), the presentation logic in the view and the process of turning it all in HTML - in the template, which view picked.
I recently went through some tutorials on how to program your own PHP MVC framework. To avoid some questions and comments: I don't want to use it in a productive environment, I just like to fiddle and get the idea of whats going on in MVC.
So far I am able to have single pages eg. http://domain/news/show/3 shows me the news-record from the database with id 3 and http://domain/news/all lists them all on one page.
Now I have multiple entities and thus multiple lists and want them all to appear on one page. Preferably the page you see when you open http://domain/
Do I have to write a new model and controller that makes calls to the other models? I'm kinda unsure how to achieve this.
There is no strict definition or convention on this that I'm aware of.
What I would do is this:
Class Overview
Controller_Homepage
Controller_News
Model_NewsArticle
Behavior
Controller_Homepage
Action_Index fetches multiple Model_NewsArticle entities, has them rendered, and passes the output to view. Also fetches any other entities you may need and gives their rendered output to view.
Controller_News
Action_List fetches multiple Model_NewsArticle entities, has them rendered, and passes the output to view.
Action_View calls Model_NewsArticle::factory($id), has it rendered, and passes the output to view.
Model_NewsArticle
Contains a static factory method that accepts an $id. Returns an instance of Model_NewsArticle.
Contains methods used to find multiple articles. A query builder would be nice here.
That's by no means comprehensive and I've left out lots of little details, but it's fairly simple and is pretty dry.
This is a matter of preference really. Having another controller and model makes code separation easier in larger projects. Personally, I would only make a new controller since it is a different page with potentially different actions, and I would use the existing models to get the data to keep your code DRY (Don't Repeat Yourself).
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.
All the examples I've seen of what and how MVC SHOULD be have used classes as the models, classes as the controller, and HTML templates as the view. And all of them consisted of one index.php script and different requests in the url to run the entire site.
So they've all been something like...
MODEL
class User{
function getUser($userID){
$sql = mysql_query('SELECT name......');
// more code.....
return $array
}
}
VIEW
<h2><?php echo $user['name']; ?></h2>
CONTROLLER
class Controller{
$userModel = new User;
$userInfo = $userModel->getUser($id);
$template = new Template('usertemplate.tpl');
$template->setVariables($userInfo);
$template->display();
}
I understand why the model is made of classes that simply get and save data (even though I assume classes arent always necessary and functions could be used). I understand why the template consists of mainly HTML. But I dont understand why the controller is a class. I would assume the controller to be a procedural script (like userprofile.php which gets the users data from the model and sends it to the template for displaying).
Also, I was wondering why every tutorial I've read dealt with mod rewriting, and using a single page with requests in the url like "index.php?user=1", or index.php?news=3 to run the entire site. Whats wrong with having separate pages like user_profile.php?id=1, or news.php?id=3...
Can somebody please help me with a quick "tutorial" and an explanation along the way. Like...how would a registration form be implemented using MVC, what would go where and why? thankyou
PS. what other kind of design patterns are there
The big "win" of the controller in PHP's version of MVC is you get away from having a separate PHP page for each and every URL that your application responds to.
When you have a new single page being created for each URL, you're expecting your developers (or yourself) to pull in the needed libraries and initialize the template/layout engine in the same way. Even when you're a single developer, the temptation to break from the "standard" way of doing things usually ends up being too strong, which means each URL/PHP-page ends up being its own mini-application instead of each URL/PHP-page being part of the same application. When you have multiple developers this is guarantied to happen.
The end results is pages and components that don't play nice with each other and are hard to debug (with everything hanging out in the global namespace), giving an inconsistent experience for both the users and the developers who have to work on the project.
MVC frameworks also make it easier to give your site friendly URLs. There's usually enough going on in the routing system that you don't need to resort to a huge number of query string variables. Readable URLs are a plus, for SEO and for savvy users.
Finally, although this is pie in the sky with most shops, when you have a controller the methods on the controller become easily unit testable. While you can technically wrap a test harness around a non-MVC site, it's always a pain in the ass, and never works like you'd like it to.
using a single page with requests in
the url like "index.php?user=1", or
index.php?news=3 to run the entire
site. Whats wrong with having separate
pages like user_profile.php?id=1, or
news.php?id=3...
Using a single entry point makes some things easier, I suppose :
You don't have to duplicate any portion of code in user_profile.php and news.php
If you want to set up any kind of filter (like PHPIDS for security, or ACL, for instance), you only have one file to modify, and it's done for the whole application.
PS. what other kind of design patterns
are there
There are a lot of design patterns ; you can find a list on the Design pattern (computer science) article on wikipedia, for instance -- with links to the page of each one of them, for more details.
There's nothing wrong with having separate scripts for each action, and in fact you CAN create a MVC architecture this way, without using a class for the controller. I'm working on an MVC framework at the moment that supports both styles.
The important thing is really to keep separation of different concerns. Database logic goes in your models, Layout logic goes in templates, and everything else in the controller.
So for a really simple example you could have a script "register.php" with the following code
$signup_options = SignupOptions::getSignupOptions(); // Load some data
require("register_form.php"); // Pass it to the view
And this posts to register_process.php
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
$email = $_REQUEST['email'];
Users::Register( $username, $password, $email );
header( 'location: register_success.php' );
MVC is not suitable for all applications, so you should consider your architecture on a per project basis. For many sites, just having a bunch of independent scripts works fine. For larger more complex applications however, MVC has proven itself to be a reliable and scalable way of developing web applications.
Another common design pattern is "View-Helper", which is where you call a template directly, and the template calls a "Helper" object that performs business logic between the template and the models. Similar in concept, but you can skip having any extra code for templates that don't need it, while still maintaining separation of concerns like MVC. (The difference is essentially that you call the template directly, rather than calling a controller).
There are several ways to implement a good application, but I am just going to touch on a few concepts. These concepts are taken from Samstyle PHP Framework.
Firstly, you have these components: Model (Table Data Gateway), View, View Controller and Backend Controller.
This View Controller actually controls how the view is going to be like (e.g. display out the registration form). The Backend Controller processes user data on the backend and interacts with the Model (database).
So here we can easily integrate Post-Redirect-Get into it.
Say you have register.php for the View Controller which will display the form and parse the content into the template HTML file.
User uses the form, submit and will then be posted to the Backend Controller deck.php. The Backend Controller validates, check then passes the data to functions (Table Data Gateway) which will help you to interact with the database. After the interaction is done, the user is redirected either to a success page, or the registration page with an error.
In the Model (Table Data Gateway), you actually have functions which take in an array and then CRUD with the database.