Why does Joomla separate MVC View into two parts - php

I have been using joomla more than for a year now and familiar with the MVC pattern as well. But I'm unclear how Joomla uses MVC when showing a view. In the components deveopers use below two method.
1st method
class myView extends JView
{
function display($tpl = null)
{
//HTML & PHP goes here
}
}
2nd method
class myView extends JView
{
function display($tpl = null)
{
parent::display($tpl);
}
}
In the 2nd method they create a tmpl folder and place a default.php inside of it. All the HTML and PHP code then goes inside that file.
Now problem is why they use 2nd method when we can right away use 1st method? What's the industry standard? What are the pros and cons of above methods? What should be used and why and depending on what? Thanks

There is no "industry standard". But MVC has such concept as "separation of concerns".
The second approach is much closer to the spirit of MVC-inspired patterns. Views are supposed to be responsible for UI logic. And, if this logic require to generate response, views multiple templates to create it. Or it might choose just to sent an HTTP header.
The first approach is "quick'n'dirt" version. It often means, that UI logic has leaked in controller. Or, that developer does not understand why spaghetti code is a bad thing.

It looks like the second method is calling a parent so it's calling the base part of the template. Often times you have a base template and then individual content (pages) that uses that base template.

Related

Creating controllers in Views

I have a view - PageView - whose output is the concatenation of multiple ModuleView outputs. I'd wish to always initialize views (if necessary) and models in controllers. The reason for this is that I find it easy to initialize the given view based on controller action (many models are associated with multiple views, ie.: front-end and back-end views).
Am I to be beheaded if I initialize a controller in a view? If yes, what approach would you recommend to solve the issue of a view being the concatenation of other views?
PHP code
class PageView
{
public function Output()
{
# $this->modules was set by a method called from PageController
foreach ($this->modules as $module)
{
$module_controller = new ModuleController();
# Will initialize ModuleModel (ID of 23 in constructor) and ModuleView, then call ModuleView->Output(ModuleModel->GetData())
$module_controller->ShowFrontEnd(array('module_id' => 23));
}
}
}
The project is AJAX heavy, hence the need for page and module controllers. The goal is to offer easy extensibility and readibility by those who are experienced with the MVC pattern in PHP.
Yes, you will be beheaded. Controllers should be spawning/handling views, not the other way around. It is no longer MVC if you are initializing Controllers from a View.

Single View class to handle all templates

I just got into MVC architectures and I'm trying to create my own very simple MVC framework that I understand, with only the core functionality without the extras I don't need.
I made a View class, that can handle the rendering of all view templates.
My question is, should I make a View class for every view template instead of using one for multiple templates?
I did not see a reason why I would, but I thought I'd ask and be sure I'm not going against any MVC principles.
class View {
private $_vars = [];
public function __set($index, $value) {
$this->_vars[$index] = $value;
}
function render($fileView) {
$path = ABSPATH . '/view/' . $fileView . 'View.php';
if(!file_exists($path)) {
throw new Exception('View not found: '. $path);
}
foreach($this->_vars as $key => $value) {
$$key = $value;
}
require $path;
}
It kind of depends on your own wishes and requirements. I've seen many different view structures in MVC (like) frameworks. Your options include, but are not limited to:
Using one view class per page (class Login, class EditUser).
Wrapping even parts of the view in separate classes (class Textbox, class Form), with which you ensemble bigger views (class Login would consist of one class Form, consisting of two Textbox classes).
Using one view class to render multiple templates. Class User would then be responsible for rendering an AddUser template, and an EditUser template, etc.
It's all dependent on the size of the application and wishes in terms of performance / resources, programming-ease, readability ...
You should create only one class that handles templates in your framework. You can declare it as an abstract class and then, create multiple, more specific Views (like HTMLView, JSONView and etc that extends abstract class). But generally, your approach is correct. Based on MVC structure, View class should only locate the template file on the disk and render it. All loops and statements should be written within that template file.
In your case, the View class shouldn't be a singleton. For every template being rendered, you should create a new instance to avoid variables in private $_vars = []; getting mixed up within different controllers. The better approach would be to create static method within View class and then, invoke it like this: View::render($args) or View::render($args, $template_name).
You can do this in Symfony2-like style, so controller only returns array with variables to assign in the template (and optionally the path to .tpl, but it's good to define logic structure and force View to find it automatically). Please don't forget about returning correct response from your app, so think of headers, statuses etc.
I strongly suggest you implementing some templating engine to your app, like e.g. Twig. It will make your life easier and the view classes will be delivered out of the box with such an engine.

What to do about those page specific little classes that don't seem to fit as Models or Libraries in CodeIgniter?

In my current implementation of the MVC design pattern (demonstrated using PHP and CodeIgniter):
Let's say I have a "page" located at "www.mysite.com/blue/page" that is ultimately generated by the following (greatly simplified) files:
/libraries
session_lib.php
/controllers
/red
/white
/blue
page.php
/models
/red
/white
/blue
funky_class.php
page_model.php
/views
/red
/white
/blue
page.php
And here's an easy to understand controller:
// FILE: /controllers/blue/page.php
// Get some paramaters from URL
$params = $this->input->get();
// Use a library to do some stuff with these params with a session
$this->load->library('session_lib');
$this->session_lib->store_in_session($params);
// Use a very page specific class to do some funky stuff with the params
$this->load->model('blue/funky_class');
$funkified_params = $this->funky_class->funkify($params);
// Pass params to a model
$this->load->model('blue/page_model');
$data['output_from_db'] = $this->page_model->get_some_output_from_db($funkified_params);
// Send to view
$this->load->view('blue/page', $data);
And now the question...
What is the best procedure for these "funky" little page specific classes that don't interact with the database? In this example I store the little class with the models, and in some cases might just add additional methods inside the model class to do the funky stuff. Is this good practice? Or should the library and funky class both go inside the model so the controller is even skinnier (however the model might be used in other places without the need for sessions and funkiness)?
I would use a helper.
When a helper is loaded, that function will be available in the global scope so you can call it anywhere.
They're great for small, stand-alone functions that do only one thing that is not necessarily related to code in a model or library
Helpers especially excel for me when converting things between one format or another (slugify, convert_timezone, change_query_string) or doing little tasks that you don't want to think about (force_ssl, is_image, uri_string)
funkify() seems like an appropriate helper function that may prevent a lot of repeated code.
Here's the codeigniter documentation page on them: http://ellislab.com/codeigniter/user-guide/general/helpers.html
If you're in a situation where the helper function is so specific it will be only used in one place, you can still use a helper. Name the helper after your controller, page_helper.php for example.
page_helper.php
function funkify($params) {
// do funky stuff
return $funky_params;
}
then in your controller:
class Page extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('page');
}
public function page() {
// do stuff
$funky_params = funkify($params);
// do more stuff
$this->load->view('blue/page', $data);
}
I have no excuse for it, but sometimes if I am in a situation where I need a razor specific function that will only be used on one location (say, a controller) ever, I will put it right in the controller's file. You can paste a function outside of the class definition and it will act like a helper and be available globally (as long as that controller is loaded). You can also define functions inside of a view. Yucky, but possible. I don't like to do it often because it's unusual and not expected (by myself or other developers)

Pagination in PHP MVC

I've written a small MVC in PHP5 and desire a pagination module to be added to some files in my views section/folder..
I was wondering.. would the Pagination class be included in the Controller or Models section/folder?
Currently i've included it in the Models folder and called the function when needed..
The way I see it, pagination is a control, allowing user to tell your database (model), which portion of data he or she wants to see.
So I would go with the Controllers module.
Well, I think a better approach would be to make a helpers folder and then load them into your application like this :
function use_helper()
{
static $helpers = array();
foreach (func_get_args() as $helper)
{
if (in_array($helper, $helpers)) continue;
$helper_file = HELPER_PATH.DIRECTORY_SEPARATOR.$helper.'.php';
if (!file_exists($helper_file))
throw new Exception("Helper file '{$helper}' not found!");
include $helper_file;
$helpers[] = $helper;
}
}
Then all you have to do is build a pagination.php file with your Pagination class.
When you need it, you call the function
use_helper('pagination');
From here of course it depends on you Pagination class.
Hope this helps.
i guess the best approach is to call the pagination from the view, referring to this MVC
A view queries the model in order to generate an appropriate user interface
(for example the view lists the shopping cart's contents).
The view gets its own data from the model.
In some implementations, the controller may issue a general instruction to the view to render itself.
In others, the view is automatically notified by the model of changes in state (Observer) that require a screen update.
and because you will be using this class almost in every view, you should make a helper and include this class inside that helper so that all the views can share its methods

MVC - Can I call more than one (or multiple) controller in class controller?

For projects written in php, can I call more than one (or multiple) controller in class controller? Example in http://img192.imageshack.us/img192/7538/mvc03.gif
ASK: I need to call an action from another controller... And if I do like the picture above, I'm being out-ethics?
Thanks,
Vinicius.
I'm sure that you can do what you want with whichever framework you're using. If you can't do it natively for whatever reason, then you can extend your framework as required.
Having said that, I personally don't like the idea of a controller calling another controller. It seems to somewhat break the MVC paradigm if only from a theoretical standpoint. What I might do instead is build a library class that contains the functionality required and then have both controllers instantiate that class as a member and call the functions required.
For example, using CodeIgniter:
libraries/MyLib.php:
class MyLib
{
public function MyFunc()
{ /* do whatever */ }
}
controllers/ControllerA.php:
class ControllerA extends Controller
{
public function index()
{
$this->load->library('MyLib');
$this->mylib->MyFunc();
}
}
controllers/ControllerB:
class ControllerB extends Controller
{
public function index()
{
$this->load->library('MyLib');
$this->mylib->MyFunc();
}
}
out-ethics? Anywhose... back to reality.
Yes, a controller can call another controller's action. For instance, in cakePHP, this functionality is afforded via requestAction
// pass uri to request action and receive vars back
$ot3 = $this->requestAction('/stories/xenu');
If you're rolling your own, the details of how to implement it will be very specific to your framework.
then you need to modify framework, find place where controller is lounched and add there your second controller.
what framework you are using?
You can do it any way that you want. You don't have to use MVC if you don't want to. However, in MVC you really should only have one controller active at a time. You probably want multiple Views or Models, not another Controller. There is nothing at all wrong in loading, say, a header and footer view for the menu and footer of the site.
If you are building another Controller, then feel that you need to access the functionality of a previous Controller to access its functionality (because it works with a specific / desired Model), then the Model you developed for the latter probably needs to be refactored. IN plain speak, your target Model may be doing too much. Break it up.
You are trying to avoid repeating yourself (DRY) by using calling the methods of a Controller that has already been developed, but in doing so your are creating TIGHT coupling between both controllers! If something changes in the borrowed controller, it will have an effect on the borrowing controller. Not good, Dr. Jones.

Categories