CodeIgniter MVC - Is it a good practice to have Models serve views? - php

I'm developing a news website using CodeIgniter 3. Almost every page contains a Notice Board content of which is same on all pages. I have created a view for this section named 'noticeboard.php'. And different pages are controlled by different Controllers. i.e. Home, Post, Gallery, Poll, etc. The problem using controller here is I need to perform two operations on every controller to generate the noticeboard HTML.
Controller looks like:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class SomeController extends CI_Controller {
/* .. */
public function index() {
/* .. */
$noticeboard['notice'] = $this->noticeboard_model->getNotice(); // Gets Notice's HTML
$data['noticeboard'] = $this->load->view( 'sidebar/noticeboard', $noticeboard, TRUE );
/* .. */
/* $data is served to main page template */
}
/* .. */
}
And views/sidebar/noticeboard.php looks like:
<div class="noticeboard">
<h3>Notice</h3>
<?php echo $notice; ?>
</div>
I could solve this code redundancy by simply having a getNoticeboardHTML() on Noticeboard model and having the model fetch the view and return HTML. But is it a good practice?

Better you create a custom library and put getNoticeboardHTML() in that class. After that call this wherever you need. Do not dirty your model with HTML.
Create Custom Library

Theoretically speaking, No. You are not supposed to do this. Its a violation of MVC. You could use a library class to avoid the code duplication.

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.

Codeigniter and Mongodb library - do I need a model?

I am trying my hand out with mongodb as a backend to my codeigniter application.
I found and followed this example: http://www.surfinme.com/codeigniter-mongodb/
So I have the following structure:
+application\
libraries\
Mongo_db.php
config\
mongodb.php
controllers\
api.php
This is what my api.php file looks like so far:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Api extends CI_Controller {
public function __construct()
{
parent::__construct();
//loading the mongodb library
$this->load->library('mongo_db');
}
public function index()
{
$data['main_content'] = "dashboard";
$this->load->view('includes/template',$data);
}
public function list_available()
{
//connect to mongodb collection (i.e., table) named as ‘surfinme_index’
$collection = $this->mongo_db->db->selectCollection('testcollection');
$result=$collection->find();
foreach($result as $data)
{
var_dump($data);
}
}
}
And the code seems to be working. It gets my data out of the database and dumps it to my browser. But this "feels" wrong becuase I don't have a model.
Or should I be viewing the library as my model layer?
I could just as easily create a file in the models folder called api_model and make the calls to the library from there.
But is that overkill?
Any comments would be appreciated.
Thanks.
Depends on how tightly you want to adhere to MVC principals.
By creating a model for database operations you get several potential benefits. First, it provides a source that can be reused by multiple controllers. For example, there may be more than one controller that uses selectCollection. Second, if for some reason you decide to change databases you only have to modify the Models as opposed to every controller that makes calls to mongo_db.

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.

Better file naming conventions or structure

I create folders and then add files e.g.
folder: orders
files : view.php, add_update.php, invoice.php
Uri becomes: orders/view, orders/add_update, orders/invoice
another example
folder: user
files : view.php (view profile), add_update.php (add, update users)
Uri : users/view, users/add_update
and many more folders and files having similar structure. It works fine but in the editor (netbeans) I see the the name of the file only in the tab so that if I have opened order/view.php, users/view.php, files/view.php I see view.php, view.php, view.php ... I can certainly hover over and see the full path but I was wondering if you guys follow a better file naming pattern. I sometime make mistakes when uploading orders/view.php or users/view.php cos the files structure look so similar. What would you suggest?
PS: These are controllers not the CI view files. One of the reasons I have this structure is to have meaningful uri. I just tagged in CI but it doesn't matter if I am using CI or not.
Why the need for folders? Why not simply have a class of Orderswith methods view, update, etc?
Barebones example:
<?php if (! defined('BASEPATH')) exit('No direct script access');
class Orders extends CI_Controller {
function __construct() {
parent::__construct();
}
/* URL = example.com/orders */
function index()
{
/* default action */
}
/* URL = example.com/orders/view */
function view()
{
/* view method code */
}
/* etc */
}
you can rename your files like order_view.php, order_update.php etc and similarly user_view.php, user_update.php... it will differentiate the orders and users in your IDE
I would suggest working with namespaces, and give the views a more meaningful name.
This is how my Netbeans looks:
And I have assigned namespace \Ganymedes\Views to all of them. So I have meaningful names, and still everything in the same namespace.

mvc pattern, frameworks, implementations

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.

Categories