I am facing some confusion because i have decided to convert from procedural to oop, I Find it more efficient.
So anyway I've got some questions i hope i find answers here :)
Let's say am working on a php Registeration System which requires
1-Signup process
2-Activation Process
3-Login process (which requires)
Validating inputs
Validating Sessions, etc
The questions is: Should i make class for every process Or i can combine all of them into one class named 'User', with methods to login, signup, activate and so on, Or can i make 1 class named USER which has user's properties, and signup, login classes extends it ?
Should i use separated classes for Sessions, Validating etc ? or just normal Checking inside the main class
Should i Separate ADMIN classes from normal classes ? meaning I have a USER class, which has methods, to login user, signup user etc, should i add more functions for admin like DELETE user, UPDATE user ? or separate it from the normal classes
You should make a User class with different functions for login signup and whatever.
You should separate different functions into as many classes/objects as you feel suits. For instance, with your User class you might have a Session class which you use within your User class to do the session management stuff. You could also create a Person class which User inherits from. This can have functions like printFullName and such, whereas the User class has auth specific stuff like login and register.
Again, its up to you. You can do whatever you want. I would probably have a UserAdmin class which has functions like deleteUser($userid) and editUser($userid) just because then its not confusing it with the auth side of things. However it can be done the other way. You could call a User object for a specific user and call deleteUser() on that to delete the user. Its what you feel most comfortable with.
As with all my answers, its what you want to do. There is no standard to this, and no rules. OOP is mainly about layering everything so that it makes sense, structurally, and about creating reusable code.
Another thing you want to look at is MVC programming. MVC stands for Model, View, Controller. In this set up you actually differentiate objects not by category (e.g. user, page etc) but by their function (e.g. model - connects to a database, view - has the code to layout a page, controller - computes stuff and passes data to the view). If you look at something like codeigniter then this will become more apparent to you.
Now you can create a model for users. In this model you can do all the database stuff, adding, editing, deleting users and such. This can then interface with a controller which will layout the page, e.g. seeing if the user is currently logged in, calling the user's model and getting the name of the user from the model, then passing it to the view to display on screen. This will make much more sense when you start using frameworks like code igniter.
Anyway, good luck in your learning.
It's really your own choice what is in a class and what is not. Mostly it's about what you find to create a good overview and what makes certain use-cases easier. In this case it will most likely cause more confusion if you split these operations, instead of putting them under the same banner.
I'd under most circumstances choose to put validation, signup, etc. in the same class. If admins are also users (and not a whole new table of users for example) I'd also include these in the same class - Or maybe create an admin class that extends the user class.
But there's no ultimate law of what is put in one class and what is not. It's about trial and error and seeing what gives you a good overview, and when you come to building abstraction layers, extending classes, etc. you need to be a little more careful. Taking the right steps can save you a ton of work in later work with extending classes.
I made the switch about 6 months ago from functional to OOP. I read a shitload of papers trying to figure out what the big deal about OOP is.
I think a conceptual understanding is important in this case. Think of an object as a physical thing.
A car:
A car has properties:
color
remaining petrol
top speed
A car has methods:
start
stop
accelerate.
1) A user is an object, login, logout, signup are actions/methods that a user does.
2) A user has session variables(properties) so I would place them as properties in the class
3) An admin user has more methods, but still needs acess to old ones. So idealy an admin user should inherit the properties and methods, I think this is done with the Extends keyword. This is called subclassing, or inhertance.
You best is to google "understanding oop concepts" and read whatever connects with you
Related
I'm fairly new to php oop and I'm starting to get the hang of things. Though I have extended procedural experience, I've only recently started to build my own MVC framework, mainly for learning purposes. I got to the stage where I know how to route url's to controllers and models and render views based on what's requested. What I struggle with is a conceptual thing:
My application has users, which have to log in in order to use it. If you're not logged in, nothing happens. These users are objects and have methods like login(), logout(), auth() etc.
At the same time, I would like to have a "module" in my application where certain users can manage users, like root for example. A page where I can see all users, add new ones, remove existing ones, reset passwords etc. ...
While I know how to build the latter, I'm confused about where the login() and logout() actions should go. Are these part of the UsersController or should I have a separate class for them, despite technically dealing with the same object type?
Thank you!
MVC and the chess game
This is to help you understand what's the Model, the View and the Controller and how each layer might be used.
Let's suppose that you want to implement a chess game in MVC.
The rules are essential for a chess game. The rules are the Model layer.
You may play with with a wooden board, or using a computer, or using only your mind to represent the state of the game. The representation of the game is the View layer.
Of course, the rules and the representation of the game don't tell how the moves are chosen. There might be humans or some machine playing the game. Different humans and machines usually make different decisions. Those are the controllers. The fingers, pointer devices, keyboards are also controllers. They interact with the Model. All those controllers belong the Controller layer.
Let's suppose that in the Model layer there's a method:
MoveResponse ChessGame::move(from, to)
That doesn't mean that there shouldn't be some method:
void HumanPlayer::move(from, to)
The human interacts with the game using, for instance, a mouse. There could be something like that:
MouseGameController::onClick(x, y)
Using the board representation (from the View), it would convert the click position to the board position (in the model), check if there's some game piece there and notify the View for visual feedback.
If there was some game piece and the player clicks again, void HumanPlayer::move(from, to) would be called, that would call MoveResponse ChessGame::move(from, to) and the returned MoveResponse would be used to update the View. Some method would evaluate the content of the MoveResponse and call the appropriate method, for instance, to move a piece with an animation and make some sound.
Where to put the login and logout
Someone has to login and logout. That's a decision made by the user, therefore it should be in the controller.
Nevertheless, since it's possible to login and logout, there are users models. You need to access users data, change them, know what's the current user, etc. I believe the login/logout functionality should be implemented in the Model, but how that's invoked should be implemented in the Controller.
In the Model it's not important how you proceeded to login or logout, or how those events were triggered: you clicked the "Esc" key, or you clicked a button, or you sent a HTTP message, etc. That's the Controller responsibility. Implement the login and logout without thinking how the user will login or logout, then use something else to call what you implemented when the user wants to login or logout.
Usually, the idea controllers are limited to map the actions of a router to a function, but the db connection and other things involved exported to other layers of your framework and just to be called there.
So I've been working on an PHP MVC for a client for about 3 weeks now, I've got pretty far.
I'll explain a small part of the system.
There are three types of users, Fitters, Agencys, and Admins.
these can all log in and have limited functionality, admin obviously has all functionality!
The admin can add, edit and delete users, jobs, stock blah blah the usual.
The way I've set it up so far is like so...
The query string is like: /admin/users/?method=agency&action=add
This will call the admin controller, and call the users function.
The users function will then call the users model.
The users model contains functionality to add, edit, delete, admins, fitter, and agencies.
action=add&method=admin will call add_admin() which will dynamically return a form for admins
action=edit&method=fitter will call edit_fitter() which will dynamically return a form for editting fitters
Now I was wondering...
Would it be better for me to have an ADD class. with ALL the add methods like, add_fitter, add_agency, add_admin, add_job, add_stock etc... and then have a class for EDIT, a class for DELETE, and a class for VIEW ???
Would this be a good way?
I thought that by doing this, I can limit the dependancy on classes like the USERs class.
Because the users class adds, edits, deletes, inserts, updates and views fitters, agencies, and admins. So the user class needs a Validator, a database, a Form class that returns html forms for adding and editting etc etc.
However if i had ONE class for ALL the adding, then it would eradicate the dependancy for a validator? because the add class would be responsible for returning the form. Nothing else
The reason I'm asking this question is because I'm new to MVC. and I dont want to spend the next couple of hours changing all my code, and then realising that theres a problems with my proposed pattern.
So i'm just asking you kind people, can you foresee a problem with this method?
is this how its usually done?
or is this method steered clear of for a reason?
ANY advice or tips will be GREATLY appreciated!
Just to be clear... I'm asking whether I should have separate classes for Add, Edit, Delete and view
Alex
I think the best way is store the access level of the user (session, etc), and render the page according to what was stored in the session. Urls need to be only /admin/users/?action=add
Or
admin/user/edit/?id=27
router/controller/action/?param1=value1
Just if anybody was curious, i did implement my mvc this way and it's much better!
I have 3 tables that contain user information, one for students, one for teachers and one for administrators.
They are not related in any way. I wan't to create a dashboard for the Administrators, where a list of students and teachers shows up.
The only way I found to achieve this was using the $uses variable in the Administrators controller. However, I have read in many places that this is bad practice.
Any solutions?
Another, perhaps better practice is the use of ClassRegistry::init('MyModel')->myMethod() (more reading # Cake API)
This only loads the object when it's used, as opposed to loadModel or uses, with ClassRegistry the models are treated as singletons.
--
that you are doing something wrong: you need access to a model that has nothing to do with your current controller.
There are plenty of conditions where you would need to access all of your models data, from one controller, but never a definitive answer on how to do it without breaking convention!
You can always use another Model which is not related by using
$this->loadModel('NewModelName');
Then you can access new loaded model by:
$this->NewModelName->add(); // whatever method model has defined
Why prefer loadModel() over uses?
To gain performance. How? uses calls the loadModel function itself to load all the models you specify in uses array. But the problem is if only one of your action needs a particular model, whats the good thing to include it in every action. e.g. only add() action requires an unrelated model, but if you have specified it in uses array, no matter what action gets called a completely unrelated model is going to load. To put simply it will be inefficient. Its like you have declared variables in a C programme but never used them. In case of C compiler will warn you that you are not using your variables, but unfortunately cake couldn't tell you.
Its alright to use uses if all your actions needs to load that model, use loadModel() otherwise.
You probably didn't read my answer in your other question :))
I have 3 tables that contain user information, one for students, one for teachers and one for administrators. They are not related in any way. I wan't to create a dashboard for the Administrators, where a list of students and teachers shows up.
The problem is you are separating similar data into 3 different tables, in this case, user information. So when you try to manage this data, you hit a brick wall: because you leave out the relationships when you separate them in 3 tables.
The only way I found to achieve this was using the $uses variable in the Administrators controller.
You got the wrong idea about the controller. Each controller manage the data flow of a particular model (and related models). It doesn't mean that you have to stay in Admin controller to do administrative things. What model you want to manipulate decides what controller you need to be in.
However, I have read in many places that this is bad practice.
Now for the main question: using $uses is a red flag that you are doing something wrong: you need access to a model that has nothing to do with your current controller. Now, there're always exceptions in programming, sometimes we need to have access to that model. That's where loadModel comes in. Because it should be rare. If you need the model a lot, then you'll need to call loadModel a lot, which is cumbersome, which is what $uses is for, but then that means something's wrong with your app design :))
So, you can say using $uses is a sign of bad decision (in DB design or application structure); and so is using loadModel a lot.
Edit: Any solutions?
I gave one solution in your other question. But if you want to have them all in one place, you can have 1 users table with user information. Each User can hasOne Student, Teacher, Administrator and a 'group' field to decide what group the User is. The third solution is using $uses. Its performance impact won't be a problem really. But it will be pretty convoluted when you develop your app further. That's what you need to worry about. For example, I can say that, if you use Auth, you'll need to tweak it a fair bit to get it working with 3 models. If you use the users table, it will be a lot easier.
Rather than use a full-blown PHP MVC, I'm designing one that will best-fit my uses. I have the basic framework done, and have coded the models and controllers I'll need to run my website.
Now I'm moving onto the Views, and I've encountered a small dilemma. My approach is working fine for me, but for future reference, I want to know if what I'm doing is a bad habit to get into.
What I'm trying to do:
In my View, I'm calling a Model that runs my authentication system, and requesting the login status of a user. I then use that boolean to decide whether to show certain elements within the view, and where to place others.
Should I be designing separate views for each login status, or is this approach fine? However, if I'm going to be implementing this MVC into the work I'm doing for my clients, I need to use the best practices.
Any advice would be appreciated!
Can I call the model from the View?
Yes, you can. As long as you maintain the separation of concerns between M,V and C, you are free to call upon the Model (or the Controller) from the View. Most MVC diagrams show a bidirectional connection at least between View and Model. What you don't want to do though, is place logic/code from the Model (or the controller) into the View and you don't want to modify the model from there.
For example, you might have a widget on your page that aggregates the latest ten blog posts headlines from your favorite blogs on each page of your website. You get the headlines by calling, say MyFavFeeds::getLatest(); in your model. What are your options now?
You could add the code to fetch the headlines into the controller, but that would require you to replicate it in each and every controller action, which is against the DRY principle. Also, the controller's concern is handling user input for specific actions and fetching the headlines on each call is likely not even related to these actions.
If your architecture supports it, you could fetch that data in some sort of preDispatch hook, that is, the headlines get loaded and injected into the View from a plugin or callback. That would be DRY, but a second developer might not be aware of that plugin and accidently overwrite the variable holding the headlines from his controller action. And there might be cases in which you wouldn't want to load the headlines, e.g. when just rendering confirmation pages for form submissions, so you'd have to have mechanism for disabling the plugin then. That's a lot to consider.
You place the call to (not the code of) MyFavFeeds::getLatest() into the View or Layout template or, better, a ViewHelper, that encapsulates the call to your model class and renders the widget. This way you don't have to worry about overwriting any variables or repetition. And when you don't need the headlines on your view, you simply don't include it.
About your other question:
In my View, I'm calling a Model that
runs my authentication system, and
requesting the login status of a user.
I then use that boolean to decide
whether to show certain elements
within the view, and where to place
others.
Authentication is something you will want to do early in the application flow, before any controller actions are called. Thus, you should not run your (entire) authentication system in the View. The actual authentication is not View-related logic. Just requesting the user status after authentication, on the other hand, is okay. For instance, if you want to render a widget showing the user name and giving a login/logout button, it would be fine to do something like
<?php //UserHelper
class UserMenuHelper
{
public function getUserMenu()
{
$link = 'Logout';
if(MyAuth::userHasIdentity()) {
$link = sprintf('Logout %s',
MyAuth::getUsername());
}
return $link;
}
}
If you got larger portions of your GUI to be modified by a User's role, you might want to break your View apart into partial blocks and include them based on the status, instead of writing all the HTML into a View Helper.
If you are only looking to render a navigation based on the user role, have a look at Zend Framework's Zend_Navigation and Zend_Acl to see how they do it.
You can, but you shouldn't. Except for a few extreme cases (and branching your view based on logged-in status is definitely not an "extreme case"), it's pretty much always A Bad Idea to call model stuff from a view.
What you probably want to do in your situation is pass the boolean to the view through the controller. That way, if you change something about the User model, the view doesn't have to know, so long as the controller keeps the behavior the same.
While I only know enough about MVC to get myself in trouble, I've always lived by the fact that unless your view is STRICTLY user interface, then it shouldn't be there.
Also, I've also ran with the idea of thin controllers, fat models.
Going off of these, I'd suggest adding a method to your authentication system model that returns the appropriate view to render and passes that to the view.
Okay, I would really try to keep my Views as logic-free as possible. If you need to switch anything based on e.g. the result of a model method, put a controller in place that delegates the rendering.
Just make sure you follow the basic idea: Do your stuff in the models, Tell your models what to do from your controllers and also tell your views what to show from your controllers.
1) Where does the homepage of your website fit into "controllers"? I've seen some people use a "page" controller to handle static pages like, about, home, contact, etc., but to me this doesn't seem like a good idea. Would creating a distinct controller just for your homepage be a better option? After all, it may need to access multiple models and doesn't really flow well with the whole, one controller per model theory that some people use.
2) If you need a dashboard for multiple types of users, would that be one dashboard controller that would have toggle code dependent upon which user, or would you have say a dashboard action within each controller per user? For example, admin/dashboard, account/dashboard, etc.
3) It seems to me that using the whole simple CRUD example works like a charm when trying to explain controllers, but that once you get past those simple functions, it breaks down and can cause your controllers to get unwieldy. Why do some people choose to create a login controller, when others make a login function in a user controller? One reason I think is that a lot of us come from a page approach background and it's hard to think of controllers as "objects" or "nouns" because pages don't always work that way. Case in point why on earth would you want to create a "pages" controller that would handle pages that really have nothing to do with each other just to have a "container" to fit actions into. Just doesn't seem right to me.
4) Should controllers have more to do with a use case than an "object" that actions can be performed on? For all intensive purposes, you could create a user controller that does every action in your whole app. Or you could create a controller per "area of concern" as some like to say. Or you could create one controller per view if you wanted. There is so much leeway that it makes it tough to figure out a consistent method to use.
Controllers shouldn't be this confusing probably, but for some reason they baffle the hell out of me. Any helpful comments would be greatly appreciated.
1) I use a simple homebrew set of classes for some of my MVC stuff, and it relates controller names to action and view names (it's a Front Controller style, similar to Zend). For a generic web site, let's assume it has a home page, privacy policy, contact page and an about page. I don't really want to make separate controllers for all these things, so I'll stick them inside my IndexController, with function names like actionIndex(), actionPrivacy(), actionContact(), and actionAbout().
To go along with that, inside my Views directory I have a directory of templates associated with each action. By default, any action automatically looks for an associated template, although you can specify one if you wish. So actionPrivacy() would look for a template file at index/privacy.php, actionContact() would look for index/contact.php, etc.
Of course, this relates to the URLs as well. So a url hit to http://www.example.com/index/about would run actionAbout(), which would load the About page template. Since the about page is completely static content, my actionAbout() does absolutely nothing, other than provide a public action for the Front Controller to see and run.
So to answer the core of your question, I do put multiple "pages" into a single controller, and it works fine for my purposes. One model per controller is a theory I don't think I'd try to follow when working with Web MVC, as it seems to fit an application with state much better.
2) For this, I would have multiple controllers. Following the same methods I use above, I would have /admin/dashboard and /account/dashboard as you suggest, although there's no reason they couldn't use the same (or portions of the same) templates.
I suppose if I had a gazillion different kinds of users, I'd make things more generic and only use one controller, and have a mod_rewrite rule to handle the loading. It would probably depend on how functionally complex the dashboard is, and what the account set up is like.
3) I find CRUD functionality difficult to implement directly into any layer of MVC and still have it be clean, flexible and efficient. I like to abstract CRUD functionality out into a service layer that any object may call upon, and have a base object class from which I can extend any objects needing CRUD.
I would suggest utilizing some of the PHP ORM frameworks out there for CRUD. They can do away with a lot of the hassle of getting a nice implementation.
In terms of login controller versus user controller, I suppose it depends on your application domain. With my style of programming, I would tend to think of "logging in" as a simple operation within the domain of a User model, and thusly have a single operation for it inside a user controller. To be more precise, I would have the UserController instantiate a user model and call a login routine on the model. I can't tell you that this is the proper way, because I couldn't say for sure what the proper way is supposed to be. It's a matter of context.
4) You're right about the leeway. You could easily create a controller that handled everything your app/site wanted to do. However, I think you'd agree that this would become a maintenance nightmare. I still get the jibbly-jibblies thinking about my last job at a market research company, where the internal PHP app was done by an overseas team with what I can only assume was little-to-no training. We're talking 10,000 line scripts that handled the whole site. It was impossible to maintain.
So, I'd suggest you break your app/site down into business domain areas, and create controllers based on that. Figure out the core concepts of your app and go from there.
Example
Let's say I had a web site about manatees, because obviously manatees rock. I'd want some normal site pages (about, contact, etc.), user account management, a forum, a picture gallery, and maybe a research document material area (with the latest science about manatees). Pretty simple, and a lot of it would be static, but you can start to see the breakdown.
IndexController - handles about page, privacy policy, generic static content.
UserController - handles account creation, logging in/out, preferences
PictureController - display pictures, handle uploads
ForumController - probably not much, I'd try to integrate an external forum, which would mean I wouldn't need much functionality here.
LibraryController - show lists of recent news and research
HugAManateeController - virtual manatee hugging in real-time over HTTP
That probably gives you at least a basic separation. If you find a controller becoming extremely large, it's probably time to break down the business domain into separate controllers.
It will be different for every project, so a little planning goes a long way towards what kind of architectural structure you'll have.
Web MVC can get very subjective, as it is quite different from a MVC model where your application has state. I try to keep major functionality out of Controllers when dealing with web apps. I like them to instantiate a few objects or models, run a couple of methods based on the action being taken, and collect some View data to pass off to the View once it's done. The simpler the better, and I put the core business logic into the models, which are supposed to be representative of the state of the application.
Hope that helps.