5

Traditionally in a MVC framework (Such as CodeIgniter or Kohana) I create controllers as I create different pages. There will be a login controller, a home controller and so on. But recently I learned more about objective oriented programming and want to start using it. And even though the framework uses classes, it's not the same principle as an object.

Yes. The login controller is as an object. But where am I supposed to write my "User" class for example? Do I write them in a library and import them when needed? What is the proper way of doing this, if there even is any.

I'm just puzzled on how I can do this right.

Henrik Skogmo
  • 1,995
  • 4
  • 18
  • 25
  • Are you asking in general or specific to CI/Kohanna? – prodigitalson Jun 26 '13 at 13:09
  • I didn't want to close it of as a Cl/Kohana question. Since I do think I've seen similar structures in other frameworks as well. But you can by all means consider it to be Cl/Kohana specific. – Henrik Skogmo Jun 26 '13 at 13:17
  • It is not writing more controllers as you creating different pages. It is, mainly, writing more Actions where Actions are methods that access those controllers. In other words, in MVC, the objects are controllers and models. – SaidbakR Jun 26 '13 at 14:15

3 Answers3

4

<rant>

If you start out with frameworks that are either direct Rails clones or heavily influenced by Rails architecture, you are not really implementing MVC. Ruby on Rails framework was originally intended to be a purely rapid prototyping framework, which means that they sacrificed most of MVC concepts on "The Altar of Scaffolding".

Rails-based PHP frameworks replace fully functional views with templates, model layer with some collection of active record instance and for the "controller" to deal with all the presentation and application logic.

</rant>

The bases of MVC design pattern is the separation between business logic (contained in model layer) and user interface (managed by presentation layer). These two layers each contains different groups of structure.

The User is not a model. There are no "models" in modern MVC. Instead your User instance is a domain object. Also, it should not be directly exposed to the controllers or other presentation layer structures.

The interaction between presentation layer and model layer should be performed by services. Services in model layer are structures, which are responsible for handling the interaction between domain objects and storage abstractions (either data mappers directly or via repositories and/or units of work).

namespace Controller;

class Authentication
{
    // .... snip
    public function postLogin( $request )
    {
        $service = $this->serviceFactory->create('Recognition');
        $service->authenticate( $request->getParameter('username'),
                                $request->getParameter('password') );
    }
    // .... snip
}

In this case the User instance is somewhere inside the recognition service, which is there to deal with different business-logic aspects of user authentication. And do not confuse it with authorization. For authorization in MVC context there is a bit different recommended approach.

P.S.: if you are just now starting to really delve into OOP, you might find this list useful in your research.

my two cents

Community
  • 1
  • 1
tereško
  • 56,151
  • 24
  • 92
  • 147
  • 1
    It's considered to be a common courtesy to leave comment, if you downvote. Did I write something wrong? Or is this another revenge-vote? – tereško Jun 27 '13 at 11:50
  • 1
    Not the downvoter. Really like this answer. But I want to ask a question. Do you mean, in the case I mentioned in my answer, I need a class named i.e. `Actions` and there to be made all the interactions between the users, another class named `Authentication` where all the login details and queries for users are – Royal Bg Jun 27 '13 at 11:53
  • @RoyalBg , maybe ins some aspects, but as I read it, your `Actions` instance has some significant issues with [SRP](http://en.wikipedia.org/wiki/Single_responsibility_principle). – tereško Aug 05 '13 at 23:47
1

It is better to write your User class as a library since it is not a controller(assumption) and you should not have direct access to the User class through the URL. So the best practice is to write a Class if you want it to be object oriented. Or you can create a helper file if you want to have static functions.

Asskey
  • 21
  • 2
  • Yes, a library or a helper file. But is that the best practise? Considering that these (Cl/Kohana) frameworks was built upon OOP itself, shouldn't they have some kind of pre-defined for the developer to write objective oriented code as well? – Henrik Skogmo Jun 26 '13 at 13:19
  • I absolutely agree, and would add that, if you wanted a way to view your users, then you'd create a User class with other 'domain' objects and Controllers to create views for each domain object you want to view. – rbrtl Jun 26 '13 at 13:27
  • Depends on what you are using the User class for. For example, in a forum or a game, the User is one of all the things which the game/forum/platform has. So you have either a UserController and UserModel, for all the interactions which the user has – Royal Bg Jun 26 '13 at 13:30
1

I think it's too individual. Really depends on what kind of application is built. Let's think out of the CodeIgniter or Kohana, but for your individual framework, with individual application.

If you have simple login system, where the user is nothing but a Name and an ID, and all the interactions are between the other stages of the application, instead interactions between the users, your User Class which only contains information about the user (simple queries to the db which retrieves certain information from users table), can be a helper.

But in some applications (platforms in this case), the user might be an equal to any other object in it.

For example building a Forum-like application, you might want to have Warn level, Reputation, various logs of user actions, etc.

Also the user is an equal object like a 'topic', which also have for example likes/dislikes, priority, etc.

In this case you build a model and a controller for the user. For example in your Model you will have methods like

createUser(), getUser(), getUserWarnActions(), updateUserActions(), logUserActionChange(), etc, etc.

All of that methods, will be in a class called i.e. UserModel which extends the Model main class

where for example UserActions are the warn level, the email change, username change, reputation change.

In your controller, you might want to have

updateWarnLevel() => which interracts with updateUserActions(), tells the model it's action = warn level, and updates it, by the given value

so these methods will be in a class i.e. called UserController which extends the Controller main class

But at all it really depends how you look on your User class as. According to me it will be bad practice to have Controller/Model called Warn level, since it's a part of another abstraction, but not individual one.

To assume which is a child or a parent, I would try to make a structure, like a db one, and then create models/controllers/helpers.

If you have the following database tables:

  • users
  • user_reputation
  • user_warnlevels
  • topics
  • topic_votes
  • warn_levels // contains i.e. id | level | something_which_depends_on_the_level

It definately means that Users and Topics would be Models/Controllers in your application, where warn_levels won't be, since they are separate table only because they have some logic, but they are no parent table, only child one

Royal Bg
  • 6,854
  • 1
  • 16
  • 24