mvc pattern, frameworks, implementations - php

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.

Related

how to retrieve data in view Independent of controller in codeigniter

I have a sidebar in my site that receive some information from db and I can't use controller for retrieve data because I have different controller and same sidebar. How can I print this data in view page.
when I wrote in P.h.P code in the view it shows an error that it cant define variables.
How could I do this?
When you find that you need the same code in many different controllers a "custom library" (class) is the perfect choice. Documentation for creating your own libraries is found HERE.
Controllers should be using models to get data from the database. Custom libraries can also use models just like controllers. Here is a very basic custom library called Sidebar. It depends on a model (sidebar_model) that will not be shown. The purpose of the Sidebar library is to return the variables need by the sidebar_view file.
File: application/libraries/Sidebar.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Sidebar
{
protected $CI; // Read the documentation link to see why this is needed.
public function __construct()
{
$this->CI = & get_instance();
$this->CI->load->database(); //only needed if not already done
$this->CI->load->model('sidebar_model');
}
public function get_sidebar_data()
{
return $this->CI->sidebar_model->get_sidebar();
}
}
The library method get_sidebar_data() returns the variables for the view.
Here is a controller that uses the custom library. It will use the custom library and a view file (not shown) containing HTML for the sidebar.
File: application/controllers/Main.php
class Main extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('sidebar'); //can also be autoloaded
}
public function index()
{
$data['sidebar'] = $this->sidebar->get_sidebar();
$this->load
->view('banner')
->view('sidebar_view', $data)
->view('main_view')
->view('footer_view');
}
}
Any other controller that needs to show the sidebar would use this same pattern.
This controller loads four different view files and is using "method chaining" which is encouraged. Method chaining executes a tiny bit faster. But the best reason for using it? Less typing.
The method chaning could also be type like this:
$this->load->view('banner')->view('sidebar_view', $data)->view('main_view')->view('footer_view');
But, IMO, putting each ->view() on a separate line makes it easier to read.
You can create a helper for your common tasks. Then create a function for your sidebar and call it where you need it. Check this link for more details about creating helper
You can also create a library for it. Although it will not a very good choice.
create sidebar (view page) and Call model directly inside that sidebar (view page).
secondly call sidebar (view page) directly inside all other view pages.

How to pass data to layout in Laravel regardless of controller?

Let's say I got ControllerA and ControllerB which both implement the same layout. Now I want to pass data to layout, for example, a message that should appear in layout no matter which controller implements it. If I had only 1 controller, I would do something like:
class Controller extends \BaseController {
public function setupLayout() {
View::share('message', 'Hello world!');
}
// further methods
}
However, when I want multiple controllers to implement a layout, I have to do this in every controller, which doesn't sound reasonable. So I wanted to ask, is there any native way in Laravel to pass data to layout and not to copy code in every controller.
Thanks in advance!
For those cases I would recommend a view composer, where you can set them for more than one view (or layout) or just all of them:
View::composer(['store.index', 'products.*'], function($view)
{
$view->with('model', 'one');
$view->with('colour', 'black');
});
You can put that in your routes file, filters file or, like, me, create a app/composers.php and load by adding
require app_path().'/composers.php';
To your app/start/global.php.

Controllers structuring in PHP frameworks

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.

Method in one controller calling a method in another controller, using MVC

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.

Would bypass of the controller in CodeIgniter be considered a good practice?

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.

Categories