I have created a login system and I am trying to stick to the rules of MVC as much as possible.
I have a simple login form that uses AJAX to submit the form data to small script, which then calls the controller for the processing of the username and password:
function __autoload($classname) {
include("../classes/$classname.php");
}
$username = $_POST['username'] ;
$password = $_POST['password'] ;
$AC = new AccessControl ;
$result = $AC->login($username, $password) ;
if($result !== 0)
{
echo $result ;
exit() ;
}
AccessControl is my class for user authentication and account management operations, the code is here in my other post: MVC Relationships and DRY
Have I done this wrong because this small script isn't a controller or a model? All it does is relay information returned from the controller back to the interface/view, such as error messages.
First, don't let any particular paradigm prevent you from doing things the best way possible in your particular situation.
That said, your small script is a controller. It's processing an action and returning a result. It may not be managing a specific view but it's delegating processing and handing off the result to a view.
In my oppinion, haven't used the MVC structre to the blood, this is about right, with some minor changings.
I usually prefeer something like :
$AC = new AccessControl ;
$AC->setUsername($_POST['username']);
$AC->setPassword($_POST['password']);
if ( $AC->login() )
echo $result // if all is ok from login method return true
else
// manage some error handling here if not true
Maybe you want to user that Username and Password in more places and other methods, so you can use getPassword() / getUsername()
You are mixing authentication and authorization. Structures like AccessControl should be dealing with authorization, not authentication .. you choice of names .. emm ... leaves room for improvement. To learn more about the authorization in context of MVC, i would recommend to read this post.
Authentication, in context of MVC and MVC inspired design patterns, should be part of the model layer and handled by some form of Recognition service.
What you have on the code snipper looks a bot like code from controller's method, but it has several issues.
Ok .. lets pike apart to code:
The use of __autoload() function is not recommended. You should instead learn how to utilize spl_autoload_register() function. It would let you code to use multiple leaders.
Also, since release of 5.3, it is possible to use namespaces in PHP. In combination with autoloaders, it would let you better organize you code. Lately it is common practices to map project directory structures (at least partially) to namespaces.
The most known implementation would be PSR-0, though it should not be considered even close to ideal. It has some serious flaws, but it will make for a good example to illustrate use of namespaces in autoloading.
You should avoid use of new deep in the application call graph. This causes tight coupling to the name of class from which you are creating the new instance.
Instead your controller should have a factory injected into constructor, which then is responsible for initialization of new instances.
namespace Controller;
class Foo
{
protected $serviceFactory = null;
protected $view = null;
// --- SNIP ---
public function __construct( HasSomeFactoryInterface $factory, $view )
{
$this->serviceFactory = $factory;
$this->view = $view;
}
public function postLogin( $request )
{
$recognition = $this->serviceFactory->create('AccessControl');
// --- SNIP ---
}
Controller in MVC design pattern should only change the state of model layer and current view. It does not return anything nor passes data from model layer to view. You seem to confuse classical MVC, Model2 MVC, MVP, MVVP and the Rails parody of MVC pattern.
In the Model2 MVC (also known as Web MVC) design pattern the controller take the incoming user request, and, by passing data from said request to the respective parts of triad, changes their state.
namespace Controller;
class Foo
{
// --- SNIP ---
public function postLogin( $request )
{
$recognition = $this->serviceFactory->create('AccessControl');
$recognition->login( $request->getPost( 'username' ),
$request->getPost( 'password' ) );
$this->view->prepare( $request->getMethod() );
}
// --- SNIP ---
}
In this example view receives notification, that the POST request was received, which means, that, instead of generating HTML from several of templates, it has to only send HTTP header as a response.
To see a short overview about the MVC-related patterns, try this post.
If you are aiming for Model2 MVC design pattern, then view should retrieve information from model layer on its own. But all MVC-inspired design patterns view is supposed to be responsible for the presentation logic.
That also includes dealing with error state in model layer. Domain business logic has nothing to do with how view represents errors.
Related
We all (most of us) know that controller's job is to handle the request made by client (e.g. web browser), get the model, render the view.
My senior developer has 20 years experience, grown up with native PHP, unlike me 4 years experience, grown up with PHP MVC frameworks. I saw my senior developer creates an object of a controller in another controller's action function because he wants to use the same business logic as below sample.
class FooController extend Controller {
public function view($id) {
// Business logic goes here...
// Pseudo code
// If request comes from BarController
// Render no layout, only view template.
// If request comes from browser
// Render view template with layout.
}
}
class BarController extends Controller {
public function viewFoo($id) {
// Create an object of FooController so that we can reuse the business logic of the view function.
$foo = new FooController();
$foo_view = $foo->view($id);
// Render $foo_view template.
}
}
Is it a good practice to create an object of a controller (in this case FooController) in another controller (in this case in BarController::viewFoo($id) ), following MVC design pattern?
This practice may be ok in some situations but in general it's a sign of problems.
According to some people, reusable business logic doesn't belong in the controller. Instead they recommend some variation of "fat model skinny controller" (put these terms in an internet search engine). Controllers should be really simple, and the reusable logic should be in the model layer, or in a separate services layer.
Given that, most people would assume that controllers are not reused like this. This makes the application brittle: Imagine someone changing the reused controller or the view it renders: they won't know they have to test this unrelated part of the application.
I am currently learning zend expressive and I can see a couple of options as to how to access middleware within routes/actions.
In the expressive skeleton application, there is a HomePageFactory where the container is injected, then the router, template engine etc are pulled from the container and a new HomePageAction class is constructed using these and returned.
For example:
class HomePageFactory
{
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = ($container->has(TemplateRendererInterface::class))
? $container->get(TemplateRendererInterface::class)
: null;
return new HomePageAction($router, $template);
}
I then needed a flash messenger and came across the following:
class SlimFlashMiddlewareFactory
{
public function __invoke($container)
{
return function ($request, $response, $next) {
// Start the session whenever we use this!
session_start();
return $next(
$request->withAttribute('flash', new Messages()),
$response
);
};
}
}
So this is slightly different and is adding the middleware to the request via an attribute. Which can then be retrieved where its needed by something like:
$flashMessenger = $request->getAttribute('flash');
So really my question is what are the advantages/disadvantages of these two methods of getting the FlashMessenger into the action?
If I have a UserService which deals with retrieving users from a database and therefore may be needed in multiple actions/routes, would I be better off modifying the HomePageAction & Factory (and any others that need it) to accept the UserService?
i.e.
class HomePageFactory
{
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = ($container->has(TemplateRendererInterface::class))
? $container->get(TemplateRendererInterface::class)
: null;
$userService = $container->get(App\UserService::class);
return new HomePageAction($router, $template, $userService);
}
Or would I be better to go with how the FlashMessenger works (which seems a bit easier to manage) and add it to the request via an attribute to access it that way where needed?
i.e.
$userService = $request->getAttribute('UserService');
I'm wondering if there are any performance issues with the latter option, although I do understand that it could be done in this way only for specific routes rather than the UserServer being application wide.
My gut feeling (after writing out this question) is that really, this is a Service and not true middleware so I should really be Modifying the HomePageAction & Factory and adding the UserService that way rather than doing what seems easier and using the attribute ala FlashMessenger. But it would be very handy if a guru could help clarify this.
Many thanks in advance.
I don't know about performance differences since I haven't tested this. But I guess the question you need to ask yourself is what does the class do? Is it needed by other middleware before or after invoking the Action class or do you need it only in the Action class or somewhere else in the application.
In your case the UserService might take care of registering or updating an user. That stuff would be injected with the ActionFactory as your gut feeling tells you. However for authentication it would be different if that is done with middleware. First you need that class in your authentication middleware which you can pass on to your authorisation middleware with the request (or maybe only pass the authenticated user object, that's what I do).
So I guess the rule of thumb is that if something is needed to change the incoming Request or outgoing Response before / after the Action, you pass it on with the Request, otherwise inject it in the Action with a Factory.
If you start passing everything around with a Request, it will be very hard to keep track of. I find it much easier to inject as much as possible into the Action itself because then I can easily see what is needed inside that class and I can test it easier.
Things like a flash messenger, session and the authenticated user I would inject in the request.
I have a model named Message, which is an internal notification in my website.
I have a controller, RegistrationController that handles when a new person registers with my website. When this happens I send a Message to all users.
This is how the code involved looks like:
public static createMessage($receiver, $content)
{
$message = new Message;
$message->receiver = $receiver;
$message->content = $content;
$message->save(false);
}
It is called like this in the RegistrationController.php
foreach($users as user)
Message::createMessage($user->ID, $content);
What is the best approach and that it won't violate mvc?
Inside the Message model I add the createMessage() function. It doesn't require imports.
Or I create a MessageController and add that function inside? If I do version 2 then I need to include MessageController in the RegistrationController.
Any better idea.
Which version would produce better code that can better be maintained? Please quantify your answer to avoid opinions.
Doing MVC is a style of programming.
There is no restriction where to put a logic. You can put it in Models or Controllers.
Which ever best suit your work style, use it.
I usually put in Controller the logics that interact with users through interfaces. (Get values from interfaces)
And put in Models the logics that help business rules. (Do things with the value from interface and database)
If you decide to put your Message logic as Controller, you do not need to include MessageController.
But make sure in the /config/main.php you include this:
'application.controllers.*'
EDIT: After some research, I saw this framework: this MVC framework. It have classes in Libs folder which are static (like Config, Session), can I use these ?
I am pretty new to MVC practices, and I am stuck on a weird problem..
I have many models, such as DB, User, Config, etc.. but I'm using many of these in each function I create.
I have a problem working with MVC patterns; I created multiple models, I'm using each one of them to handle grouped tasks(connection, DB, ect..).
Problem is, after creating the basic models, I ended up with code like this(within the controller).
class User
{
function signup($username, $password, ...)
{
$config = new Config();
$DB = new DB();
$HTML = new Session();
// And so on...
$canRegister = $config->get("registration-enabled");
if ($canRegister and ..) {
$this->username = $username;
$DB->saveAccount($this);
$session->setUser($this);
} else {
throw new Exception('bad signup');
}
}
}
I have to create instances of many models just for one or two functions.. but if the models are static, it should look like this:
class User
{
function signup($username, $password, ...)
{
$canRegister = Config::get("registration-enabled");
if ($canRegister and ..) {
$this->username = $username;
DB::saveAccount($this);
session::setUser($this);
} else {
throw new Exception('bad signup');
}
}
}
Note that many models doesn't use __construct method.. so is it good practice (or not bad) to have statics models in a MVC pattern ?
Please see EDIT above before responding.
Model is a concept of abstraction!
Model consist of services, while services themselves consist of storage abstractions and objects that handle computations. Simply put, a service is a bridge between domain objects and storage abstractions (such as Data Mappers or Table Gateways). A model consists of those services.
That's a typical way how a model should be structured:
Model
- Storage
- MySQL
- YourMapper
- Service
- YourService
A class that handles abstraction to a table and does computation and validation is also known Anemic Model (which seems to be your case), because it violates the SRP and breaks Separation of Concerns.
When adhering to this right way, you can easily replace storage (say you can replace MySQL to MongoDB) since they no longer tightly-coupled to business logic. Or you can replace domain objects that handle computations without even touching a storage.
And no, nothing ever should be static!
For the purpose of example, let's imagine, that your write a library that does file uploading.
class Uploader
{
...
public function upload(array $files)
{
$path = Config::read('upload_path');
$some_another_option = Config::read('foo');
$this->move($path, $some_another_option, $files);
}
...
}
So what kind of problem might lie here? Just remember that we write a library, and let's face these facts:
In order to use a uploading library, the Config object must be properly instantiated and its data must be fully loaded into the memory. Which is a waste of RAM and
What if you decide to replace Config to another source of required information? You can't because its tightly-coupled
If you want to distribute your library, you will also have to distribute your Config + its dependencies, which will make your library look bad.
Yeah, you probably have seen this approach in another frameworks. But popular doesn't mean correct, anyway.
The right way,
You gotta remember that object instantiation is another responsibility too. When you instantiate a Conifg you probably load data from somewhere (array or a table, whatever). So in your first approach you gotta load it n-times? That's seems a very wrong way to do.
What you should really do is to instantiate Config only once, and pass it to classes the require it, like this:
$config = new Conifg();
$config->load(__DIR__ . '/config_array.php');
$user = new User($config);
$system = new System($config);
// and so on, you got the point
The same applies to your DB and Session. Classes which use these objects should not bother about their instantiation. They just gotta bother how to use them.
Remember: Nothing ever kills code reuse-ability like Static classes and Singletons
All cool dudes refer to this technique as Dependency Injection
I'm building a web application that needs to be able to write data to either a mysql db or an xml file, depending on the online status of the application.
In my model, I have a super class (Dao is data access object)...
abstract class Dao {
static function getInstance($online_status) {
if $online_status = 'online' {
return new DaoMySQL;
} else {
return new DaoXML;
}
}
abstract function dao_select();
abstract function dao_insert();
abstract function dao_update();
abstract function dao_delete();
}
Now, here is the part I'm confused about. I have a domain model/entity class that selects the appropriate Dao using:
$this->dao = Dao::getInstance($online_status);
So, now I have the correct data access object selected. But, the problem is I still two implementations of dao_select() and the other functions. Now, the main implementations are in the respective classes DaoMySQL and DaoXML, but dao_select() in each of those classes require different things. i.e. the DaoMySQL version needs two parameters, $table and $where_statement. DaoXML (which I haven't implemented) will need the element name, and maybe another argument, I don't know.
So, in my domain model class, after calling
$this->dao = Dao::getInstance($online_status);
is this where I need to include two separate local implementations (pertaining to the domain model/entity class only) of dao_select(), or this wrong? It just seems like I'm taking the elegance out of the process by doing something like this:
class EntityModel {
$this->dao = Dao::getInstance($online_status);
if($this->dao->type = 'mysql') {
$result = $this->dao->dao_select($table, $where);
} else {
$result = $this->dao->dao_select($xml_params);
}
}
I feel like I'm taking the simplicity out of the system... Does this approach make sense, or is there a better one?
You are doing it wrong.
Few notes to begin with:
in OOP the extends statement signifies is a relationship. Which means that, while class Duck extends Bird is all fine, writing class User extends Table is NOT.
in MVC the Model is not a class or an instance of a class. Instead it is a layer of application, mostly made of two types of elements:
domain objects: containing domain business rules and logic
data access structures: usually datamapper dealing with storage and retrieval of information
I would argue, that the third significant part of Model layer are services. But there are options on whether it is part-of or above Model.
Currently what you are trying to do is forcing a ActiveRecord (which is fine for small things, but as project grows, it becomes a burden on architecture .. which is what you are face with now) patterns to work with dynamic data sources. And to do so you are resorting to procedural calls.
Anyway, the point is that you should inject your DAO instance into your Domain Objects (what you calls "models"). And you should leave the creating of your DAO to a separate factory instance, which would be responsible for initializing them and providing them with data source (instance of PDO or file path). This way you can, not only separate the responsibilities, but also swap the storage destination "on fly".
To learn more you should investigate what is dependency injection. Here are few video that might help:
Don't Look For Things!
Global State and Singletons