Let us say I have a controller that takes care of login/registration/password recovery and such in my app. I want to share this across different modules and controllers. What's the best way?
Should I make an action helper, Or use inheritance? Of course I don't mean logic of those action, those are implemented by models (different for every module), I just want to share common parameters, interpretation and passing results to views.
I'm targeting to do some kind of a generic library for those things in my project. So I would have some abstract user model from which all other models that want to use login/registration function will inherit, but I'm wondering what about the controller stuff.
Any idea?
Basically I think what you are trying to create are widgets . Here is an great article how to create them using action helper by ZF team lead http://weierophinney.net/matthew/archives/246-Using-Action-Helpers-To-Implement-Re-Usable-Widgets.html .
Creating a re-usable authentication service is what you want to do. Creating it as a service allows you to test it in isolation. Inject the service into a front-controller plug-in so it is run during each request. The actual checking can be encapsulated into a custom validator so you can simply call ->isValid(). If not valid, re-route to the login page.
Related
I have started a new laravel website project and I have hit a road block in my understanding of MVC. I need to refactor to continue but I don't know the best way.
Currently I have web pages that display the results of a single bit of logic. I.e. A page listing all users, a page listing the details of just one user etc etc - all handled by a userController. This applies to other pages being handled by other controllers.
I have created models directly relating to the tables in my database, and controllers in relation on the models. I moved the business logic from the controllers to services. The controllers use the services to perform the business logic and with the data returned, pass that data to the views.
This nicely groups similar functionality together and works fine.
userTable -> userModel -> userController -> userService
clientTable -> clientModel -> clientController -> clientService
...
In my routes, I have pages which do related functionality use the same respective controller, but individual methods depending on what the page does
/listallusers -> userController#list -> userList.blade.php
/listallclients -> clientContoller#list -> clientList.blade.php
/listdetailofoneclient -> clientContoller#details -> clientDetails.blade.php
This is ok when dealing with pages that do that functionality and (apart from using services) seems to be what is hinted at in the laravel docs.
However, I'm starting to get confused about controllers when dealing with pages that either don't really use functionality from any of the services or pages that heavily require functionality from multiple services (and the data needs complex manipulation like formatting or such).
A basic index page.
What controller would handle this? The index might link to routes that are handled by existing controllers but it probably won't need to display much functionality apart from that. That means the controller won't need to pass much complex -if any- data to the view. You could stick the logic to return the view in the route file but that is pretty tightly coupled.
A page that shows complex client and user data
You need to pass client data and user data to the view from the controller. But from what controller? This is the part that is really holding me back.
Because I have a limited number of pages but lots of logic displaying on each page, I was thinking of making a page controller (or something) which would handle the routing. Although I have looked, I have not seen any real mention of this idea anywhere which makes me think I am either reinventing the wheel or have failed to grasp some basic concept in laravel / MVC.
Would the page controller in this case handle all the routing? Would it handle only the pages with 'overlapping' existing controller functionality and the pages that don't fall into the existing controllers? Is a page controller even a good idea?
Some more points that have made me question MVC from this issue
Do controllers need an equivalent model?
Can controllers 'control' other controllers in order to separate logic?
I'll take a shot at a couple of these questions.
Having a PageController or HomeController is very acceptable. Controllers don't have to be linked to a specific model, for instance an AuthController would handle logic for logging in and out but isn't tied to a model, or PasswordController which handles setting/resetting passwords, or a PaymentController that handles billing routes. A controller is just a way to organize logic for related routes in one file. Static basic pages are related routes so a PageController makes sense to me.
Are users tied to a specific client? If so you can arrange your controllers in a nested way so you have a ClientController and a UserController and your routes look something like this:
/clients/{client}/users //list all users for this client
For heavy data formatting it's probably best to use a service provider and use dependency injection to inject it into controllers where you need to use it. This allows you to detach your data manipulation from your controller so you could change it out if needed. Say you are using a software to make charts, and you want to change it out later - you want that formatting logic to be removed from your controller.
I hope I helped in some way... sort of a train of thought here!
I'm wondering if it's possible to set a route in Cakephp that will allow me to route to a set of controllers where a prefix is set. What I'm looking to do is duplicate most of my controllers but for a REST api.
I'd like to still have all the default controllers for the site itself but have a product controller for instance that only returns JSON. For this I would like to move all api controllers into a subfolder and route to them by detecting /api/controllername.
Is this possible or even the correct way to accomplish this?
What I'm looking to do is duplicate most of my controllers but for a
REST api.
Bad idea. IMHO. You're going to duplicate code very likely and scatter code everywhere. Keep it in one place. This sentence is an indicator that makes me think you have to much logic in your controllers. Move it to models, fat models.
There are several better ways to do this.
Use a prefix for routing to API methods inside your related controllers (api/v1/foo/bar -> ControllerName::api_actionName())
Implement a single API controller that dispatches model methods (api/v1/foo/bar -> FooModel::barMethod($queryParam1, $queryparam2,...)
Implement a service layer that sits between the model and the controllers and implement a dispatcher filter or the API controller from the 2nd suggestion to dispatch the service methods. You'll use services instead of models then. Controller <-> Service <-> Model. To implement this well some experience with the framework and design patterns is required. If its not well done it will probably cause more problems than benefit - IMHO.
If it's a more or less simple API and the API logic is similar to your actions you can simple re-use the same controller actions you already have and just usethe built in REST and JSON/XML view serialization and could still use routing to create a fancy route (api/v1/...) for them. You can then do conditional checks as well if the controller is called as API.
It's up to you which one you pick, I've seen and used them all in action, they all work the difference is mostly the implementation and level of abstraction you need. However, the key point is to write clean and DRY code and care about SoC.
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
I'm thinking of re-working my MVC before I get to far along with it. At the moment it uses a sinle controller which takes the user input and determines the model. The model has maby differ methods which I call actions, because one is called automatically. The model loads its view file, which again holds many different methods. The model can set properties which can be used in the view. Then the controller calls th template classwhich parses the output for display.
Is this the bst way to do it?
Or should each different part (news, contact, about) have its own controller, which loads a specific model and view. Essentially, instead of grouping methods into a single file, it uses multipe files.
I'm kind of lost as to how I should do it.
Cheers
Start using a MVC that works and is well-known like in Symfony or Cake. From that you will decide:
what do to in your own, knowing the best practices;
to drop your own if you feel like you can save time by using theses.
If you are thinking of advancing your own MVC model, like #e-satis have said, you will need to experience what is happening in already developed systems. However, as based on my experience in designing MVC model and determining what is there in opensource community, I stick back to my own MVC for two good reasons. One reason is the flexibility of customization and the other is own MVC privacy.
I used the following approach for MVC design pattern.
A Router.php file identifying user-request urls. This router will be able to fetch controllers and include the file and call the controller default method.
The loaded controller is also able to load other controllers if required to function. This is done using a global method, where all controller Class will extend to a MainController Class which is able to call to other controllers.
I do use a global registry to set and get variables from one controller to the other.
The Models are used to get the Data from Table, and most of my Models will represent Database functions which includes CRUD (Create Read Update Delete). So that a controller can easily manipulate database table data using a model.
Naming conventions in all controller, models, and views is also important, if you want to system to be more intelligent to identify the required action knowing the file name.
I use the Views separately for each type of controller. And these views will be sent to a Master Template View file.
Same as models, the controller will be able to set Views to Master View.
There are other customizations which you can do, like applying security methods before calling a class, or after calling a class/controller/model/view etc.
This is done by the MainController, which it will always look into a folder with autoload class which states what files should be loaded before and after of different actions during the process of building the content and delivering the output.
MVC is not a small scale idea, but it is a design idea which can always be developed. There are so many PHP MVC open source frameworks to be found if you know how to search the major search engines like google.com
But I do advice you that, MVC is not a good solution if you are simply developing a small dynamic website, as it will consume more time in developing compared to developing small websites. MVC is ideal, if you have business logic and needs system automation in order to avoid most routine tasks of developing, and like that I would say MVC is most ideal for larger applications.
The model loads its view file
The Controller should act as a Mediator between the Model and the View.
The Model shouldn't be aware of the way the view renders it, and also the View shouldn't be aware of any kind of logic of the Model.
In theory, if your MVC is well structured, you should be able to represent the same Model with different types of Views (HTML, XML, JSON for example).
Build FrontController which parses request uri and decides which controller to load and which method to run. With .htaccess rewrite all request to index.php
//index.php
class FrontController{
function run(){
//parse request uri here /comment/new
//load controller comment
//run controllers method new and pass some request attributes
}
}
// ../controllers/comment.php
class Controller_Comment extends Controller{
function new($request){
//do stuff here
}
}
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.