there are cases when i require to run the same logic both in controller and view, i thought they may have a shared code, for example when to display an edit link and the same logic should check for edit permission in controller , where should i keep such code so that same can be used in controllers as well as views, I am okay to write a a component wrapper and a view wrapper for this method but the core logic should be common.
Some mentioned bootrap is a place but putting there do i have all the cake defined parameters or constants available from that location? or there is a better place
EDIT
I gave only authentication related example but there can be more cases like, a view helper for displaying data/time based on offset time set in database (system time + offsetime), i have been forced to use of same code in controllers also (ajax output). What does it imply that in common code we not only have shared logic but also some shared data too, so for only session classes appears to be providing shared data!
On the whole, I'm inclined to say you're not going about this the right way. If you have to include the same piece of logic in both the controller and the view, chances are you're doing the same work twice, which is always a bad idea. DRY (Don't Repeat Yourself) is something you probably heard about a million times before.
However, in the case you mention (authentication): this is done in the Controller, which relies on the Model layer to find out if the user has the permissions to see/use edit links.
Based on the data the controller receives from the Model layer, it should do one of the following things:
choose to render a specific view (with/without edit links)
Present the user with an error view
redirect to the login
For the first case, an editable and non-editable view, you can choose to use the same view script, and use a helper to pass on the session information to the view. Effectively giving the view the means to check a users' session, check if the user in question has the rights required to see the edit links and render them...
Another simple fix would be to set a property of the view to true for editable and false for non-editable in the controller, and check that bool flag in the view. No extra logic required.
The main thing here is that what you're after is authenticating the user. By the time you reached the view, the route is a given, there's no way back. If you find yourself still having to validate the users' identity, you've made a mistake at an earlier point: the controller, and model layer is where this kind of core logic should reside.
A view contains no logic other than its own: a loop or 2, some if-else's... nothing more.
The rule of thumb, then is: the first thing the controller does is authenticate the user. The authentication itself is the concern of the Model layer: no actual core/business logic should be in the controller. Based on the findings the model layer returns (authentication failed, or user has rights to do X, but not Y), the controller can redirect, throw errors or choose to render a specific view.
Only after all these things are performed the view is brought in. If there's a user in play, the view can assume that this user is valid, and has the rights required to see its contents. The view does not validate data, nor does it authenticate users.
To authenticate a user the Cake-specific way there's a core Authentication component that seems to be quite well documented. See if you can't use that...
You can add simple functions to bootstrap, but another option would be to create a class in app/Lib/ using static methods. Then from any controller you can include the library and use the methods defined:-
App::uses('MyLibrary', 'Lib');
If all controllers need to use these just include the library in AppController.
For your views I'd then consider defining a View Helper that would apply the methods used in MyLibrary.
Related
I'm doing registration and login form using cakephp. I'm new to cakephp framework. I have downloaded and installed cakephp on my system. And I've already connected into my database table. I've made few changes in core.php and database.php.
I'm following these tutorials to do registration and login form.
http://alvinalexander.com/php/cakephp-user-registration-form-example-recipe
http://www.grasphub.com/2013/01/simplest-registration-form-in-cakephp/
http://karven.wordpress.com/2009/07/30/create-simple-user-authentication-using-cakephp-auth-component/
I've tried everthing. But none of them does not works. I don't know where i need to create these php files. I'm new to MVC design pattern too... Here anyone give me some step by step procedure to finish this simple task.. I'm not ask any coding here.. I want some step by step procedure..
It may look a bit hard, but when you understand its scheme it becomes super simple:
The model layer handles everything about data. It will silently connect to the database configuration declared in the variable "useDbConfig" in the model (if not declared, it will connect to default config). They are stored in the Models folder. "Handles everything about data" means that it fetches the data from a datasource, validates data that will be saved, formats data, etc.
Models can attach a behavior. Think of it as an "interface" in OOP terms (not the same, but somewhat close). They provide common functionality between them (for example, TranslateBehavior makes data for that model translatable). They are stored in the Models/Behavior folder. You can call them in the array variable $actsAs, or load it on the fly. For example:
public $actsAs = array('Translate');
The controller layer handles all actions that will be done with the data. It will silently instance the model with the same name as the controller to handle the data, but you can tell a controller to instance many different models to suit your needs. They are stored in the Controllers folder. Usually functions in controllers are called actions, because when a HTTP request is handled in your server, it will be delegated to the corresponding function in your controller. Say, http://www.example.com/users/login will call your action login() inside UsersController.
Controllers can attach a component. It's the same as a behavior, but specifically for controllers. They are stored in Controllers/Components folder. For example, PaginationComponent makes the data fetched in a controller paginable, so you can sort it, divide it by pages, etc. You can call it in the variable $components, or load it on the fly. For example:
public $components = array('Paginate');
The view layer handles all your presentation. It means that they have all the HTML + Javascript that the user will see. It's called from a controller after an action is resolved. It silently will render the view inside View/ControllerName/action.ctp, It means that, for example, when login() action has finished, it will then render the view View/Users/login.ctp. Views usually use the layout default to render, but you can change it in the variable $layout inside the controller. You can pass variables from controllers to view through the function $set() in the controller.
Views can use helpers; they are the same as components and behaviors, but for the views. But you have to declare them in the controller in the variable $helpers. They are stored in the Views/Helpers folder. For example, the default HtmlHelper lets you make some tags easier, like <img>, <a>, <script> or <link> for css.
Also views can use elements. They are kind of blocks that you can reuse in any view or layout you want. You just create an element in Views/Elements folder, and use them with $this->element('nameOfTheElement');.
In summary, you for the login you will need an User.php model, an UsersController.php controller, and a login.ctp view. In the controller you will need the AuthComponent to load, because it will handle the login. In the view you probably will need the HtmlHelper and FormHelper, but they are loaded by default. And in the login() function in the controller, you just check if Auth->login() succeeds or not, and take the proper actions.
Once you're more experienced, you can look at the convention called fat models, skinny controllers to be more organized.
Good luck!
I've been doing PHP for years and know how to check if a user is logged in and all that but I can't find a good example of how to do it in the MVC way.
I was thinking if the Controllers for the members pages are like members/memberpage1, members/memberpage2 then I could check the start of the Controller with a regular expression for the word "members" and if it returns true I could then do my check to see if the user is logged in. It would probably work but is it the best way?
Also, for the members pages in the controllers folder is it better to put them in a subfolder called "members" within the controllers folder? I'd definitely be doing that with the views anyway.
The best option would be to check users access rights outside the controller. Authorization is not the responsibility of the controller. You would be breaking SRP. If you want to see how it can be implemented, read this topic: ACL implementation.
As for member-only areas of the site, decision about, whether to show them or to display an error, can be handled wither before accessing controller, or by the Views (you might have some restricted views, if you have active views instead of passive ones).
Though more often you would have both parts involved: authorization service changes the state in model layer, and then view reacts to that change by choosing to include error-message template in the presentation.
Everything does it a different way. I tried building a small MVC framework for PHP and this is the way I done authentication (much like the rails way really:)
Had a 'SessionsController'
The SessionsController contained a method called 'user_is_logged_in' and that returned the current state of the users session. This method was then added to a special method '_before'on any class I wanted to secure.
The main application always ran a controllers _before action before any other methods if it existed. You could also pass 'except' into it to stop it executing on certain actions so it was just a case of checking if the user was logged in in that action.
Of course there are probably more compliant ways to do it as #tereško greatly suggested but it worked for the small application I was working on.
Cake's documentation says "Most commonly, controllers are used to manage the logic for a single model." I'm finding this is uncommon for most of my code, and I don't want to break convention unless it is proper to do so.
For example, my application sends a user to their account dashboard after they log in - this uses data from probably half a dozen tables, not all of which are even related. Do I create a "dashboard" controller for this (even though there is no dashboard model or table)? Or do I create a dashboard method in an existing controller?
Thanks, Brian
I have a similar situation and how I handle it is keeping the actions that connect a lot of models in the controller that is the most centric. For instance, my user can create voicenotes, comments, has settings, has twitter and facebook information. All this information I can get from my user model $this->User->Voicenotes->find('all'), for example.
I believe creating additional controllers might just confuse you, use what cake gives you, you can specify that models are to be used in a controller either by setting the $uses variable or using loadModel in the controller action, if you have your relations set up you can just do it the way i described before, no need to create additional controllers.
I guess it depends on how you want your own app to work and what comes easier in your situation.
I use php and usually structure my application into model-view-controller so its always accessed via index.php with class and method attributes. Class attribute passed as part of URL specifies controller class and method simply method to be called. This seems to be pretty common, but then I'm always having trouble in figuring out what controllers shall I create. What is the best, easiest and most applicable way to decide on what controllers should be created? I understand it depends on web application itself but must be some general way of thinking to get this process started.
I've found that building controllers based on your application's objects works well, and can take care of most actions you'll want for your app.
Take a look at SO -- there's URLs starting with /questions, /tags, /users, etc. I'd suggest a design which starts by creating a different controller for each object. /questions (or /questions/list) returns a list of all the questions. /questions/[0-9]+ returns the details of a particular question with that id number. /questions/ask returns the Ask Question interface.
As you continue building your app, you might find that the controller-based-on-objects method doesn't meet all your needs. For example, on my site (http://www.wysiap.com), I eventually made a /list controller to simplify my Grails URL mapping. But in most cases I did use this method and it's easy to figure out which controller should be doing different actions.
I recommend to think about the pages you'll need in your applications to accomplish all the requested tasks. You'll group similar tasks on the same page and create as many pages as you need. A page can be sliced in different views for specific actions.
With this in mind you could have one controller per page. Each view of the page can have its own method (action) in the controller. And inside the method of each view you can have a switch() that will enable you to have several tasks for the view. Example:
index.php (Dashboard controller)
/question-list (QuestionList controller, action index, display the whole page)
/question-list/add (QuestionList controller, action add, manage the "add" view with tasks like show-form, validate-form, insert-question)
/profile (Profile controller, action index)
/profile/edit (Profile controller, action edit, manage all the tasks requested for your profile)
...
I design most of my web applications this way and using Zend-Framework
Rather than use a full-blown PHP MVC, I'm designing one that will best-fit my uses. I have the basic framework done, and have coded the models and controllers I'll need to run my website.
Now I'm moving onto the Views, and I've encountered a small dilemma. My approach is working fine for me, but for future reference, I want to know if what I'm doing is a bad habit to get into.
What I'm trying to do:
In my View, I'm calling a Model that runs my authentication system, and requesting the login status of a user. I then use that boolean to decide whether to show certain elements within the view, and where to place others.
Should I be designing separate views for each login status, or is this approach fine? However, if I'm going to be implementing this MVC into the work I'm doing for my clients, I need to use the best practices.
Any advice would be appreciated!
Can I call the model from the View?
Yes, you can. As long as you maintain the separation of concerns between M,V and C, you are free to call upon the Model (or the Controller) from the View. Most MVC diagrams show a bidirectional connection at least between View and Model. What you don't want to do though, is place logic/code from the Model (or the controller) into the View and you don't want to modify the model from there.
For example, you might have a widget on your page that aggregates the latest ten blog posts headlines from your favorite blogs on each page of your website. You get the headlines by calling, say MyFavFeeds::getLatest(); in your model. What are your options now?
You could add the code to fetch the headlines into the controller, but that would require you to replicate it in each and every controller action, which is against the DRY principle. Also, the controller's concern is handling user input for specific actions and fetching the headlines on each call is likely not even related to these actions.
If your architecture supports it, you could fetch that data in some sort of preDispatch hook, that is, the headlines get loaded and injected into the View from a plugin or callback. That would be DRY, but a second developer might not be aware of that plugin and accidently overwrite the variable holding the headlines from his controller action. And there might be cases in which you wouldn't want to load the headlines, e.g. when just rendering confirmation pages for form submissions, so you'd have to have mechanism for disabling the plugin then. That's a lot to consider.
You place the call to (not the code of) MyFavFeeds::getLatest() into the View or Layout template or, better, a ViewHelper, that encapsulates the call to your model class and renders the widget. This way you don't have to worry about overwriting any variables or repetition. And when you don't need the headlines on your view, you simply don't include it.
About your other question:
In my View, I'm calling a Model that
runs my authentication system, and
requesting the login status of a user.
I then use that boolean to decide
whether to show certain elements
within the view, and where to place
others.
Authentication is something you will want to do early in the application flow, before any controller actions are called. Thus, you should not run your (entire) authentication system in the View. The actual authentication is not View-related logic. Just requesting the user status after authentication, on the other hand, is okay. For instance, if you want to render a widget showing the user name and giving a login/logout button, it would be fine to do something like
<?php //UserHelper
class UserMenuHelper
{
public function getUserMenu()
{
$link = 'Logout';
if(MyAuth::userHasIdentity()) {
$link = sprintf('Logout %s',
MyAuth::getUsername());
}
return $link;
}
}
If you got larger portions of your GUI to be modified by a User's role, you might want to break your View apart into partial blocks and include them based on the status, instead of writing all the HTML into a View Helper.
If you are only looking to render a navigation based on the user role, have a look at Zend Framework's Zend_Navigation and Zend_Acl to see how they do it.
You can, but you shouldn't. Except for a few extreme cases (and branching your view based on logged-in status is definitely not an "extreme case"), it's pretty much always A Bad Idea to call model stuff from a view.
What you probably want to do in your situation is pass the boolean to the view through the controller. That way, if you change something about the User model, the view doesn't have to know, so long as the controller keeps the behavior the same.
While I only know enough about MVC to get myself in trouble, I've always lived by the fact that unless your view is STRICTLY user interface, then it shouldn't be there.
Also, I've also ran with the idea of thin controllers, fat models.
Going off of these, I'd suggest adding a method to your authentication system model that returns the appropriate view to render and passes that to the view.
Okay, I would really try to keep my Views as logic-free as possible. If you need to switch anything based on e.g. the result of a model method, put a controller in place that delegates the rendering.
Just make sure you follow the basic idea: Do your stuff in the models, Tell your models what to do from your controllers and also tell your views what to show from your controllers.