Is it bad to inject controller class into a controller class? - php

By trying to follow single responsibility principle, I decided that rendering form view I could move to another class. Also to render form I already am planning to use 5 dependencies. So the main controller which injects form will have less dependencies which is good.
I never injected controller classes into a controller class. What I usually do is I create the library. I have libraries folder made as sibling to controllers folder.
But now thinking - maybe better idea would be to have another controller injected into a controller?
Tried to search for this, but did not find any examples. But at the same time tried creating controller with just constructor function and echo a string. Then inject this controller into another. And string gets displayed.
So this means it is possible to inject controller into controller. So is it good? Or maybe this would be a must?
By default laravel do not even have libraries folder which is interesting, maybe creators assumes that it is not needed.

Yes it's bad. Controllers not only must have one single responsibility, but they are also a different kind of class that should have only one job: A controller is a proxy between the HTTP request and your application (models, repositories, views). So basically it should receive an HTTP request, get some data from your models and pass it away to a view.
Everything else should be done by your support classes (models, repositories, helpers, composers, etc.).
If you are in need to call a second controller class, it's probably because you need methods on that controller that should not be in that controller, because your controllers are doing more than what their job is.
This is one of my controllers:
class Connect extends BaseController {
public function index()
{
$connections = $this->execute(GetConnectionsCommand::class);
return View::make('connections.index')->with('connections', $connections);
}
}
There's a lot happening behind the scenes in that GetConnectionsCommand to get the information to show all connections, and my controller should not know any about it all.
There are some subviews on that ´connections.index´ view, but calling subviews are a view responsibility, my controller doesn't have to know that a particular view needs subviews to be rendered. I can have a master view and some #ifs inside it to render them all properly.
A controller returns data (a rendered view, rendered by another class) back to the response object (behind scenes in Laravel), which is the guy responsible for effectively rendering the data which will be passed back to your browser. So a controller is right in the middle of something, doing very little orquestration, because, the more it knows about your business logic, the more you'll feel it needs to ´talk´ to another controller. You can think of it as MVP if you like, but this is pure MVP using the Single Responsibility Principle as it should be. But in this case the Controller is not decoupled from the view, because there is no Interface between them, so it's not really MVP.

Related

PHP MVC: Too many dependencies in controller?

I'm working on a personal HMVC project:
No service locators, no global state (like static or global), no singletons.
The model handling is encapsulated in services (service = domain objects + repositories + data mappers).
All controllers extend an abstract controller.
All project dependencies are injected through Auryn dependency injection container.
All needed dependencies are injected in the constructor of the abstract controller. If I want to override this constructor, then I have to pass all these dependencies in the child controller's constructor too.
class UsersController extends AbstractController {
private $authentication;
public function __construct(
Config $config
, Request $request
, Session $session
, View $view
, Response $response
, Logger $logger
, Authentication $authentication // Domain model service
) {
parent::__construct(/* All dependencies except authentication service */);
$this->authentication = $authentication;
}
// Id passed by routing.
public function authenticateUser($id) {
// Use the authentication service...
}
}
The dependencies list would further grow. This needs to change. So I was thinking about:
Totally separate controllers from views.
They would then share the service layer. The views wouldn't belong to controllers anymore and the Response would be a dependency of the views.
Use setter injection in controllersLike for Request, Session, Logger, etc;
Inject dependencies in the controller actionsOnly when needed.Like for Request, Session, Logger, etc;
Use decorator pattern.Like for logging after an action call.
Implement some factories.
To constructor inject only the needed dependencies only on child controllers.So not in AbstractController anymore.
I'm trying to find an elegant way to deal with this task and I'll appreciate any suggestions. Thank you.
I'll answer to my own question. When I wrote it I already had a good overview of what many experienced developers recommend regarding dependency injection in MVC and MVC structure.
The constructor injection is the proper option. But it seemed to
me that, following this line, I'll end up with too many
dependencies/arguments in constructors. Therefore giving controllers
too many responsibilities (reading the requested values, changing the
state of the domain objects, logging operations, requesting the view
to load the templates and to render the data, etc).
Setter injection was also a solution to take in consideration. But, in the course of the developing time on my project, I realised
that this solution really didn't fit (at least) into the picture of
my controller-view relationships.
The injection of the dependencies directly into the controller
actions caused me hard-time (but great time) too, having in mind
that I already had the url values injected as action arguments and
that I didn't used any routing dispatchers.
Implementing factories was also a great idea, in order to be able
to have objects at my disposal within each controller action.
Factories are a great tool to use, but only going from the premise of
needed run-time objects, not of just reducing the number of
dependencies in constructors.
Decorator pattern is also a good alternative. But if, for example, you want to log something within a controller action, then
this is not a solution: you still have to pass a logger as dependency
(in constructor, setter or action).
I had a thought about injecting the needed dependencies only on
child controllers. But then the problem of multiple
responsibilities of the corresponding controllers remains the same.
So, none of this solutions seemed to entirely fit into the structure of my HMVC project, whatever I did. So, i dug further, until I realised what the missing link was. For this I give my whole appreciation to Tom Butler, the creator of the following great articles:
Model-View-Confusion part 1: The View gets its own data from the
Model
Model-View-Confusion part 2: MVC models are not domain
models
His works are based on an in-depth, well argumented analyse of the MVC concepts. They are not only very easy to follow, but also sustained by self-explanatory examples. In a word: a wonderful contribution to the MVC and developer community.
What I'll write further is meant to be just a presentation of his principles with my own words, having in mind to somehow complete them, to provide a compacter perspective of them and to show the steps followed by me when I implemented them in my project. All credit on the subject, ideas and principles and workflows depicted here goes to Tom Butler.
So, what was the missing link in my HMVC project? It's named SEPARATION OF CONCERNS.
For simplicity I'll try to explain this by referring myself to only one controller, one controller action, one view, one model (domain object) and one template (file), introducing them into a User context.
The MVC concept most described on web - and also implemented by some popular frameworks that I studied - is centered around the principle of giving the controller the control over the view and the model. In order to display something on screen you'll have to tell that to the controller - he further notifies the view to load and render the template. If this display process implies the use of some model data too, then the controller manipulates the model too.
In a classical way, the controller creation and action calling process involve two steps:
Create the controller - passing it all dependencies, view inclusive;
Call the controller action.
The code:
$controller = new UserController(/* Controller dependencies */);
$controller->{action}(/* Action dependencies */);
This implies, that the controller is responsible for, well, everything. So, no wonder why a controller must be injected with so many dependencies.
But should the controller be involved in, or responsible for effectively displaying any kind of information on the screen? No. This should be the responsibility of the view. In order to achieve this let's begin separating the view from the controller - going from the premise of not needing any model yet. The involved steps would be:
Define an output method for displaying information on screen in the
view.
Create the controller - passing it all dependencies, excepting the
view and its related dependencies (response, template object, etc).
Create the view - passing it the corresponding dependencies
(response, template object, etc).
Call the controller action.
Call the output method of the view:
And the code:
class UserView {
//....
// Display information on screen.
public function output () {
return $this
->load('<template-name>')
->render(array(<data-to-display>))
;
}
//....
}
$controller = new UserController(/* (less) controller dependencies */);
$view = new UserView(/* View dependencies */);
$controller->{action}(/* Action dependencies */);
echo $view->output();
By accomplishing the five upper steps we managed to completely decouple the controller from the view.
But, there is an aspect, that we hypothesised earlier: we did not made use of any model. So what's the role of the controller in this constellation then? The answer is: none. The controller should exist only as a middlemann between some storage place (database, file system, etc) and the view. Otherwise, e.g. only to output some information in a certain format on screen, is the output method of the view fully sufficient.
Things change if a model is beeing brought on the scene. But where should it be injected? In the controller or in the view? In both. They share the same model instance. In this moment the controller gains the role of the middleman - between storage and view - in his own right. A theoretical form would be:
$model = new UserModel;
$controller = new UserController($model, /* Other controller dependencies */);
$view = new UserView($model, /* Other view dependencies */);
$controller->{action}(/* Action dependencies */);
echo $view->output();
Doing so, the controller can change the state of the model and ensure that it's saved in the storage system. The same model instance, respective its state, is read by the view and displayed. The controller passes display logic informations to the view through the model. The problem is, that these informations don't belong to the business logic, which a model is supposed to exclusively have. They are only display logic participants.
In order to avoid giving display logic responsibilities to the model, we have to introduce a new component in the picture: the view-model. Instead of sharing a model object, the controller and the view will share a view-model instance. Only this one will receive the model as dependency. An implementation:
$model = new UserModel;
$viewModel = new UserViewModel($model, /* Other view-model dependencies */);
$controller = new UserController($viewModel /* Other controller dependencies */);
$view = new UserView($viewModel, /* Other view dependencies */);
$controller->{action}(/* Action dependencies */);
echo $view->output();
And the workflow can be described like this:
The request values are sent by the browser ("the user") to the
controller.
The controller stores them in the view-model instance as properties
(data members), therefore changing the display logic state of the
view-model.
Within its output method, the view reads the values from the
view-model and requests the model to query the storage on their
basis.
The model runs the corresponding query and passes the results back to
the view.
The view reads and passes them to the corresponding template.
After template rendering, the results are displayed on the screen.
The view-model does not belong to the domain model, where all domain objects reside and the real business logic takes place. It does also not belong to the service layer, which manipulates the domain objects, repositories and data mappers. It belongs to the application model, e.g to the place where the application logic takes place. The view-model obtains the sole responsibility of gaining display logic state from the controller and conducting it to the controller.
As can be seen, only the view-model "touches" the model. Both, the controller and the view were not only completely decoupled from each other, but also from the model. The most important aspect of this approach is, that each of all the components involved gains only the responsibilities, that it is supposed to gain.
By making use of this kind of component separation and of a dependency injection container, the problem of too many dependencies in controllers vanishes. And one can apply a combination of all options presented in my question in a really flexible manner. Without having in mind that one of the components (model, view or controller) gains too many responsibilities.

Firing Events in MVC (specifically in PHP, if it's needed)

I have searched on SO about this question, but I basically haven't found one concerning this particular scenario; hence, my reason for asking.
I have a basic, abstract understanding of the MVC pattern: Controller calls the right Model based on the action needed; the Model contains the actual business/data logic, and the View displays the result. What I am having trouble understanding is the actual implementation.
Originally, my assumption was this: Controller calls Model; Model processes information, and returns the data back to Controller; Controller call the View, passing this
data to the View, which simply displays it. After reading more articles on MVC, I discovered that the Model doesn't really pass the data back to the Controller; rather, it fires an event, which allows the Controller to call the proper View.
My question centers on this event firing part:
Q.1: Must an event really be fired? Once the Model completes its processing, and returns control to the Controller, can't the Controller simply call the View?
Q.2: In an actual implementation, a Model object is injected into a Controller class. So, Model object basically has no idea what Controller called it. How does it know what Controller to fire an event to? And how do we know what Controller is expecting that notification?
Q.3: The Controller calls the View, injecting it with the current Model object, so the View can use it to obtain the needed data. Is this correct or wrong? If wrong, why is it wrong, and what is the proper way to do it?
I have read my questions on MVC on here and other sites, viewed MVC diagrams, but I haven't been able to really connect the dots the way it's supposed to be connected.
Thanks.
There are many way's on how the different components on MVC are linked together. I think there is no 'Golden Rule'.
I use it the way shown in this picture:
The creation of objects is then like this:
the app object creates a controller, depending on the route. The router is injected into the controller.
The controller creates a model, depending on the route. The model is created by a IoC container.
The controller creates a view, and injects the model into the view.
In my situation I can answer your questions like this:
Q1: No, I do not use events. There is no need. The controller calls the model, and when done the model has state, and can be used by the view.
Q2: I do it just the other way, the controller creates the model. The model has no knowledge about the controller, or view.
Q3: this is the way I implement it.

Implementing MVP in Web Applications

As I understand it, MVP is a derivative of MVC where the Model and the View are loosely or completely decoupled, and the Presenter replaces the Controller and acts as the bridge between the View and the Model. This pattern seems more appropriate than traditional MVC in web applications (whether or not that is true is not the subject of this question, so please refrain from going down that direction).
My problem is in implementing the various MVP pieces in PHP, using a passive view. Here is my current flow of things:
The PHP script sets up an autoloader and a router. To me, this means whatever view was in existence send an event of some kind to the server.
The router then determines which presenter should be used based on the request.
Here be dragons. The Presenter acts as the bridge between the View and the Model and should take a View and a Model as dependencies so it can easily be tested. That means I need to know what model and view I should be using before the presenter is created.
The presenter seems to be the class that knows what Model and what View it needs, so how can I move that logic out of the presenter? I understand that the generic pattern to use is a factory, I just can't seem to understand how to implement it in this case.
Perhaps I am doing this all wrong. Maybe I've been coding for too long of a stretch and am experiencing mind warp. Regardless of why I can't seem to understand how to solve this problem, I'll accept any guidance.
Not 100% sure I know what you're asking. You are right that you load the appropriate controller based on the request. That controller is typically associated with a model and a view.
Let's say you have a URL that looks like: http://www.example.com/test/view/1
It would be fairly standard to load the Test controller, call the method view pass it the argument 1. So let's assume you have:
TestController.php
TestModel.php
test.php (view)
When the TestController loads it includes the model, TestModel, where your "data stuff" goes (I think you understand that). So for this example, let's say view wants to load the last 5 posts from the user with id 1. So in TestController.php:
function view($arg)
{
$userID = $arg;
$posts = $this->model->loadPosts($userID);
$this->render('test', $posts); // outputs the HTML in test.php
}
And in test.php, you can loop through $posts and output it however you choose.
It seems like you already know how this stuff works though, which is why I am confused as to what you're asking. Does this clear up anything?
I find it useful to think of Web Apps in terms of states and state transitions. the application is in a particular state, it's "at" a View, some HTML was with the aid of the associated Presenter from data in the Model and rendered to the browser . The user takes an action and this is going to move our app to a new state. So we are moving from one View/Presenter pair to another. In my mind the Model is a longer lived, evolving thing, I don't see us getting a new Model for each transition.
So you have PresenterA, responsible for responding to events in ViewA.
PresenterA receives some event, performs some work that may result in Model changes, and then decides which View to go to, say ViewB. ViewB can create its Presenter. As per the Wikipedia example (not PHP I realize, but the principle is clear):
public class DomainView: IDomainView
{
private IDomainPresenter domainPresenter;
public DomainView() // Constructor
{
this.domainPresenter = new ConcreteDomainPresenter(this);
}
}
In effect the Presenter is the creator of the next View/Presenter pair. If you have more complex logic replace the explicit constructor
new ConcreteDomainPresenter(this);
with a factory, working with View and Model information.

What could I do to improve my MVC?

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
}
}

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