Codeigniter: Is calling a model from a helpler a bad idea? - codeigniter

I have a menu on my page that is loaded on every page. The menu data is fetched from the database through a model. My first thought was to call the model from the controller, and then pass it to the view on every page. But that results in "messy" code, if i ever forget to pass the menu data to the view, it will result in an ugly error (or just no menu items).
So i came up with the solution of fetching the menu items through a helper, and then just call the helper function from the view. It makes more sense, because i only have the code in one place (the menu view).
My views are set up in this way: Controller calls "page" view which then loads the header view, menu view, the appropriate content view, and lastly the footer view. The helper is only called from one place, the menu view.
Normally you can't even load models from helpers, but i did a workaround using $i = get_instance(); and then loading the model through that instance; $i->load->model().
I have a feeling this is not the way to go, but are there any better ways?
Edit: To put it in a better way:
I want:
view -> get data -> display
not:
controller -> get data -> pass to view -> display
I'm just not sure if that's "Ok" to do, since it disregards the MVC model completely.

So I found a quick example to cut-n-paste (in this case I have a model called login autoloaded, but you can of course do that manually)
In the file core\MY_Controller.php
class Admin_Controller extends CI_Controller
{
protected $login_ok;
public function __construct()
{
parent::__construct();
/* --- Check if user is logged in --- */
$this->config->load('adldap', TRUE);
$data->login_ok = $this->login->check_login(TRUE);
$this->load->vars($data);
}
}
If you then extend your controller with this. You will have $login_ok available in your view.
This way you can be sure that the required variables are always prepared and you only have to write the code in one place

I think that the solution is easier than you think.
If now you're doing something like this in your helper:
create_menu()
{
$menu_items = $this->db->query('')->result();
// creating the menu here
}
You could just change the function to accept input like this and still follow the MVC pattern.
Helper
create_menu($input)
{
$menu_items = $input;
// creating the menu here
}
Model:
get_menu_data()
{
$menu_items = $this->db->query('')->result();
}
Does this make sense?
Edit:
This is the way I did it on one of the projects:
I extended my standard controller. Within the constructor of that controller I called the model and grabbed the data:
$this->menu_items = $this->some_model->get_menu_items();
Within a view nav.php:
if(!empty($this->subnav_item))
{
// Generate menu
}
This way the MVC is intact, but I dont have to worry about passing variables.
EDIT 2
How to extend the standard controller:
Create a file MY_Controller.php in application/core
class MY_Controller extends CI_Controller {
public $menu_items = '';
function __construct()
{
parent::__construct();
$this->load->model('some_model_that_you_always_use');
$this->load->library('some_library_that_you_always_use');
$this->menu_items = $this->some_model->get_menu_items();
}
}
When you create a new controller, you extend MY_Controller instead of CI_Controller like this:
class Something extends MY_Controller {
}

Keep in mind that nothing about the MVC pattern prohibits a View from contacting a Model directly. That's just a convention that seems common with CodeIgniter.
I suggest that in this case, your menu view should load the menu data directly from the menu model.

Related

How to render a ShapeTemplate without a contentitem?

im new to orchard and my brain is burning because of the MVCSHD model
(Model View Controller Shape Handler Driver)
From Orchard docu:
Shapes are dynamic data models that use shape templates to make the data visible to the user in the way you want. Shape templates are fragments of markup for rendering shapes. Examples of shapes include menus, menu items, content items, documents, and messages.
I would like to display a Shape Template and provide a Model into the view that is not a ContentPart and got no ContentItem.
Because i want to create this Model in the Controller (or in the driver later if i get this working finally).
The content of the model is dynamicly created.
in the Controller this is not working:
TestThingie testThingie = new TestThingie (5);
_orchardServices.ContentManager.BuildDisplay(testThingie,"Summary");
Because testTingie does not have a contentItem...
Is there any other way to display a shapeTemplate with a Model? What am i missing here?
Is it just me or is it kinda impossible to gain furhter Information about how all this stuff is about to work out of the Documentation?
The BuildDisplay method is for crafting the display shapes of a given content item. You don't have a content item, so you cannot use that method.
What you can do however is use the dynamic Display:
public ActionResult MyAction() {
TestThingie testThingie = new TestThingie(5);
return View(myShape);
}
Then in your Views/MyControllerName/MyAction.cshtml:
#Display.MyShape(Thingie: Model.TestThingie)
And in your MyShape.cshtml:
#{
TestThingie thingie = Model.Thingie;
}

Laravel check session on every page

I'm using Laravel 4 for my website, and would like to check on every page load if user has seen a popup, and if not - show the popup to the user.
I don't want to do that in every controller, is there a place where can I put the code, so it's checked before every page is loaded?
You can create a filter to check if the popup is shown.
// app/filters.php
Route::filter('popup.shown', function()
{
// Your check logic here
});
Then, you could use that filter in your routes, controllers or a base controller which you could extend to have this functionality:
class PopupController extends BaseController {
public function __construct()
{
$this->beforeFilter('popup.shown');
}
}
Then, extend this controller:
class MyController extends PopupController {
public funcion getIndex()
{
// this will run the `popup.shown` filter
}
}
You can read more about beforeFilter() here:
http://laravel.com/docs/controllers#controller-filters
Another approach would be to use the App::before() event, so the check would be done on every request. However, I don't recommend this one as it's not flexible and you will have to modify it soon or later.
I would approach this via a view/template style. Although if you use a lot of templates that don't show this popup then maybe the filter method suggested by Manuel Pedrera is best.
In global.php or some bootstrap file you can set a view variable that is injected automatically. http://laravel.com/docs/responses#views
// Perform popup logic
View::share('showPopup', $logicResult);
And then in the various layouts you want to include this popup you can check for the variable within the view. http://laravel.com/docs/templates
#if ($showPopup)
<div class="popup">Popup</div>
#endif
The advantage of this is that you do not have to include the variable to show/hide the popup for every View::make() call.

Joomla 2.5 custom mvc component: different form for task add

I'm developing a custom mvc component for Joomla 2.5.
For my admin section I included a "New" button in the toolbar.
By clicking this button I want to display a separate form with less
fields. So far everything works out but the buttons of the view's
toolbar won't redirect (i.e. 'Cancel')
To redirect the task 'add' I added an override of the method "add()"
to my controller:
class ArchitectProjectControllerArchitectProject extends JControllerForm
{
public function add()
{
JRequest::setVar('layout', 'add');
$result = parent::add();
return $result;
}
}
I don't know if I'm on the right track. Probably someone can give me a hint?
If you wish to redirect for example on 'Cancel' then try the following in the controller:
public function cancel()
{
$this->setRedirect('index.php?option='.$this->option.'&view=yourview');
}

kohana view from what controller?

I have a view that could be called from any of 3 actions from one controller.
But, that view should be slightly different depending on what action caused it (it should display 3 icons or 2 or one depending on action called). Can I check in the view what action caused it so I can use if statement to check whether display each icon or not?
Thank you.
Of course, you can pass action value directly to the view:
$this->template->action = Request::current()->action();
But View should not know anything about Request properties, its a Controller logic. I suggest you to pass special flags from your actions:
public function action_show1()
{
// show only one icon
$this->template->icons = array('first');
}
public function action_show2()
{
// show another two icons
$this->template->icons = array('second', 'third');
}
public function action_showall()
{
// show all icons
$this->template->icons = array('first', 'second', 'third');
}
Or set special flag (variable) for every icon.

ExtJS 4 how to create and display a new controller/view from another controller/view?

I have looked over lots of examples of ExtJS 4 MVC, and they all pretty much show the same thing: The application creates a viewport, loads in a view, and has a 'controllers' defined, which init's the controller:
Ext.application({
name: 'AM',
controllers: [
'Users'
],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [
{
xtype: 'userlist'
}
]
});
}
});
Thats great, but now let's say in my application I want a button contained within my view to open a whole new controller/view, how do you do that?
I think what I am looking for is a way to say something like:
- Create Controller (run it's init code)
- in the controller init code, create the view and display it
Is that correct, and how do you do this?
I want to clarify that in my case I would need TWO individual instances of the SAME controller/view combination. For example, I might have a view with a tab panel and two tabs. I then want to put TWO separate instances of a 'Users' controller and 'user.List' view inside each tab.
I think what I am looking for is a way to say something like: - Create Controller (run it's init code) - in the controller init code, create the view and display it
In extjs, all controllers get instantiated when the application is loaded. You can use the launch method in the Application class to start off a view. And Have a controller listen to events of that view. In a controller, you can always access the other controller using the application object:
this.application.getController('ControllerName1').displayListPanel(options);
In the above code, I am calling a method displayListPanel that is available in ControllerName1 controller. This method holds the code to display a view (a grid panel) onto the screen. Similarly, I can have methods that create views like a new form for data entry. Here is another example:
this.application.getController('ControllerName1').newDateForm();
and In my method:
newDataForm : function() {
var view = Ext.widget('form',{title: 'New Data'});
view.show();
},
Just checked the documentation of new controller and view classes.
It seems to me, that you could always find needed view when you need it.
For example you can:
//somewhere in controller
this.getView('Viewport').create(); // or .show()
check this and view class methods:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.app.Controller-method-getView

Resources