I'm making a simple PHP application with Twitter/Facebook integration to practice OOP concepts and patterns, and I need help with how it should be designed.
What my app will do
Basically, once the user logs in, he's show a form with title and body field. When he clicks on "Post", this content will be appropriately transformed and posted to Facebook and Twitter. Of course, he'll also get an option to authenticate my FB/Twitter app if he hasn't already done so. That's what I'm trying to achieve.
The structure I've come up with till now
Since database access will have to be shared amongst multiple files, I'm using a Singleton pattern. Essentially, I have a DB class with a static mysqli link and a static method to get this database link. The models will use mysqli functions with this single link. (I don't want to abstract the database type just yet.)
I have a User class which holds a user's data, like it's id, username and hashed password. It has methods to retrieve user based on id, credentials and even save the current user to the db.
An Auth class manages session and returns a User object for a valid user. So, it manages logging in, and keeping the user logged in between page visits.
The structure I'm having problem with
I now need access to the Twitter and Facebook information of the user. Of course, they'll be in separate tables, and have separate classes to interact with them. But each of this class is associated with a User.
So, when I'm fetching user information from the database, I'll also use JOINs to fetch corresponding data from the Twitter and Facebook table. Then, my plan is to have a Twitter and Facebook object instantiated within my User object. So, these two classes can be accessed as say $user->twitter->post("Something");.
Is this a good structure, or is there a better way to organize classes? This is a simple app, and coding is not my concern. My concern is the structure, since I should be able to add new social networks to the application.
It is preferable to keep persistence functions out of domain objects. Instead of having the User class load and save itself, I would have a UserRepository interface, for example:
interface UserRepository {
public function findUser($username);
public function save(User $user);
}
and a MysqlUserRepository class that implements this interface. That way you keep database-specific code out of the User class.
Similarly, I would pull social networking functions into their own interface, say:
interface SocialNetworkService {
public function post($status);
}
and separate implementations for FacebookService and TwitterService. This allows you to add support for new social networks without having to modify the User class.
These services can then simply wrap around a user object and provide their services for that user:
$fb = new FacebookService($user);
$fb->post("blah");
A common principle behind all of these decisions is the single responsibility principle: your User class should have only one reason to change, and that is when you need to change the model of a user. Any other changes, such as dealing with databases or social networks, shouldn't affect the User class.
Related
I'm having trouble getting my head around the best way to perfect my system. Currently, it's pretty archaic, so I'm interested to know if you have any suggestions about improving it?
User Class -> handles data and basic functions on users that are referenced on the page. The __construct takes an ID and uses the get_user() function to get the user's data with the given ID.
UserService (extends User) -> handles login, logout, etc. Is called at the top of every file to figure out if a user is logged in, and is defined as $user = new UserService(); every pageload, which presents the current user's data from User class.
UserNotifications (extends user) -> handles user notifications.
The problem that I'm having is that I have various child classes, such as the ones above, that interact with each other and I don't want them each calling an instance of the parent that may already be instantiated through another child.
Obviously that adds unnecessary queries. What's the best way to pass parent instances between child classes?
At this point, I'm a novice to OOP, and I've been stumped by this. I also apologise for the lack of clarity. I hope that you understand.
I'm a bit confused on how to perform insert and update statements using MVC.
Is it ok to create an instance of an object in your controller and pass it to your service to save it or do you pass data to your service and handle everything else in there?
Insert
In my controller something like:
$userservice->insert("myname","mypassword");
In my UserService:
function insert($username,$password){
$user = ORM::for_table('user')->create();
$user->username= $username;
$user->password= $password;
$user->save();
}
Update
In my controller something like:
$userservice->update("myname","mypassword",1);
In my UserService:
function insert($username,$password,$id){
$user = ORM::for_table('user')->find($id);
$user->username= $username;
$user->password= $password;
$user->save();
}
Is this good practice?
Because I see a lot of these answers where for example a user is being created in the controller and passed to a repository to save it:
Proper Repository Pattern Design in PHP?
But I don't like the idea of creating a user in the controller...
Controllers belongs to application layer and controlls only activity. In your example the activities are Create- and Update for an existing or for a new User. These operations belongs to the Domain Layer, which contains services. Thus services encapsulate the domain as a gatekeeper and provides operations for resolving domain like a facade.
Is it ok to create an instance of an object in your controller and pass it to your service to save it or do you pass data to your service and handle everything else in there?
The service should provide a method to pass a ValueObject. ValueObjects are better to encapsulate lot of data (Property values for User). Inside the service, the ValueObject should be delegated to Filter and Validator. If validation didn't fail the ValueObject will be delegated to a DataMapper. The DataMapper will map the properties of ValueObject to a data-model for the UserRepository (ORM). Repositories often need another model of data, e.g. Objects versus storage mediums based on RDBMS like MySQL.
This approach should be strict to seperate the concerns between layers to improve maintainabilty and interchangeabilty. Services should be thin and acts as a delegator to Domain Objects (Filter, Validator, etc.), for example see Service Layer Pattern.
So, where should be a value object created?
I would prefer that the service provides a method for this: getEntityPrototype() by using the prototype pattern.
Be careful with naming. ValueObject is an object which have no identity. Entity is an object with identity (here id of User). For an existing User you will have have a method like getUserById($id), which should return an UserEntity. If User does not exist for given id, it should return a NullObject. To create a new User getEntityPrototype() will return an UserEntity which have no identity yet, so you will call it ValueObject or better Prototype of Entity. After setting properties (e.g. by a FormObject) and persisting this object is a real entity. In a Factory for this service you can set the EntityPrototype.
What you should think about in this case is if the classes have only one responsibility.
Controller decides about the flow of the action. If there's a need for registering a user then it registers him, but it should not define how to do it, but ask a service to complete this task and get the result.
On the other hand you should have some kind of UserManager which updates, creates and fetches users - is this single responsibility? Kinda, yes - it's managing them in a broad sense.
There's a slight problem you have with your methods' names though. You should have registerUser not insert since it's way easier to tell what it actually does.
You should Pass Data to Model. MVC is all about dividing tasks Controller - Handles Application Flow, Model - Contains all the business login Database etc and View - here you decide how to show. Basically the UI part is stored here
So the Controller should send data to Model and model decides what to do with the data. The advantage of coding this way is that in future if you want to change something in the code you know where to look, or if you ask a designer to redesign your website you only have to give him the VIEW part of code . If the designer does something that caused an error , correcting that wont take that much time. If you follow MVC properly Adding,Updating or Maintaining functionality wont be a problem
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.
<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
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.
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
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
I have an app that is essentially a wrapper for a 3rd party API. The app does not use a database and only stores a single cookie which is the session ID that the API requires.
The API is a shopping system which allows users to
-login/register/edit profile/logout
-buy merchandise
-make a donation
-become a member
The API has 50 or so methods that my app needs to connect to. Example API calls are addItemToBasket(), addDonation(), GetUserDetails() etc.
I am trying to work out what should be classes in my application. Here is what I have so far:
Classes
1) APIManager() Class
Contains the methods that match one-to-one with the methods exposed in the 3rd party API and provides the mechanism to make a connection to the remote API server. So a user would be logged in via
APIManager->loginUser($sessionKey, $uid, $pwd);
and the remote API would set the user as logged in. If needs be, my app can check the logged in status of any session key by calling the API:
APIManager->isLoggedIn($sessionKey);
2) User() Class
This holds methods that contain business logic required before processing API calls such as Register or Login. An example method is:
function login($_POST) {
//perform sanity checks, apply business rules etc.
//if certain conditions are met, we may pass in a promo code, $pc
APIManager->loginUser($sessionkey, $_POST['uid'], $_POST['pwd'], $pc);
}
I realise that I could probably just make a call to APIManager from the login page, rather than having a User class per se, but I felt that since some business logic needs to run before we actually call the API's loginUser() method, it felt right to have that handled within a User class. I'd be keen to know what people think about this.
3) Basket() Class
The basket is managed in the 3rd Party API, so my app's role is to make the appropriate API calls to add new items to the basket, remove items, view the basket etc. My app knows nothing about the basket until the data is retrieved from the API, nor can it make any changes to the basket without going via the API. Again, it felt appropriate to group this related logic into a Basket class. The front end web page might call something like:
Basket->addItem(23);
and this addItem() method in the Basket class would looks something like:
addItem($itemID) {
//perform checks, apply business rules e.g. if user is eligible for discount
APIManager->addToCart($itemID, $discount);
}
where addToCart() is the third party API method we call to process the item.
4) Donation() Class
This allows users to make a donation. The donation appears in the basket and can be removed from the basket. I thought of just adding an addDonate() method to the Basket class and not worry about having a Donation object at all, but... (see below)
5) Membership() Class
... memberships are actually a type of donation! The API will treat donation going into a certain account as being a 1 year membership, and not a plain donation. We cannot change the logic/behaviour of the 3rd party API.
So, if I donate $50 to account '1' then it's just a normal donation, but if I donate $100 to account '8' then I become a member with all the member benefits (reduced prices, no postage fee etc).
Here's where I'm not sure of the best way to design this.
Should I create a Donation class and then extend that with Membership, since all of the Donation methods will be required by Membership. But Membership will need additional methods such as renew() or getExpiry() etc.
Also, should I look at extending User to become Member? Again, a member has all of the core methods that User has, but also has additional ones such as getSpecialOffers() or getDiscountCode() that only members would access.
Any guidance in how to best approach the design would be very much appreciated.
Thanks, James
Personally, I would build this in 3 layers.
Layer 1: API Interface
This layer is where the actual line-level calls to the remote API take place. This layer is all about the protocol. There should be nothing in this layer that's API specific. Everything should be 100% generic, but should be able to be used by the middle layer to interact with the API. Note that this layer can come from a library or another source like a framework. Or you could write it custom. It all depends on where you are and your exact needs.
Some classes that might belong here:
XMLRPC_Client
SOAP_Client
REST_Client
Layer 2: API Adapter
This layer actually has the API information hard-coded into it. This is basically the Adapter Pattern. Basically the job of this layer is to convert the remote API into a local API using the Interface layer. So, depending on your need, you can mirror the remote API in a 1:1 manor, or you could bend this to your needs a little bit more. But the thing to keep in mind is that this class is not about providing functionality to your program. The purpose is to decouple the remote API from your local code. By swapping out this class, your code should be able to quickly adapt to use different versions of the remote API and possibly even different remote APIs all together.
An important thing to remember is that this Adapter layer is meant to encompass the API. So the scope of each individual class is the entirety of an API implementation. So there should be a 1:1 mapping between adapters and remote APIs.
Some classes that might be here:
RemoteAPI_v1_5
RemoteAPI2_v1
Layer 3: Internal Objects
This layer should be your internal representation of the different objects (In your specific case: User, Basket, Cart, Donation, Membership, etc). They should not directly call the API, but use Composition (Dependency Injection) to become what's basically a bridge to the API. By keeping it separated, you should be able to vary the API completely independent from the internal classes (and vise versa).
So, one of your classes might look like this:
class User {
protected $api;
public function __construct(iAPIAdapter $api) {
$this->api = $api;
}
public function login() {
$this->api->loginUser($blah);
}
}
That way, there's no real need for an API manager so to speak of. Just create a new instance of the API at the start of the program, and pass it around to the rest of your code. But it has the major benefit of being quite flexible in the sense that you should be able to change APIs (either version or the call itself) by simply swapping out the adapter layer in your code (when you instantiate the adapter). Everything else should just work, and you should be completely isolated from changes to either your code or the remote API (not to mention that it should be quite testable if built this way)...
That's my $0.02. It might be overkill, but that's really depending on your exact need...
I'd say:
create a donation class with all that it needs
create a member variable of membership (which should be of the type Donation).
you can have a method in the membership class such:
public function makeDonation($data) {
$this->donation = new Donation($data) // maybe with the data parameter;
$this->donation->commit() // whatever it does to set things up
......
whatever you need
}
This way you have nice decoupling between the items. Also the Donation should implement an iterface so that if behavior is later changed it should still contain the methods required by the memeber class.
Thsi way it is more flexible than inheritance.
I had asked a similar question some time ago and got a good answer:
Elegant alternatives to the weird multiple inheritance