PHP MVC structure where to put own classes - php

I just started taking a look at the MVC pattern.
My question is:
Where would I put my other class files (Database, User, Logger, Mailer, etc)? Should I create a new directory for them, e.g. libs?
Should I instantiate the classes in the Controller inside the model function?
<?php
class Controller {
protected function model($model) {
require_once('../app/models/'. $model .'.php');
return new $model();
}
protected function view($view, $data = []) {
require_once '../app/views/'. $view .'.php';
}
}

Where would I put my other class files (Database, User, Logger, Mailer, etc)? Should I create a new directory for them, e.g. libs?
Putting them in separate files since they all provide different functionality should be fine. There is no difference in your directory naming - as long as it matches the naming conventions of your project or general (probably, even better).
Should I instantiate the classes in the Controller inside the model function?
No. As far as I see it, the flow could be similar to:
The index file receives the request and initiates a new bootstrap instance
bootstrap sets the throwable handler and the router
router then calls the respective method basing on the request method and uri provided by matching against a set of routes
The matching route initializes all the components of the MVC triad and the callable method. The components (Model layer, View layer, and Controller layer) are passed to the method called by the router. In my case, I call the class FrontController, the method init.
Basically, the init is the place where the MVC triad is actually made. Model layer is responsible for business logic, persistence, etc. It is important to note that Model is not a single file or class (the same for View and Controller). Both View layer and Controller layer consult the Model layer to do the respective actions. View layer's mission is to manage the output, for example, decide wether the output will have Content-Type of application/json or text/plain, or which Template to render. Also, Views are not Templates, which are meant for displaying the data. Note here, Views ask the necessary data directly from the Model layer; there is no interaction with the Controller layer whatsoever. Finally, Controller layers steps in when there is a need for interaction, for example, a user submits a form, the respective Controller filter the input and calls the method from the Model layer.

As MVC has three major parts, I'd recommend (and noticed that almost all frameworks on the market do so) to create a directory of each of the three components, and place the classes in the appropriate directory.
As regarding the other components, Database is a utility and can be placed for example in a lib directory, User is a model and can go to the model folder, and Logger/Mailer can also go to the lib folder. These are examples and not something to strictly follow.
As for instantiation, each Controller can define the list of models and libraries it depends on and have the MVC framework handle the initialisation of those objects. You'd follow the dependency injection pattern this way.

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.

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

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.

cakephp registration and login form

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!

Can I generate all of the content necessary for multiples pages in a single file with MVC?

I'm in the early stages on learning the Model, View, Controller framework with PHP. I'm getting the hang of it thanks to a tutorial found here. From my understanding, the controller will invoke the model so that the appropriate code can be ran in order for the viewable content to be rendered correctly.
The problem is that based upon that particular tutorial, it seems that I'm going to have to create an entirely new file for each page just to invoke the model in order to render the data viewable.
For example, in my controller.php file I have:
require_once("model.php");
class Controller
{
public $file;
public $league;
public function __construct($file, $league)
{
$this->file = $file;
$this->league = $league;
}
public function invoke()
{
// Everything that needs to be done in PHP will be done here so that once
// whatever file is included, it will just fit in fine and echo out perfectly
require_once($this->file.".php");
}
}
In my model.php file, I have:
class Model
{
private $file;
private $league;
public function __construct($file, $league)
{
$this->file = $file;
$this->league = $league;
}
More code. You get the idea...
}
In my teams.php file, I have:
$controller = new Controller("teams", "nba");
$controller->invoke();
But, since the teams.php has to invoke the the model and will ultimately require_once("teams.php"), I have to create an entirely new file just for the view. So, now the display will be featured on teams_display.php. Is there anyway that mod rewrite can help facilitate a framework whereby all of the pages happen in the index.php file while giving users the illusion that they're not?
As some already have mentioned. MVC is not a framework.
MVC is quite old design pattern, originally defined for smalltalk. Thought in all the years it has somewhat evolved and produced several related patterns, that have been adapted for use in Web.
The core idea in MVC is separation of concerns. This is why MVC and all the MVC-inspired patterns are made of two layers:
presentation layer, that deals with interface in all of it's forms
model layer, that handles the storage an business logic.
Since these are two different layers, they should not be aware of other's internal structure. Otherwise you end up with leaking abstraction.
The presentation layer
In well implemented MVC structure, the controller only changes the state of model layer (and in rare cases - state of current view instance). Controllers IS NOT responsible for instantiation of model layer or any structures in it.
The view instances in MVC should responsible for producing a response to a user. In some case it might entail only sending an HTTP location header, while in other case - it produces a HTML output, by combining multiple templates. View request data, that it needs, from model layer.
In this context, the "user" is not the human, but the browser, which is communicating with website.
The model layer
This layer is usually made from three major groups of structures:
domain objects, that deal with logic of particular business entity
storage abstractions (usually - data mappers), that are able to store data from domain objects
services, that contain the application logic (interaction between domain object and storage abstractions)
The presentation layer interacts with model layer through services. Controllers send data to them, which change the state of model layer, while view instances request data form them.
If you are interested, there is a bit longer explanation of the model layer available here.
P.S.
Avoid the PHP frameworks. Non of them actually implements MVC. Instead, most of them, are pure Rails clones, which by it self was never intended to be a production-stage framework(explanation here).
MVC is not a framework but a design pattern. This tutorial will help you understand the MVC pattern but if you want to use a real framework you can take a look at Zend Framework.
In your case index.php is the entry point, mod rewrite redirect all the requests to index.php who is redirecting to the appropriate controller according to the user request. For example, http://localhost/teams/nba, 'teams' is the controller, 'nba' is the action.
You have to create a TeamController and in the controller you have to create a 'nba' action. The model is dealing with the DB layer so create a Team model with getNbaList method to retrieve all the NBA teams.
You have to call the model inside your action and then you can feed the view (mainly html) with all the teams you get from the model.

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

Categories