So I have been reading through From Apprentice to Artisan by Taylor Otwell, Laravel Author
And I came across this 'mantra' : HMVC usually indicates poor design.
Which is kind of true...
Also Taylor has suggested
Feel the need to call controllers from other controllers? This is often indicative of poor
application design and too much business logic in your controllers. Extract the logic into a
third class that can be injected into any controller.
And I don't seem to find such way yet..
How can I avoid HMVC and extract the logici nto a third class that can be injected to any controller?
I came up with a neat way to do it, and it seems to have helped me speed up my workflow...
I think this alternative I made can replace HMVC, as well as the conventional way of using controllers... as now controllers are but somehwere where our -what I called- 'motors' are injected.
Check out my article at coderwall where I went through the whole thing.
Read through it, and hopefully it will provide a better way of doing things, starting from the models to and finishing at controllers.
However if you wish to proceed your own way, make sure what was required to be shared between two controllters hiarchecly gets shared in a more neater way, as taylor suggested, shared through injection.
For instance, you are in AdminsController and you feel the need to call an action from UsersController, just make that action and its siblings into a third class, and in your AdminsController
//AdminsController
use ThirdClass;
public function __construct(ThirdClass $mything)
{
$this->myThirdClass = $mything;
}
public function mySharedAction()
{
$this->myThirdClass->mySharedActionFromUsersController();
}
And like so.
Update
If you have gone through my article at coderwall, the one I have mentioned above, I have made a little package that generates all of the mentioned components in there.
Check it out at github
Related
Well i'm learning Symfony (3.3) and i'm little confused about Service Container. In first tutorial the lector show register, login, add post, edit, delete methods in User, Article Controllers. Then in other tutorial, they show same methods but use Service Container (User and Article services) with User and Article interfaces. So .. what is the best practice for implementation in Services instead of Controllers.
I would like to add to Alexandre's answer that it is considered best practice to keep your controller 'thin'. In other words, only put code in your controller that really has to be there (or if it only makes sense to put it in your controller).
Services are like tools you can use in your application. A service in an object that helps you do something. In one service, you can have many functions. I think the best way to understand the difference is that a controller is for one specific action, a service can be used in many actions. So if you have parts of code that you want to use in more than one controller, create a service for it. And for the sake of re-usability, create functions in your service that do only one thing. This makes it easier along the way to use these functions.
the "best practise" depends on what you want to do with the Service. If you build an REST-Api you might want to do Database-Operations in Controller. Why? When you rely on the SOLID-Pattern you want to reduce or eliminate redundant code. If you code a real REST Api you don't have redundant code because each REST-Verb will do a different query/thing.
So in a non-REST-Api-application you will have a lot of redundant code. You do the same things/services on different pages/controller-actions. So the best thing is to implement all the business-logic in services to have it only one time in one place. If you have a lot of individual queries place them into repositories. If you have business-logic that fit's into an entity-class place them there. So in my opinion you can choose a thick controller/no service design in API's and a thin controller/thick service design in classic symfony front-/backend applications.
But one more thing: there is no totally wrong way to design an application. But if you work with other people or want to run the application longer than a month (without having trouble to maintain it) you should pick a common design-pattern.
Controller must implement the application logic like check if it's a post request or if a form is submit etc...
Never use DQL or any SQL Request directly inside a controller !
EDIT In the example i use a find method inside the controller because it's a Repository method but i parse the result inside slugify (my service method)
Services contains business logic like formatting phone numbers, parse some data etc...
Of course you can inject a repository inside a service and call your methods inside it.
An example:
//This is a fictive example
public function indexAction(Request $request) {
//Application logic
if(!$request->get('id')) {
//redirect somewhere by example
}
$article = $this->getDoctrine()
->getRepository(Article::class)
->find($request->get('id'));
//Business Logic
$slug = $this->get('my.acme.service')->slugify($article->getTitle());
}
Hope this helps
First question on StackOverflow (I don't know if I'm doing this right, so sorry if I mess it up)
Background:
My controller has a method that list all actions in my app and plugins called getActions().
And I need to use getActions() in a Helper that overrides HtmlHelper->link() method, because the purpose of this method is return null if the link is forbidden by Acl, thus not rendering any link that would lead to a forbidden action.
Question
How to share this method? I'm doing this wrong?
Lib is the right way to go?
This doesn't seem right: In CakePHP, how do I call an AppController method from a helper?
Don't share the method, share its output. as mentioned in the link to the other question.
I assume that this data is static, meaning: if it will be called from any part in the application, it will return the same value.
Call the method in the controller, store its output in a view-variable or in the session, and write a helper that will access this information and do the acl logic.
It won't break the MVC and will avoid DRY.
The right place for the method is Lib, because its a general purpose method that is going to be used in differents places with differents objectives.
CakePHP's core has many examples of this approach like: CakeTime, CakeNumber and others.
Others examples could be seen in some of CakeDC plugins too.
IMHO #yossi was right about "assuming the data as static", but his approach of storing the data in Session just would make my code more confusing.
In my particular case I'm taking the Lib way. Thanks for the help.
I have read a lot of SO topics about this already, but still haven't found (or have been able to create) a proper answer.
I am working on a small MVC framework and I want some global class/object that I can call from my controllers (but maybe models too).
There are a couple of routes I can take:
Global variable
Static class/Registry
Dependency injection
The internet seems to agree that the DI is the best route to take. I think I have grasped the idea, but am not comfortable yet. So I want to throw in some background information; I will probably be the only one working on the project, it is a small project, all my controllers extend the main Controller (so I could just load one library like class there).
As a concrete example, I want to have an array of categories. So I started out with putting that array in the CategoryController. But now I noticed I kinda want to use that array in my frontview and in ProductController as well. Obviously I don't want to load all of CategoryController into ProductController.
You could also say I could put that array in some kind of configuration or settings file, because of the simpleness of this example, but that's why it's an example. I will probably expand on it with more functionality.
So to summarize: In PHP (specifically inside a MVC model) how can you give your classes (mainly Controllers) access to some kind of common class or other sharable functionality.
Your controllers are created by "something" (usually a front controller). So when the controller is created, you could inject a dependency injection container.
And in your configuration/bootstrap (before the controller is created), you should add you categories to the container.
That way you can access the categories from every controller.
Please note that this is a simple example that doesn't totally fit the spirit of dependency injection. The best solution would be to inject directly the categories (instead of injecting the container). But that can become a lot of work if you generalize that pattern (lots of dependencies to handle in your front controller).
A solution would be to use a dependency injection framework that could do that for you.
For example I work on a DI container that lets you inject stuff with annotations (PHP-DI), but there are several other libraries for DI so you have a choice.
My 2 cents:
In a small self-made mini-framework I have done some time ago, I have created a global singleton class named Application, and anything/everything which should be accessible from anywhere/everywhere was a property or method of this class.
In my case, there was a $db property for database access, a $user property to access the user data and methods, an $input property for a "powered" $_REQUEST access, and so on.
Of course, you have many other options, suitable for different scenarios. This approach simply worked fine for me on that occasion.
Now, if you want to access a controller from another controller, this really sounds strange. This "thing" that you want to access should be a model class, a library class, or anything else, but it should not be "locked" inside a controller class. Indeed, the controller should be "as thin as possible", and focus on calling the appropriated methods from other classes, based on the user input (request) and then calling some output method to generate and send the answer (response).
Finally, although I've read some criticism and complaints about it (as well as praises too), I do make use of static methods a lot, mainly for classes which are more "helpers" than anything else.
I have a doubt with the implementation of the model and can not find a reasonable explanation for the problem.
I'll give you an example I'm working, it is an MVC implementing a blog.
I am ControllerPost which is responsible for control of reading a particular post Blog
consequently have the ModelPost
the ModelPost must contain all methods needed?
method getPost()
method getComment()
method getArchive()
or should I isolate the methods?
ModelPost
method getPost()
ModelComment
method getComment()
ModelArchive
method getArchive()
this causes me much confusion, I see examples but no proper explanation.
I hope that was clear in my doubts, otherwise try to be more explanatory
Thank all
In most projects I've worked on, we've had a model class for a database table.
Using mostly Zend MVC, that would mean extending the Zend_Db_Table classes for each entity.
So in your case, if the comment, post and archive are different tables (which I suppose they are), I'd build separate classes with get, update, insert and delete (and other similar) methods.
This might steer a bit off topic, but I suggest you look into domain driven development (DDD):
There are links to some good reading material here: Domain-driven design with Zend
Also give this a read:
http://phpmaster.com/building-a-domain-model/
http://phpmaster.com/integrating-the-data-mappers/
http://phpmaster.com/an-introduction-to-services/
The main thing about the DDD is that it switches your mindset from thinking about database tables, more towards thinking about the main logical parts of your application, and then slowly adding a persistence layer below it and the application and service layers above it.
I've been working on creating my own MVC app in PHP and I've seen a lot of differing opinions online about how exactly this should be set up. Sure, I understand there seems to be a general "It's MVC, it is what you make of it" approach, but I'm running into 2 seemingly conflicting viewpoints.
A little background on my app: I'm using smarty as my presenter and an object-oriented approach. Seems simple enough, but I'm trying to figure out the ubiquitous "what is a model" question.
If I take a look at some tutorials and frameworks, they seem to view the model as strictly a class that inherits DAL methods from an abstract class, with a little bit extra defined in the class itself as your data needs differ from object to object. For example, I might see something like $productModel->get(5) that returns an array of 5 products from the database. So what if I need to query multiple models? Do I store all of the data in the controller or an array and pass that to the view? Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view? This seems bad, especially because I then have to pass in things like "controllerName", "controllerData", and my View::render() method gets hugely bloated with parameters, unless I pass in the controller itself. Maybe I'm missing something here.
Let's say I want to make a login that queries a users table. Login is a model or a controller, depending on certain implementations I've seen online. Some implementations (I'll call this method 1) make a LoginController with method login() that might do a comparison of $_POST and what's returned from the user model instance $user->get(1) to see if a user is validated. Or maybe login() might be a method in a default controller. On the flipside, an implementation (implementation method 2) that resembles more of a Joomla approach would make a Login model and declare all of the actions inside of that. Then any data that needs to get assigned to the view would get returned from those methods. So login->login() would actually check post, see if there's a match, etc. Also the User model would probably be instantiated inside that model method.
My feelings about 1: The controller is fat. Additionally the controller is storing data pulled from models or passing in ten thousand variables. It doesn't seem to jibe with the idea that the model should be passing data to the view that the controller should be blind to. Also, let's say I want to wrap everything that is in a specific model handled by a specific controller in an outer template. I'd have to copy this template-setting code all across my controller functions that interface with this model. It seems grossly inefficient.
My feelings about 2: It doesn't make for having actions that aren't model methods. If I want to go to my site root, I have to make an index model or something that seems like overkill in order to have a model that passes data to the view. Also, this doesn't seem to be a very popular approach. However, I do like it more because I can just do View::render(mymodel->func()) and ensure that the data is going to be passed back just the way I like it without having to crap up my controller with code merging a thousand query results together.
I've waded through far too many religious arguments about this and want to know what you guys think.
I've built my own framework in the past too so I know what you're going through. I've heard the saying "build fat models" and I agree with that -- as long as the main goal is to return data. I considered the controller to be "The Overlord" as it manipulated data and directed where it should go.
For a login controller i might create something it like...
Post URI: http://example.com/login/authenticate
LoginController extends ParentController {
public function authenticate() {
$credential_model = $this->getModel('credentials');
// Obviously you should sanitize the $_POST values.
$is_valid = $credential_model->isValid($_POST['user'], $_POST['email']);
$view = $is_valid ? 'login_fail.php' : 'login_success.php';
$data = array();
$data['a'] = $a;
// .. more vars
$this->view->render($view, $data);
}
}
In my opinion data should always flow from the model -> controller -> view as it makes the most sense (data, manipulation, output). The View should only have access to what it has been given by the controller.
As for this...
Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view?
Well I would imagine you're building a 'base' or 'parent' controller that gets extended off of by your dynamically called controllers. Those child controllers can have properties that are needed for for the view to render -- honestly I'd need an example to go further.
Hopefully this helps a bit. If you ask more specific questions I might be able to give a better thought out opinion.
If you're writing your own app, I think the best solution is to do it yourself and find out.
Ultimately, whatever makes the most sense to you, and whatever makes it easier for you to conceptualize your app and quickly add to or change it, is going to be your best option.
If one way is "wrong", then you'll find out through experience, rather than someone else telling you. And you'll know the entire situation that much better, and know EXACTLY why one way is better.
What helped me when I was writing my own framework in PHP was, strangely enough, CherryPy. It made the concept of an object-oriented web app so simple and obvious, and I enjoyed using it so much, that I modeled the basic structure of my PHP framework to imitate CherryPy.
I don't mean to imply you should learn CherryPy. I mean that simplicity, clarity, and enjoying developing with your own web app go a LONG way.
If I were to give one piece of specific advice, I'd say try to avoid retyping code; write your code to be reusable in as many situations as possible. This will not only be good for your app, but for future apps you may write or work on.
You might check out Eric S. Raymond's Rules for Unix Programming. I think they're definitely applicable here.