Situation:
The simplified situation is this: consider a blog that is build as an MVC project. The YII blog-example is fine for this, but the question is not framework specific: It is nothing special; you have a table with posts and a page build from:
a model (YII will give you a basic active-record setup)
a controller that for instance builds the index (list of all posts)
a view (or some views) that build the actual HTML in the end.
Now I have a working blog, but I also have an external source of information that I want to introduce to this same page: for example an RSS feed.
How do I add this new datasource?
Possible sollutions
To clarify what I am struggling with, here are some things I am considering
Make a new model that gets its information from both sources
Feels like the way of least resistance/work
It would need to sort the blogposts and RSS items by date
It might need to give some sort of flag about what kind of item it is (An RSS item might not have an author, but it does have a source).
The fact that above flag feels neccessairy makes me believe these should be 2 models.
Make a new model for the RSS and make a controller that combines the two sources and feeds it to a view that can handle both types of post
Something more complicated (maybe more framework specific), but the current view of a post is just one view for one post, and it gets repeated. Instead of one view that handles both types you might want not only a model, but also a view for your RSS, and a controller(?) that does all the mixing and matching?
Framework notes:
I'm using YII, but it's not really about YII. Ofcourse if something complicated is to be done I will have to implement it in YII, but it's about the design and the MVC pattern, not about where to put the ; ;D
u can hve something like this (I too use yii so the following code follows yii framework)
class XyzController extends CController
{
.
.
.
public function actionAbc()
{
.
.
.
$this->render('viewname',array(
'model1'=>$model1,//for posts frm table
'model2'=>$model2 //for rss feed
));
}
}
for better understanding try to render two separate views for each type of post inside the parent view "viewname"
If i had to do it, i would make a new controller for the view, and use two models.
I am very new to the mvc pattern, however from what i have gathered till now, it feels like any model should limit itself to only one data source. Also in addition to the CRUD operations, the "business logic" (if any) , should be included within that model. Business logic here would mean logic that applies to the data source pertaining to the web app, i.e the things that you have mentioned, like sorting RSS by date.
Create a controller that accesses these two models, to populate your view(s).
Finally the best way to organize these components/modules/parts of the mvc, with respect to Yii, depends on your app requirements, and ux.
Now, i think you should put this question in the programmers site also.
Hope this helps!
Edit: Not too sure where to put the sorting, controller or view.
Related
I've only just started learning CodeIgniter, so please excuse any misunderstandings I have.
I understand that the controller calls models and views. Views contain the HTML, models contain the database functionality etc.
I don't want to have to write code out to create a header menu, footer menu, side menu etc, in each of the controllers that import the menu structure into the view, so after some googling, it would look like it would be best to write a library in which my controllers can call to retrieve the type of menu they want.
My question is:
Would I place my database queries for retrieving the data to build each menu in the library itself, or would I delegate it to a model and call the model from the library? For the menu construction, I don't need to write to the database, just read the data it contains.
Many thanks
I never put any query directly in the library, as I believe that goes against the MVC that CodeIgniter intended.
I would aim to always make functions for simple database queries in the model, so that you may re-use them in various other portions. This allows you to return the data from what you need via the database when you require it. Which in turn allows you, in the library, to add additional caching or manipulate the data as it comes from the model.
I based that from 3 years of working in CI, and this little picture on this page: http://ellislab.com/codeigniter/user-guide/overview/appflow.html
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.
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 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.
This is my first foray into using an MVC construct (CodeIgniter). I'm hoping someone can tell me where the following elements belong. I have them written; I just want to make sure they're placed properly in their respective locations. This is how my application will run:
Call a DB and see if we have a user signed up
Route to a signup page
Route to the main preferences page for existing users
Make DB queries for producing a new user
Make update queries when users change their preferences
The service being provided is a cron job cycling every 10 minutes, which I still have written outside of CodeIgniter. Is this something I should/could add to the logic somewhere? It pings Twitter, and does stuff with any new tweets. Let me know if I can clarify any part of this!
Model
Controller
Controller
Model
Model
Rule of thumb: if it involves the database or the state of the application, it belongs in a model. If it is HTML or presentation logic, it belongs in a view. Controllers handle the rest of the logic, and help link the views and models together.
There are a lot of other things that come up too:
Where should I sanitise data? As it comes from the model - in the controller or finally before I view? I do it generally in the view if it's something like htmlspecialchars() (though I'm sure others might disagree).
Wikipedia has a very good article.