Problem
Suppose you have a class user. You want to be able to return this user object to others so they can use it to extract information using getters. However, you don't want people to be able to readily set the internal state because the internal information should directly relate to a row in the database. Does it make sense to have protected mutators (setters) so that only an extended class could set the variables? Is this a bad practice, irrelevant, overkill or useless?
I have considered trying to limit __construct to one use ( I believe this is sometimes refereed to as a singleton pattern - although I am not sure if I understand entirely. )
I am an amateur programer, forgive any ignorance. Thanks.
Example:
<?php
class user
{
private username;
protected function set_username($username)
{
$this->username = $username;
}
public function get_username()
{
return $this->username;
}
?>
Depends. If nothing in particular needs to happen when the state is changed then you can leave the setters out altogether. Any subclass will have direct access to the properties that are set protected or looser.
If you need something to happen when the state changes (for example having a database UPDATE happen when the state changes) then the setters will make your life a lot easier, as the call to the database updating code be put in the setter. This means if you always go through the setter then the DB will always update when you change the object's state.
So in short, it depends.
If you have a constructor that accepts an id for instance, why would you want to have setters at all. There is no rule forcing you to give an object setters just because it has getters. If your usecase is constructing the object somewhere and after that only use it to extract data from it, simply create no setter at all.
Extending objects can manipulate the protected class variables itself so they don't require any form of setter as well. If you don't want the "outside world" to be able to set something to the class, don't allow it.
Your code is totaly fine and IMHO it encapsulates perfectly. Tt also supports loose coupling.
For easier use, you can add all needed (must have) members as constructor parameters.
Regarding the singleton pattern, use it with care. Users in common aren't singletons. Refer to Refactoring to Patterns (Joshua Kerievsky).
Related
I know this is kind of a question of faith and has been asked many times before, but the answers I've found were either too general, didn't apply to my use case, or didn't satisfy otherwise.
I'm currently building an application that uses classes as representation for database tables. These classes don't offer any methods of their own, I've written a parser class for each one that works with their objects and returns the data in the format I need, which makes the parent classes nothing more than data storages and makes a nice distinction between data and logic.
Now, the consensus in OOP seems to be that you always have to use getters and setters instead of accessing class attributes directly.
An argument I've often heard is that using getters and setters gives the possibility of extending those functions later on, but in my opinion this goes against YAGNI and some other concepts I can't remember the name of right now - that a method should do exactly what you would expect from its name. If I wanted to do something more than simply set a value, I would write a new method, not put that into my setter method, since that one is, per definition, only supposed to set attributes. So I might as well skip the setter and just access the attribute directly.
Another one is that you can put validation in your setters, which I already do in my API that accesses these classes. In my opinion you shouldn't just pass values and have the object tell you if your value is okay or not, but instead validate those values first before you pass them to the object.
I do understand the purpose of private/protected attributes in "usual" classes, but when the class is literally just a data container without any methods, is this really needed? In other words: is there a glaring disadvantage to using public values, when the setter methods for those (were they private) would all just look like public function getAttr($attr) { $this->atrr = $attr; } anyway?
You only need a data structure, but the only suitable PHP construct is the class.
Typically, in object-oriented analysis, design and programming, a class is a model of a thing or concept and it encapsulates any knowledge and/or behaviour of the thing or concept.
However, in the context of this question, encapsulation is not needed since you only require a data structure.
I once questioned a teacher why she used to set properties visibilities as private or protected ALWAYS. She answered me that this is more secure than setting it public, but I'm not really confident in this answer. So, I want to know, even if I ensure that a final user won't have any way to manipulate my classes, is Public property really less secure for properties ? Why ?
No, that's absolute rubbish. It is no more or less secure.
If a user wanted to, they can access a protected/private property on an object:
class Car {
protected $engine = 'V8';
}
$reflector = new ReflectionClass('Car');
$engineProperty = $reflector->getProperty('engine');
$engineProperty->setAccessible(true);
$maserati = new Car;
echo $engineProperty->getValue($maserati); // echoes "V8"
$engineProperty->setValue($maserati, 'I4');
echo $engineProperty->getValue($maserati); // echoes "I4"
So, demonstrably, there is no security benefit.
The benefit is that it helps the end user by marking which functions and properties the class is designed for them to interact with. The developer could totally alter the internals of the class if they wanted to, but the code that calls it wouldn't have to change. If they really want to, the user of the class can muck about with it, but that's their problem if things don't work!
Public properties are not more secure or insecure by themselves as other answers pointed out. But having many public properties can indirectly lead to less secure applications. For example:
Classes with many public properties are more difficult to reason about because those properties can be manipulated by ANY other part of the code instead of just by his own methods. This way the security of the application as a whole can become harder to manage.
In other words: public properties can lead to a bigger attack surface.
This has nothing to do with security. Encapsulation might be the word you/your teacher is looking for.
See What is encapsulation? How does it actually hide data?
Inheritance is another area which is affected by encapsulation.
New features are often added to applications by extending a base class with a child class. New developers that are hired to work on a software project usually use the public methods of classes created by other developers.
If a method is declared as public by mistake then it can be overridden by future developers
I am creating a User class and it is supposed to be an Entity class. In DataBase i created User table and it has 20 fields.
My question is : Is it good to create a "__construct()" with 20 parameters or i should user setter/getter?
I recently read some article about dependency injection and how it makes code more maintainable but i am confused in my own code.
Here it is my __construct function:
class User{
private $userName;
private $userLastName;
...//Other users fields
public function __construct($name,$lastname,$phone,...){
$this->userName = $name;
$this->userLastName = $lastname;
...
}
}
I am looking for best practice to write some readable,clean and maintainable code.
Regards
This has nothing to do with dependency injection. Here you wouldn't be injecting dependencies, but just values.
So the real question is: should you get those values in a constructor, or through getters/setters?
And I'd say using your constructor is a good thing, because it can prevent your model to exist in an invalid state. For example, if you user need to have an email, then by putting it in your constructor your are guaranteed that all users will have emails.
So I suggest that you put in your constructor all the properties that needs to be defined (not null), and use setters for all others (that will help avoid having a 20 parameters constructor).
By having 20 parameters there is a big chance that your class in question violates the Single Responsibility Principle and forms some sort of monolithic class without properly delegating, composing functionality.
Ensure that your class has a low coupling and a high cohesion.
See http://500internalservererror.wordpress.com/2009/02/23/what-do-low-coupling-and-high-cohesion-mean-what-does-the-principle-of-encapsulation-mean/
As we are not doing full code review here (go to https://codereview.stackexchange.com/ instead)
I suspect you are passing things like country, zip, phone number etc all as parameters.
Ask yourself what data is absolutely required to construct a valid object.
If you have a class Person which requires a property called Name then having a setter for Name but not a ctor argument allows you to create incomplete classes. This shifts the burden of maintaining consistency to every method as you cannot be sure that Name has been set. Such code is bad and typically results in carrying some "initialized" flag or a function and clutter your code with checks.
Your ctor should contain the minimal set of parameters. Everything else can be done via properties or being further composed, e.g. an Address class removing the complexity of passing zip, state, street, etc all in the parent ctor.
You may create a "Contact" class storing email and phone numbers, etc.
It's better to use getter and setter. A __construct method with 20 parameters is to huge. And without getter how you want to access to your private User attributes ?
Please note I'm not looking for 'use a framework' answers. I'm trying to structurally improve the way I code websites and approach databases from PHP.
I'm building a web service from scratch, without any frameworks. I'm using a LAMP stack and am trying to learn a bit of PHP's OO functionality while I'm at it. I've previously only used OO to make mobile apps.
I've been at it for months now (as planned, no worries). Along the way I've bumped into a couple of structural problems, making me wonder what the best way would be to make the code object oriented.
Pretty much all of the problems involve the database in some way. Say we have a class DB and a class User. In most cases I only need to fetch a single user's information from the database. I thought a good way to handle it was to have a global $_db variable and have the User object query the database like so (oversimplified):
class User {
function __construct($id) {
global $_db;
$q = $_db->query("SELECT name, mail FROM user WHERE id = ?", $id);
$this->loadProperties($q);
}
}
Now say we have a page that shows a list of users. I still want to make User objects for each of them, but I don't want to query the database for each separate user.
So, I extend the User class to take an object as an argument:
class User {
function __construct($id) {
if(is_object($id))
$q = $id;
else {
global $_db;
$q = $_db->query("SELECT name, mail FROM user WHERE id = ?", $id);
}
$this->loadProperties($q);
}
}
Now I can create a list of, for example, the 100 most recently created and active accounts:
$user_list = [];
$q = $_db->query("SELECT name, mail FROM user WHERE banned = 0 ORDER BY date_created DESC LIMIT 100");
while($a = $_db->fetch($q))
$user_list[] = new User($a);
This all works great, except for one big downside: the database queries for table user are no longer in one place, which is kind of making spaghetti code. This is where I'm starting to wonder whether this can be done more efficiently.
So maybe I need to extend my DB object instead of my User object, for example:
class DB {
public function getUsers($where) {
$q = $this->query("SELECT name, mail FROM user WHERE ".$where);
$users = [];
while($a = $this->fetch($q))
$users[] = new User($a);
}
}
Now I would create the user list as follows:
$user_list = $_db->getUsers("banned = 0 ORDER BY date_created DESC LIMIT 100");
But now I'm calling the getUsers() method in various places using various SQL queries, solving nothing. I also don't want to load the same properties each time, so my getUsers() method will have to take entire SQL queries as an argument. Anyway, you get the point.
Speaking of loading different properties, there's another thing that has been bugging me writing OO in PHP. Let's assume our PHP object has at least every property our database row has. Say I have a method User::getName():
class User {
public function getName() {
return $this->name;
}
}
This function will assume the appropriate field has been loaded from the database. However it would be inefficient to preload all of the user's properties each time I make an object. Sometimes I'll only need the user's name. On the other hand it would also be inefficient to go into the database at this point to load this one property.
I have to make sure that for each method I use, the appropriate properties have already been loaded. This makes complete sense from a performance perspective, but from an OO perspective, it means you have to know beforehand which methods you're gonna use which makes it a lot less dynamic and, again, allows for spaghetti code.
The last thing I bumped into (for now at least), is how to separate actual new users from new User. I figured I'd use a separate class called Registration (again, oversimplified):
class Registration {
function createUser() {
$form = $this->getSubmittedForm();
global $_db;
$_db->query("INSERT INTO user (name, mail) VALUES (?, ?)", $form->name, $form->mail);
if($_db->hasError)
return FALSE;
return $_db->insertedID;
}
}
But this means I have to create two separate classes for each database table and again I have different classes accessing the same table. Not to mention there's a third class handling login sessions that's also accessing the user table.
In summary, I feel like all of the above can be done way more efficiently. Most importantly I want pretty code. I feel like I'm missing a way to approach the database from an OO perspective. But how can I do so without losing the dynamics and power of SQL queries?
I'm looking forward to reading your experiences and ideas in this field.
Update
Seems most of you condemn my use of global $_db. Though you've convinced me this isn't the best approach, for the scope of this question it's irrelevant whether I'm supplying the database through an argument, a global or a singleton. It's still a separate class DB that handles any interaction with the database.
It's a common thing to have a separate class to handle SQL queries and to keep the fetched data. In fact, it is the real application of the Single Responsibility Principle.
What I usually do is keep a class with all the information concerning the data, in your case the User class, with all the user information as fields.
Then comes the business layer, for instance UserDataManager (though the use of "Manager" as a suffix is not recommended and you'd better find a more suitable name in each scenario) which takes the pdo object in its constructor to avoid use of global variables and has all the SQL methods. You'd thus have methods registerNewUser, findUserById, unsuscribeUser and so on (the use of "User" in the method can be implied by the class name and be omitted).
Hope it helps.
I've liked to use the data mapper pattern (or at least I think that's how I'm doing it). I've done this for some sites built on Silex, though it's applicable to going without a framework since Silex is very lightweight and doesn't impose much on how you architect your code. In fact, I recommend you check out Symfony2/Silex just to get some ideas for ways to design your code.
Anyway, I've used classes like UserMapper. Since I was using the Doctrine DBAL library, I used Dependency injection to give each mapper a $db. But the DBAL is pretty much a wrapper on the PDO class as far as I understand, so you could inject that instead.
Now you have a UserMapper who is responsible for the CRUD operations. So I solve your first problem with methods like LoadUser($id) and LoadAllUsers(). Then I would set all the properties on the new User based on the data from the database. You can similarly have CreateUser(User $user). Note that in "create", I'm really passing a User object and mapping it to the database. You could call it PersistUser(User $user) to make this distinction more clear. Now all of the SQL queries are in one place and your User class is just a collection of data. The User doesn't need to come from the database, you could create test users or whatever else without any modification. All of the persistence of `User is encapsulated in another class.
I'm not sure that it's always bad to load all of the properties of a user, but if you want to fix that, it's not hard to make LoadUsername($id) or other methods. Or you could do LoadUser($id, array $properties) with a set of properties taht you want to load. If your naming is consistent, then it's easy to have set the properties like:
// in a foreach, $data is the associative array returned by your SQL
$setter = 'set'.$property;
$user->$setter($data[$property]);
Or (and?) you could solve this with Proxy objects. I haven't done this, but the idea is to return a bunch of UserProxy objects, which extend User. But they have the Mapper injected and they override the getters to call into the Mapper to select more. Perhaps when you access one property on a proxy, it will select everything via the mapper (a method called populateUser($id)?) and then subsequent getters can just access the properties in memory. This might make some sense if you, for example, select all users then need to access data on a subset. But I think in general it may be easier to select everything.
public function getX()
{
if (!isset($this->x)) {
$this->mapper->populateUser($this);
}
return $this->x;
}
For new users, I say just do $user = new User... and set everything up, then call into $mapper->persist($user). You can wrap that up in another class, like UserFactory->Create($data) and it can return the (persisted) User. Or that class can be called Registration if you'd like.
Did I mention you should use Dependency Injection to handle all of these services (like the Mappers and others like Factories maybe)? Maybe just grab the DIC from Silex, called Pimple. Or implement a lightweight one yourself (it's not hard).
I hope this helps. It's a high-level overview of some things I've picked up from writing a lot of PHP and using Syfmony2/Silex. Good luck and glad to see PHP programmers like yourself actually trying to "do things right"! Please comment if I can elaborate anywhere. Hope this answer helps you out.
You should first begin by writing a class as a wrapper to your Database object, which would be more clean that a global variable (read about the Singleton Pattern if you don't know it, and there is a lot of examples of Singleton Database Wrapper on the web). You'll then have a better view of the architecture you should implement.
Best is to separate datas from transactions with the database, meaning that you can for example have two classes for your User ; one that will only send queries and fetch responses, and the other that will manage datas thanks to object's attributes and methods. Sometimes, there can be also some action that doesn't require to interact with the database, and that would be implemented in these classes too.
Last but not least, it can be a good idea to look a MVC frameworks and how they work (even if you don't want to use it) ; that would give you a good idea of how can be structured a web application, and how to implement these pattern for you in some way.
I'm used to make pretty much all of my class variables private and create "wrapper" functions that get / set them:
class Something{
private $var;
function getVar(){
$return $this->var;
}
}
$smth = new Something();
echo $smth->getVar();
I see that a lot of people do this, so I ended up doing the same :)
Is there any advantage using them this way versus:
class Something{
public $var;
}
$smth = new Something();
echp $smth->var;
?
I know that private means that you can't access them directly outside the class, but for me it doesn't seem very important if the variable is accessible from anywhere...
So is there any other hidden advantage that I missing with private variables?
It's called encapsulation and it's a very good thing. Encapsulation insulates your class from other classes mucking about with it's internals, they only get the access that you allow through your methods. It also protects them from changes that you may make to the class internals. Without encapsulation if you make a change to a variable's name or usage, that change propagates to all other classes that use the variable. If you force them to go through a method, there's at least a chance that you'll be able to handle the change in the method and protect the other classes from the change.
It differs from case to case if you want to use private variables with public getters and setters or if you just want to declare a variable as public directly.
The reason it might be good to use "getters" and "setters" is if you want to have control over when someone accessess the data.
As an example, lets say you got this:
public setBirthday($date)
Then you can make sure that the date passed in to that setter is a valid birthdate.
But you can't if you just declare the variable as public like this
public $birthday;
Based on comments.
Also, if you decide change the
internal storage mechanism from a
string containing the date to the
number of seconds since 1/1/1970, you
can still present the date externally
in the same way if you use
encapsulation, but not if you expose
the variables directly. Every piece of
code that touched the internal
variable directly would now be broken.
This means that if the internal storage mechanism would change to numbers of seconds from 1/1/1970 then you don't have to change the 'External API'. The reason is because you have full control over it:
public getBirthday() {
// you can still return a string formatted date, even though your
// private variable contains number of seconds from 1/1/1970
}
Access modifiers don't make a whole lot of sense in scripting languages. Many actual object-oriented languages like Python or Javascript don't have them.
And the prevalence of naive getter/setter methods is simply due to PHP not providing an explicit construct for that. http://berryllium.nl/2011/02/getters-and-setters-evil-or-necessary-evil/
It is to demark variables that are internal to the implementation of the class, from variables that are intended for external change. There are also protected variables, which are for internal use, and use by extensions to the class.
We make the variables private so that only the code within the class can modify the variables, protecting interference from outside, guaranteeing control and expected behaviour of the variable.
The purpose of encapsulation is to hide the internals of an object from other objects. The idea is that the external footprint of the object constitutes it's defined type, think of it like a contract with other objects. Internally, it may have to jump through some hoops to provide the outward-facing functionality, but that's of no concern to other objects. They shouldn't be able to mess with it.
For example, let's say you have a class which provides calculations for sales tax. Some kind of utility service object, basically. It has a handful of methods which provide the necessary functionality.
Internally, that class is hitting a database to get some values (tax for a given jurisdiction, for example) in order to perform the calculations. It may be maintaining a database connection and other database-related things internally, but other classes don't need to know about that. Other classes are concerned only with the outward facing contract of functionality.
Suppose sometime later the database needs to be replaced with an external web service. (The company is going with a service for calculating sales tax rather than maintain it internally.). Because the class is encapsulated, you can change its internal implementation to use the service instead of the database very easily. The class just needs to continue to provide the same outward facing functionality.
If other classes were mucking around with the internals of the class, then re-implementing it would risk breaking others parts of the system.