Is directly call to the Model class inside the View is best practice or not? Currently I am using CodeIgniter to develop an application. In different Views of my application I'm including menus that I want to pull from the database. And the thing is currently I am passing the values to the menu through the controller. If I make a common model class and call it from the View and by pass controller. So that there will be one call to Model and it will load menu from the database at once and by pass the controller. By doing this what pros and cons will come?
With codeigniter, your views should not be concerned as to where data comes from, only that it exists. Only your Controllers should be in direct contact with your Models.
It sounds like you have a common menu that you want to load in your views and you don't want to replicate that code across all your Controllers.
To solve this problem, you need to create a common controller that your primary controllers inherit from with a method that fetches the menu.
My_Controller needs to be saved to the core folder in the application directory.
class MY_Controller extends CI_Controller
{
protected function get_menu()
{
// Load your menu here
$this->load->model('menu_model');
return $this->menu_model->get_menu();
}
}
All your primary controllers will inherit MY_Controller
class Home_Controller extends MY_Controller
{
public function index()
{
$page_data = array('menu' => $this->get_menu());
$this->load->view('home/index', $page_data);
}
}
In my opinion no its not best practice. View should contact Controller and Controllers should retrieve data from Model where Model does all the logic. Controller suppose to be the glue or middleman of View and Model.
Controller passes the returned data into View and then you do your foreach loop or whatever to display it.
View should not be doing any logic. Retrieving data from database is somewhat logic.
It is a worst practise. Then why we have controller concept for MVC. :) Mainly all logics goes into Model so thats not good to call model directly.
There will not be any problem, since you are using a common controller.
Note : You should not call model directly from view.
Related
I'm going for an example to make the question easier:
If you are implementing facebook, you want to separate user information from account information, from posts, from from from, that means there will be a model for user, a model for user info, a model for posts, a model for for for.
now if you go to user profile, it loads information from all these models, the question is how would you structure the controllers, of course you need controllers for each model to define it's unique actions, but how do i handle the rendering?
do i make a new controller that takes care of all renderings? or do i just put render profile in the user controller - which means it will have access to other models - or do i put in each controller a rendering of it's own and then combine them together...
or maybe if you have a better approach?
i just do not know the consequences of each approach that i thought of, and i don't know if there is a better approach that i didn't think of.
As others mentioned, you don't need a controller specifically for each model. However, given your Facebook example, it's quite simply done through relationships.
An oversimplification would be:
A User model to hold the user's account information and relationships
class User extends Eloquent {
public function posts() {
return $this->hasMany('posts', 'from_user_id');
}
}
A Post model to hold the content and from/to relationships to User
class Post extends Eloquent {
public function from() {
return $this->belongsTo('user', 'from_user_id');
}
public function to() {
return $this->belongsTo('user', 'to_user_id');
}
}
Then perhaps you'd have UserController load a view like so:
class UserController extends BaseController {
public function index($id) {
$user = User::find($id);
return View::make('user_page', array(
'user' => $user,
'posts' => $user->posts()->with('to')->get()
));
}
}
of course you need controllers for each model to define it's unique actions
No, this is wrong.
Controllers are part of your presentation layer, some might say you need a controller for each view object which is okay but for the model layer, it has nothing to do with the number of controllers you have.
a View is an object that toggles multiple templates and once again this has nothing to do with your controller, rendering is a view responsibility.
to understand it more, take a look here , here and here
those are really useful information to start with.
Wrong answer - controllers are not part of presentation layer - they are part of transport layer. Their task is to react on HTTP request.
Request is dispatched by Router. To proof take a look at Laravel source. Controller is a part of Routing package. When you call for example:
Route::get("/","HomeController");
You are just registering request parameters in RouteCollection. But everything is happening inside Router. Controllers can exist without any kind of view layer.
so i have a user controller, that has methods to update profile, etc. In the system i am developing the user would need to post articles, etc. So i am confused with the design of the system. The main logic of creating articles would be housed under the article_model. But how should i call the methods?
I can create a function in the user controller that calls on the article model to create article?
I can call a method in the user controller and create an article controller and the user controller calls the method on the article controller, which in turns call the model for the main logic.
Or just directly call on a article controller that connects to the article model.
I personally feel i need to have a user controller into this system, as logically speaking a user creates article. So which design is perfect in terms of logic and best practices.
You can load multiple models in a controller, you’re not just restricting to the model in the same domain as the controller. So if you need to interface with articles in the users controller, then just load the articles model. As deceze says, you shouldn’t call other controllers in one controller; that definitely goes against MVC conventions.
In your case, any interaction with an article should be in the articles controller though, accessible at a URL like /articles/add.
I actually use codeigniter and they do it this way. If you want to post an article from your user or profile controller you can just make an instance or load your model.
class ProfileController extends BaseController {
public function __construct()
{
$this->load->model('article_model');
}
public function index(){
$this->article_model->post();
}
}
don't call a controller from another controller
you can add link to any view called with the profile that reefers to add article
if you have to call the controller from another you may have a look at codeigniter hmvc
HMVC: an Introduction and Application
Try to use this extension HMVC for CI. It's allow to call controller methods in another controllers. Something like this:
class Dashboard extends MX_Controller{
public $autoload = array();
public function __construct()
{
parent::__construct();
}
public function index()
{
$params = 'some_params';
$data['some_data'] = Modules::run('another_controller/method', $params);
}
}
Where another_controller - simple CI controller, what expand MX_Controller.
Hello i have a few questions about mvc pattern and frameworks in general.
I know mvc stands for model - view -controller and that models are fat and controllers are skinny but i'm not quite sure about few details .. on the view part.
let's say for example i have this model
<?php
class Menu_Model extends Models
{
public function listMenuItems()
{
return $this->query('some_select');
}
}
controller
<?php
class Menu_Controller extends Controllers
{
public function index()
{
$this->load('menu', 'Menu_Model');
$this->view->assign('menuItems', $menu->listMenuItems());
$this->view->add('menu.php');
}
}
view
<div class="menu">
<li>{echo_some_data_from_controller}</li>
</div>
The above code let's say is for a simple menu fast wrote now .. as an example. by the mvc ideea it needs to have a model a view and a controller good but then how do i implement this menu in each of the views i have? let's pretend that:
the head.php file where i keep the import css starting of the html with basic stuff and the header of the website to get data from mysql for the menu i would need to call the model but the model is called in the controller and each page got it's own controller so from what i understand so far for each controller method i would need to call for a certain model menu, login form etc... to output on each page i need to get data or how do i do it ?.
The responsibility of a Controller is to handle User Input. If your menu doesn't require any user input, put the code into a View Helper and then fetch the Model data from there. Then call that View Helper from the View. In other words: you dont need a controller then.
An alternative would be to provide some sort of mechanism that allows you to register common functionality on each call to a Controller, e.g. something like Zend Frameworks's pre- and post-dispatch hooks. You could then write plugins for these hooks to load and inject certain Model data on each request.
I have four models in CodeIgniter for a forum I am building:
forum_model
category_model
user_model
subject_model
I wish to access the category, user and subject models within the forum model (ie: browse thread by user / category / subject) but they need to be independent for individual functions (ie: add user / subject / category)
Theres a lot more independent functions and basically what I was wondering was if it is bad practice to create a 'master' forum model (and what the best way to create the model would be) or if I should just do the linking in the controller?
I was thinking about setting the forum_model up like this:
class Forum_model extends CI_Model {
function __construct() {
parent::construct();
$this->load->model('Category_model', 'category');
$this->load->model('User_model', 'user');
$this->load->model('Subject_model', 'subject');
}
}
then possibly accessing the other models within methods using variable variables $this->$model->method()
In 2.1.0, any property (i.e. model reference, library, etc.) not defined in a model's scope will magically access the CI super object:
<?php
function __get($key)
{
return get_instance()->$key;
}
So, as long as you don't have $category $user or $subject member variables in your forum model, this should work.
However, usually it's good practice in MVC for models NOT to know about each other. I'd caution you not to let your forum model function like a controller or a library (otherwise, it should be a controller or a library!).
I have a controller/model for projects. so this controls the projects model, etc, etc. I have a homepage which is being controlled by the pages_controller. I want to show a list of projects on the homepage. Is it as easy as doing:
function index() {
$this->set('projects', $this->Project->find('all'));
}
I'm guessing not as I'm getting:
Undefined property: PagesController::$Project
Can someone steer me in the right direction please,
Jonesy
You must load every model in the controller class by variable $uses, for example:
var $uses = array('Project');
or in action use method
$this->loadModel('Project');
In my opinion the proper way to do this is add a function to your current model which instantiates the other model and returns the needed data.
Here's an example which returns data from the Project model in a model called Example and calls the data in the Example controller:
Using Project Model inside Example Model:
<?php
/* Example Model */
App::uses('Project', 'Model');
class Example extends AppModel {
public function allProjects() {
$projectModel = new Project();
$projects = $projectModel->find('all');
return $projects;
}
}
Returning that data in Example Controller
// once inside your correct view function just do:
$projects = $this->Example->allProjects();
$this->set('projects', $projects);
In the Example view
<?php
// Now assuming you're in the .ctp template associated with
// your view function which used: $projects = $this->Example->allProjects();
// you should be able to access the var: $projects
// For example:
print_r($projects['Project']);
Why is this "better" practice than loading both models into your controller? Well, the Project model is inherited by the Example model, so Project data now becomes part of the Example model scope. (What this means on the database side of things is the 2 tables are joined using SQL JOIN clauses).
Or as the manual says:
One of the most powerful features of CakePHP is the ability to link relational mapping provided by the model. In CakePHP, the links between models are handled through associations.
Defining relations between different objects in your application should be a natural process. For example: in a recipe database, a recipe may have many reviews, reviews have a single author, and authors may have many recipes. Defining the way these relations work allows you to access your data in an intuitive and powerful way. (source)
For me it's more reasonable to use requestAction. This way the logic is wrapped in the controller.
In example:
//in your controller Projects:
class ProjectsController extends AppController {
function dashboard(){
$this->set('projects', $this->Project->find('all'));
}
$this->render('dashboard');
}
Bear in mind that you need to create dashboard.ctp in /app/views/projects of course.
In the Page's dashboard view (probably /app/views/pages/dashboard.ctp) add:
echo $this->requestAction(array('controller'=>'projects', 'action'=>'dashboard'));
This way the logic will remain in the project's controller. Of course you can request /projects/index, but the handling of the pagination will be more complicated.
more about requestAction(). but bear in mind that you need to use it carefully. It could slow down your application.