Calling methods from inside views in an MVC framework - php

This is a general question and I'm asking for design patterns, approach, or what terms to even properly search for to determine the best approach. More specifically, I am working on a project in Laravel 4.2, with standard blade file views with a master.blade.php, a header, footer etc.., and they just get built with the View::make('location.of.template', ..) method, passing the parameters as needed.
The views have very little "logic" in them and just present the collection of data provided. I somewhere recall that a model should not know what a view does with the data provided, it was up to the view to manage this presentation.
But what is the rule for using calls to methods inside the view? This seems extremely useful to me and gives the view authority to call an HTML string based on a single element's $id, and relieves the view of having to prepare every possible scenario for the view's sake. This seems very useful for a page that is 100% server-side, and even better if the methods the view would call are also available as APIs using AJAX secondary calls. Is there a generally accepted guideline on when and what type of methods to use in views?

Related

Attaching data from controllers to views in PHP frameworks, standardization

most of the modern PHP frameworks use data attaching method, for example:
View->render('login', $errors); // or
View::make('login')->with(array('errors'=>$errors);
I'm trying to establish a convention, where even if the View designers and the Controller developers do not have a direct communication, they can expect what data to put, and what data to receive,
I have thought of two methods, first using a class that takes care of rendering the views including the data, and this class would contain all types of data which will be used among the platform, second method is to have a naming convention to follow, I personally find the first method better, but I have to note that I'm not a skilled developer, I'm not sure what implications can that method have, which method would you choose?
perhaps another method?
For direct view rendering, you can use View::composer method.
View composers are callbacks or class methods that are called when a view is created. If you have data that you want bound to a given view each time that view is created throughout your application, a view composer can organize that code into a single location.
It is about auto rendering.
You communication convention with designers should be easily done through Separation of concerns pattern.
Blade templating syntax is ideal for that, since it separates logic out of your view. By logic, I mean all data that comes from you domain layer (model,db...).
Using {{$data}} syntax is pretty straightforward and easy to understand to designers.

How can I populate Zend_Layout variables with backend data?

When trying to adhere to established best practices like avoiding singletons, registry, static properties and base controllers, how I can populate my layout(and partials used by the layout) with data that is only used by the layout and common across all actions?
The typical scenario is menu which is built on variable data, like an database. Keeping separation of concerns in mind, the views/layout should never talk to an backend directly, but rather be told what to contain.
Using a front controller plugin is simply not possible without using the singleton "feature" in Zend_Layout. The plugin only knows the request and response object, neither has access to controllers, views or the layout.
Zend's action helpers have init/preDispatch/postDispatch methods. One can add action helpers to the HelperBroker (ex. using the bootstrap) and these will be executed in the normal application flow.
Using the init-method to inject data into the view is not possible since it's trigged before the controller/view is ready. preDispatch/postDispatch is possible, but not perfect, since these methods are always triggered when executing a controller action.
That means that all uses of the Zend_Controller_Action::_forward() will also execute the preDispatch/postDispatch in all action helpers. This doesn't have any big implications for the code except speed, I really do not want to be setting a view (or an view helper) variable several times. One can code around this issue using some sort of $firstRun variable, but I really don't want to track this in my own code.
Another method is doing this in the bootstrap, but in my opinion it really does not belong there.
So, how can I populate my layout/view helper with data from the database, doing it only once and still keep a good separation of concerns?
I've followed the ActionHelper approach, setting the view variables on the preDispatch method. It was the most logical place, in my opinion. In addition, my projects weren't using Zend_Controller_Action::_forward(), so I didn't have any speed concerns about multiple triggering of the helper.
Hope that helps,
You could go with Action Helpers as stated in this answer (take a look at the question too, its pretty much similar to yours)
I'd use action helpers too. Just fill the view variables and display them using plain PHP/partials/render/viewHelper (depending on complexity).
Your problem with multiple runs using preDispatch could be solved using
if (!($this->view->myVar)) { // or array_key_exist or isset - depending on your use case
$this->view->myVar = $someModel->getSomeData();
}
Which is just fine IMO.

Django development - how to lay out and use code properly

Hi i'm a PHP developer trying to convert to Django and im having a bit of a hard time understanding where to put things and how to use the new language. Basically what i want to know is for example in codeigniter i would make classes and functions in my controllers. Where do i do that in django?
I believe the 'view' in django is more like the controller in an MVC framework but all the examples i can find of the view are very simple and just call a template and pass it some data.
I currently have an index view and a 'rates' view in my current project. The index page will call rates via JS and pass it some GET variables. In my php version i used these to instantiate my rates class which when had all the needed functions in it. I want to do this in Django.
The reason that it is called, "MVT" instead of "MVC" is that "View" to Django means, "presentation of data (according to given logic)" and "Template" means, "display of data presented." In a traditional MVC paradigm, "Controller" means "executer of logic" and "View" is "presentation of the result of the executed logic". (They are almost the same idea, but not quite).
So, what does this mean? Basically, if I were building something in Symfony, I would put all of the logic in the sfAction components. In CodeIgniter, it would be in the CI_Controller. In Django, I will place all of the logic in the "Views".
Just like CI (and Zend and others) will then call a "View" from the Controller descendant, the Django view will also call a "Template" from its "View". (Symfony's views are often called in a different syntax, so I will leave that to the reader to research if so desired).
Looking at your example, it looks like you want to call a method in the "View" (which view is configured in urls.py) which simply instantiates another object which has "all of your logic in it". Something like:
def ratesHandler(request):
rate = MyRatesClass(request.GET)
return HttpResponse("Insert something here. ") #or render_to_response
The logic always belongs in the view. You can put whatever logic you like there - no need to put it into a class, unless you want to. If the logic is related to a specific model, though, it is best to make it a method of the model or the model's Manager.
In django: "models" go in models.py, "controllers" go in views.py and "views" go in templates.
Models tend to be classes that subclass django.db.models.Model
Controllers (in views.py) are often functions but you can use classes if you like.
Note that if you're just displaying data from the database you can often use generic views so you hardly have to do any coding at all.
I can't tell whether there is a question in the last 2 paragraphs of your post. If there is a question there, please edit your post so it's clear.

Beginner CodeIgniter concepts - Reusable view code, where to go? (Helper?)

I am a beginner with CodeIgniter still struggling to get a complete grasp on how to use the MVC ideology most cleanly.
I am writing a basic CMS system with the ability to vote on entries and follow people etc, consequently, I have found myself using the same or similar pieces of code across multiple views here and there consisting of various pieces of html and logic such as:
Voting panel
Follow/Unfollow panel
Login/Logout panel
Code to check if a user is logged in etc...
I am wondering where to put this code so it can be unified? I am thinking a helper is the way to go? If I declare the helper in the controller, it can be called from the corresponding view right?
Some of the elements are dynamic - such as a follow/unfollow button - It would need to check if you are already following the user or not and display the appropriate button, which would require a model to check. What I have now is that all the logic is in the controller and it returns an appropriate button, but it seems weird to be returning formed html code in a controller return as well. Should it be more like:
controller checks if you are following someone
the controller passes a boolean to the view
the view calls the helper with this value to draw the appropriate button
Also, as a secondary question, I have been doing a fair bit of looping through mysql arrays in foreach loops to process mysql results returned from the view. It seems like my views are getting somewhat complicated, but I can't think of another way to do it, although perhaps this should be done in another helper as well?
Apologies if this is a naive or repetitive question, there is indeed a lot of discussion surrounding this subject but it is not always easily relatable to another project.
Helpers are certainly one way to modularize anything that isn't DRY. Another is to use Partial Views. CodeIgniter looks like it supports partial views. Here's a good breakdown - not PHP specific but the discussion should be agnostic.
As far as handling user logins is concerned, you will probably want to use a static class and the singleton design pattern, which will allow you to check to see if a particular user is logged in or not anywhere in your application. There is a good tutorial here
http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login
Loading the helper, I don't believe loading it in your controller will automatically load it in your view. I think you have to re load the helper in your view file, or you have to autoload the helper. (cant remember off top of head but Im pretty sure).
Regarding looping through the mysql results, you should be using a model for this, always. Any functions which are grabbing or sorting information from your applicaiton, should be done within the model. Then, in your view file you loop through the results and format the data how you choose to.
When developing http://newspapair.com which has the vote functionality you mentioned I used helpers and custom classes to spread the functionality across multiple views.
Helper - has functions without a class. So a standalone function or group of functions can be placed in a file and saved as a helper.
For instance I used a helper with generic form processing functions for NewsPapair, instead of a static class. But this is not the "best practices" thing to do. I did it this way because I already had the functions from a previous project.
As far a looping through MySQL results, try to write a query that allows the DB Server to do the heavy lifting. This will make your code more efficient. Perhaps ask a question about a specific query with example code. Plus do all of the data gathering in your Model.

Way to bypass the controller in CodeIgniter?

I've been using the CodeIgniter framework for PHP and am enjoying it, but I notice that it seems to require a controller for every view. I'm wondering if there is a way to call a specific model from the view itself, rather than route through a controller. I understand that use of a controller is best practice in most cases, especially where the data from the model needs to be modified in some way, but I have cases where I just need to do a strict data pull to the view (which is loaded via ajax), and setting up a controller for that seems superfluous.
Any thoughts? Thanks in advance!
You're fundamentally misunderstanding MVC, at least as implemented in CI.
All URLs on your site (at least those that utilize the CI framework) are mapped to functions (methods) within controllers.
http://myCIsite.com/controller/method[/var1][/var2]...
It doesn't matter whether the URL is accessed via regular HTTP or via AJAX. This is always a one to one mapping. Because of this, you should think of the controller/method combination as the "web page". Do not think of the view as the web page.
Models and views are subordinate to controllers. The controller delegates specific responsibilities to them - database interaction for models, and page output to views.
Because models and views only serve to perform delegated responsibilities, their use is not required in any given controller/method. Help pages, for example, generally have no need to interact with a database, so there is no model utilized by the controller/method combination that serves a given help page. Likewise, form handlers frequently redirect to another page upon completion of processing. As such, there is no view corresponding to the form handler (but there is (likely) a view called from the controller/method in the redirected to page).
Furthermore, models and views do not necessarily correspond on a one to one basis with individual controllers/methods. Any given model can be loaded and used from within several controllers. Similarly, a controller could have a single monolithic view that is used by all methods, or each method could be assigned its own view. (Or, as I just said, a given controller/method could utilize no view at all.)
Finally, CI does not enforce strict MVC separation. You can interact with the database and echo HTML all from within the controller and CI will not complain. Nevertheless, this separation and delegation of responsibility is followed because logically separating the responsibilities makes the code easier to read and helps you follow the DRY principle in your coding.
The fundamental Understanding is that the "web page" corresponds to the controller/method. The view and model, when used, handle delegated responsibilities for the controller/method.
I'm wondering if there is a way to
call a specific model from the view
itself, rather than route through a
controller.
That's not possible as of what I know, the main abstract class of the CI controller imposes restriction to use a controller otherwise you will get a fatal error.
And actually what you say will break the best practice of MVC design pattern. You got to go to model through a controller not view.
I'm a bit confused as to exactly what you're trying to achieve. The controller's value, aside from just being a clean way to handle incoming requests, is to manage the interaction between the models and the views and to determine which views to load. It's also entirely reasonable to load model data directly from your views, but how did you get to your view in the first place?
I guess I'm just having a hard time seeing the context here..
To run a query via Ajax you still need to provide a URL / path in the javascript call. You can not get around the fact that a controller function has to "catch" this call; you can not map a url directly to a model. All you need is 3-4 lines of code in your controller.
Via URI routing you can map a URL to a different controller, so you don't "require a controller for every view". I always create a controller called "ajax" to handle those requests.
A basic ajax call with jquery can be something like this
$('#prod_img').load( "http://domain.com/ajax/get_img", {'color': 'blue', 'url_title': 'bla' } )
You can echo stuff in your controller, so rather than trying to bypass the controller you should be looking into how to do away with the views. This will actually be easy, you can load the db class in the controller just as you can in a model.
But if you really don't want to use MVC perhaps Codeigniter is not the framework for you.
You should read more into the principles of MVC.
Views are strictly for presentation of data, the model shouldn't communicate with views directly.
But still if that's what you want then just pass $this->db from the controller to the view and use it in the view.
Then again, this is NOT a good practice.

Categories