I'm trying to implement mvc design pattern to my existing dating-web-app project. I believe I understood the concepts and created a login model and controller without any problems. Basically, I have a base controller which initiates a view object on construct. Than I use that object to send information to the view from within the controllers as method parameters. However, I couldn't decide how to send variables to the top menu view. Since this menu displays dynamic information (request count, notification count,etc) and included in every page of the application, only two options come to my mind:
Send information to the view from every controller, which seemed like reuse of code.
Put a seperate action in the base controller and make it called automatically when other controllers extend base controller.
Which one should I choose? Or, is there a better way to do this?
Related
As I understand it the "MVC" came before the web and is often used in Desktop software for example.
If I understand correctly, the Controller runs at the time that the user will click a button and this will trigger an action.
But if we talk about web pages, the scenario is a little different, assuming the user clicks a link then it triggers an action.
But then, came me the doubt, is the home page part of a Controller?
What I mean is, the homepage is not usually performed by a user action within the website is just the home, but noticed that many PHP frameworks use a Controller for the home, is that correct?
Another doubt is in my "home" I have several items, for example:
banners
featured posts
recent posts
Each of these items would have a different Model, can I call more than one Model and a View into the Controller?
Would these be the correct steps? Or most of php frameworks are not strict?
You are completely right and I understand the confusion.
In a pure MVC approach, the Controller only listens to user actions and updates the Model accordingly. The Model then notifies the View (through the Observer design pattern) and the View updates itself, accessing the data it needs from the Model.
This is how it was done before the web, in desktop application, where the Model and the View are running concurrently, and where the Model can notify the View. The Controller doesn't set up the View.
In this pure MVC model, the example you mentioned about the homepage doesn't need a Controller indeed. The View would just render itself, accessing the data it needs through the Model. Controllers are very thin and only listen to user actions and update the Model. That's all they do.
In the web, this model is not possible, and thus there are alternative approaches. The Model can't notify the View as in the pure model, and thus what popular frameworks require you to do, is to set up the View in your Controller. That's why for your example of the homepage you need a Controller, as you will set up your view there with all the data it requires.
However, there is another approach I have been personally writing about, where Controllers don't set up the View which allow you to keep tiny Controllers. You can read about it here: A better OOP approach to building MVC applications
Thus I believe that the homepage shouldn't need a controller action at all. The View should just render itself and access the data it needs to render. The Controller's role is to handle user actions and update the model accordingly, as you said. If it does more than that, it probably violates SRP. The Controller shouldn't set up the View, instead, the View should get its own data from the Model.
I have a blade template called 'main' and I wonder how I can render a sub template by calling a controllers method in my main template. Lets say I have a Controller WidgetsController with a method getSubView. The method returns a specific view with some data from (for instance) a database.
I already tried to #include a template but this will not call the controller which sets some necessary data to the view.
Thanks.
views don't call services, they only take variables and put them on screen for presentation.
you're on the good side with #include(). you only need to gather the infos for that sub view beforehand in the controller, and pass it to the View::make('main')->with($vars).
you may also consider using another <?= View::make('subview')->with($vars->sub);?> within the the view. or just use the #extend functionality.
I don't entirely understand your question.
I think what you are looking for is a View Composer
It allows you to get data for a subview without having to create the data in every controller.
The following code is in my FrontController. The run method should call a controller action which belongs to a given url. For example http://localhost/admin/index should point to AdminController and indexAction.
This works already, but what's the best way to call additional controller actions, for example a action for building a navigation of my site or a aside box (is not in the main section of the site) with some information. A navigation is needed at every request, so this would be no problem to implement, but when I have to call some actions which depends on the main action, how to structure this?
My first approach was to call other controller actions in two methods like runBeforeMainController or runAfterMainController. A global config holds the info for main controllers which sub controller (actions) needs to be called before or after the main controllers call.
My second approach was to think about a hook / event system. But I didn't come to good theoretical solutions. Do you have some tips or suggestions for this approach?
// in FrontController
public function run() {
$strController = static::getControllerNameFromUrl();
$strAction = static::getActionNameFromUrl();
// call actions before main controller
$this->template->main = $this->callMainControllerAction($strController, $strAction);
// call actions after main controller
}
I think HMVC is what you're looking for. The H stands for hierarchical. Basically you are using multiple mvc-constructs. Your site gets more modular and one request may result in different actions.
Afaik there are already some PHP frameworks using this approach.
I'm fairly new to the MVC architecture but I'm picking it up nicely, having my own framework almost done.
Nonetheless, I'm having a 'design issue', how to call the controller?
The controller, as in the function that checks if the user hit the submit button.
Example of controller:
$class->login($_POST['username'], $_POST['password']).
I know a lot of MVC frameworks and apps call it by the URL with $_GET params, but I think it's stupid to have one method or one class for each page that needs a function like logging in.
How do you guys do it? What's your method for this?
Any help is appreciated!
You might want to look up the Front Controller concept (and inversion of control), which you are probably already using in some form, but may not know it. The Front Controller analyzes the URL and current state of things, and determines what controller to load.
In my framework I have "routes" that have attributes, one being "require login". The Front Controller determines what "route"/controller needs to be run and checks for pre-requisites for that route, like login requirement. If the user isn't logged in, then the login "route"/controller is loaded instead of the requested "route"/controller. If login is successful, then control is passed to the appropriate "route" controller.
It shouldn't be the job of each controller to manage logins, only one controller should do that, usually the front controller. Any controller should be able to be loaded under any URL since it's the front controller that determines what controller to load. The sub-controllers don't know "why" they are loading, only that they are loading to do their 1 job.
You could have a base controller which contains a function, requireAccess($access_level). Other controllers would extend this controller. requireAccess() would redirect to the login page if the correct access level is not present.
As for redirection using GET variables for clean urls in MVC, I would not recommend this. It could cause problems down the line with wanting variables that contain slashes in them. Instead we would typically want to get the original request uri, and parse it ourselves.
Typically MVC urls follow the pattern /Controller/Action/Id/etc
In Zend Framework, I have a common use case where I need to propagate the same information in the top section of a view across a particular controller.
For example, if I have a "Book" controller, I want to display the summary book information at the top of the page, and have a tabbed interface below the book to display comments, detailed info, etc. Each tab is an action in the books controller. What is the recommended way to propagate the summary information across the views in the controller such that:
I am not continually fetching the summary book information in each action.
I am not repeating information in my views.
I though of using a Zend View Helper, a placeholder, or the action helper ($this->action...) from within the view.
Any suggestions?
Sounds like you'd want to fetch the book information in an init() method on the controller:
class MyController extends Zend_Controller_Action
{
protected $_book;
public function init()
{
// get the book data/model, etc
$book = $this->_getBook();
// if necessary, store the book for use in the actions
$this->_book = $book;
// store the book in the view
$this->view->book = $book;
}
}
If an action only renders the book info, then you can probably get away with empty action methods, letting the view scripts do their thing.
The only downside to this is that it gets the book data on every action. So if there are some actions that do not require the book data, then you'd be eating the overhead of fetching it.
I would load the tabs' contents dynamically (should be easy to integrate with your current solution via the action helper AjaxContent. Just load the action's response into your tab container.
If you decide to stick with a non-ajax solution, the code is forced to be repetitive since you need the same piece information on more than one page. A partial should be better suited for your needs since a view helper performs some kind of logic (or proxies for logic) while you only need it for presentation & markup.
The information fetched should not be that hard on your system, assuming you are using some smart cache method (perhaps one cache entry for each section/tab).