I used to program php in procedural way. Since I would like to learn more about OOP I have decided to program php in OOP way for my new project.
Anyways, let's say I have a project that requires user to login. Which means in login.php once user enters the correct username and password, it will be redirected to index.php and will start loading all the products from the product table and display them nicely in index.php.
Before, how I did this was, in login.php I'll have the following code:
login.php
session_start();
...
if (loggedCorrect($user, $password)) {
$_SESSION['loggedinuser'] = $user;
//redirect to index.php
}
index.php
session_start();
if (isset($_SESSION['loggedinuser']) {
//select fields from products table and display them
...
}
so in OOP it will be something like:
login.php
session_start();
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
$_SESSION['loggedinuser'] = $user->getUsername();
//redirect to index.php
}
index.php
session_start();
if (isset($_SESSION['loggedinuser']) {
$products = new Products();
//display all products
}
Product class
class Products {
private $productArray;
...
__construct() {
//select all products from mySQL table then put every product in productArray
}
...
}
My question are:
when initiating object (like Products in my case). do I have to check login session? if so, should I do it inside __contruct? or should I do it before the "class Products" line?
I also have a cronjob.php, which will be executed every x minutes. When it's executing, it will create some objects like Products and analysis them. So if login session checking is required, then I'm not sure how to make this works, as cronjob doesn't support session.
Please advise
Quick answers
No. Your domain objects themselves should not be dependent on a logged in session; however, they may need a User
instance to perform certain duties, such as only showing the products that a particular user is able to see.
Because of #1, this is now trivial.
Code review
First let's consider your login page code:
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
In this code, it would seem that User interacts with the database and has knowledge how to validate credentials. That seems a bit too much responsibility for a single class.
It could perform password validation by keeping the hashed password inside the object, but you would only need to validate a password once, so there's really no need to keep that field around. Another reason not to have it done here is when you need to consider strengthening your passwords on-the-fly, which could be a site policy to scale with growing hardware (e.g. when you're using bcrypt).
It should definitely not be doing database interaction; to separate both database interaction and password verification from the User class you could consider adding an authentication service.
try {
$user = $authService->login($userName, $password);
$_SESSION['loggedinuser'] = $user;
// redirect to index.php
} catch (InvalidLoginException $e) {
// oops, username or password invalid
}
Inside the authentication service, you could add another layer of abstraction to load the user record (using a data mapper for instance).
Instead of only storing the username in the session, you can store the whole User object as well. In some cases this may lead to inconsistencies, but it saves round trips to the database.
Now, let's observe the product overview page:
$products = new Products();
In terms of naming I would say that Products
is not a good candidate to describe a collection of objects. A name such as ProductList
or ProductCollection
is better.
As with the authentication above, it's unclear how the Products
class gets populated; it should come from some storage, so let's introduce the repository that will provide the list of products:
$productRepository = new ProductRepository($db);
$products = $productRepository->getAll();
In the simplest scenario, the repository gets initialized with a database instance; more levels of abstraction can be applied when necessary.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments