I have two simple questions regarding OOP practice of classes. I expect that the answers will lean toward subjective preferences.
Let's say we have a class like a blog POST, which has private variables such as id, author, etc. I see in Symfony demo project the getter and setter methods are declared for almost each variable specifically. If the list is long, this seems quite tedious. So what about creating a method like the following?
function setProp($variable, $val){
if($variable !== 'id'){
$this->$$variable = $val;
}
}
I see that the Symfony demo created three entity classes: Comment, Post, User. The addComment and removeComment methods are in Post class and takes a typecast argument of Comment class. Can we make a removeComment method in the Comment class itself? Because I feel that most of the time the comment id would be the first piece of info passed to the script, so why not have such a method handy in the class itself? And is it 'bad' to have repeated methods that perform the same job in different classes?
The purpose of accessor methods is to provide a way to hook into the action of setting or getting a property.
For basic operations, you don't need accessor methods. They may seem pointless just assigning or returning a value.
One of the main purposes of accessor methods is restricting access to a property. You may want, under some conditions, to prevent the changing of a property. If the property is public, there is nothing you can do to prevent writing to the property. But if your property is private and you have a setter, then you may just not set the property under certain conditions.
private $allowed = true;
private $data;
public function getData() {
return $this->data;
}
public function setData($data) {
if ($this->allowed) {
$this->data = $data;
}
}
public function block() {
$this->allowed = false;
}
In this example, you may block write-access to the data property by setting the allowed property to false.
There are many other cases that make use of accessors (storing data outside the object, converting values, etc.)
It is good practice to use setters and getters from the start because if you create them later, you have to replace all references to the property with references to the setter/getter.
you can look at magique method __set (http://php.net/manual/fr/language.oop5.overloading.php#object.set) but it's better to write each setXxxx
Related
I have done a few projects lately using a Database Object super class which I use for quick one off record query/update, and extending with appropriate classes, such as a User class.
I found that many classes I was writing had the exact same methods: query_values(), update(), delete(), etc.
So I came up with a class with a constructor that looks like this:
public function __construct($table, $db_object, $record_id = null){
$this->db = $db_object; // Database object with query methods
$this->table = $table; // The name of the database table
$this->get_column_data();
if(!is_null($record_id)){
// This retrieves all column values,
// stores into private $fields array property
$this->query_values($record_id);
}
}
And a child class constructor looks like this:
public function __construct($db_object, $record_id = null){
parent::__construct($this->table, $db_object, $record_id);
}
Where the $table property is defined at the top, as we should know which table this specific object works with.
Now, all common record management methods are in one place, and methods specific to the class are all that is defined in their respective child-classes.
The biggest drawback I see here is that all data fields are pulled and are encapsulated within the $fields property, so either generic get and set methods need to be defined (which I typically do) which almost negates the encapsulation*, or a method must be defined specifically for each property we want to expose.
*Example:
$user_id = $User->id; // NOT USING MY METHOD
vs.
$user_id = $User->_get('id'); // ACCESSES $User->fields['id']
Do you see this as a drawback, or a plus? The goal being ease of use, object-orientation (encapsulation), and just being plain awesome!
Well, you could make your life easy and use PHP's magic overloading __call method to create generic getters and setters. You could add the following method to your "Database Object super-class":
/**
* Create magic getter and setter methods to access private $fields array
*/
public function __call($method, $args)
{
$prefix = substr($method, 0, 3);
$prop = lcfirst(substr($method, 3));
if (isset($this->fields[$prop])) {
if ($prefix == 'get') {
return $this->fields[$prop];
} elseif ($prefix == 'set') {
if ( ! isset($args[0])) {
$msg = 'Missing argument: ' . get_class($this) . "::$method must specify a value";
throw new InvalidArgumentException($msg);
}
$this->fields[$prop] = $args[0];
return;
}
}
$msg = 'Invalid method: ' . get_class($this) . "::$method does not exist";
throw new BadMethodCallException($msg);
}
So let me explain what's going on here. The magic __call method will receive calls to any object method that does not match one of the object's concrete methods. It receives as parameters the name of the method that was called and an array of its arguments.
The __call method above does a quick substr check to see if the method was a "getter" or "setter" (using the first three letters of the method name). It expects that your $fields array stores lower-case "property" names (lcfirst) and uses everything after the setter/getter prefix as the expected property name.
If a property matches the getter method then that property it is returned. If not, the SplException BadMethodCallException is thrown. This is a best practice since the inclusion of the Spl exceptions in PHP.
Likewise a setter method will also throw the SplException InvalidArgumentException if no argument was specified.
PHP's magic methods will change your life. You can also use __get and __set to assign $fields array values in a similar fashion without making faux method calls. Get excited :)
You can have the best of both worlds by implementing a few magic methods on your objects. For example, by implementing __get, __set and __isset you can make the property accesses look "natural" (e.g. $user->id) while at the same time not having to define properties in each separate subclass.
For example, the implementation of __get could check at runtime the $fields member to see if the property you are attempting to get is valid for the specific object class. You can write this generic implementation once in the base class, and just populate $fields accordingly to make it work with any kind of object. This is actually what all modern mapping tools do, including probably all of the PHP frameworks that you have heard of.
As an aside, I hope you are caching the table schema per-class inside get_column_data. It would be really inefficient to requery the database for the schema of the same table every time you construct an object of the corresponding class.
There are two major approaches:
PHP file creation
All big ORM / database projects I know do not let the user write all getter methods himself. Both Doctrine and Propel use automatical generators to create real PHP files with the getter methods when you call a command line script. These files contain so called Base methods which are automatically extended by some classes you will put your own code in (so recreation of the base class will not delete your own code).
Advantage of file creation is that you have a well defined interface (some people dislike it when callable methods are not visible directly within the source code).
Magic methods / overloading
A database engine I have seen at client’s application used magic methods to simulate getters and setters. You could either use magic methods __get() and __set() or __call() (called “overloading” in PHP documentation) for this. Which method to use depends on how you want to access your values (most common $obj->property or $obj->getProperty()).
Advantage of overloading is that you do not need to write a complex PHP code generator, nor do you need to call a command line script each time you change your database design.
I'm trying to learn when static functions should be used, and have had a difficult time finding an answer my questions. I am creating a class User, which is related to a class Group. If I have a user id and I want to get a user object from that, is it better to do something like
$existingUser = User::get($userId);
where the class is defined like this
class User()
{
public static function get($id){
$user = new User();
return $user->findById($id);
}
public function findById($id) {
//find and populate user object
}
}
or
$existingUser=new User();
$existingUser->findById($userId);
where the class is defined like this
class User()
{
public function findById($id) {
//find and populate user object
}
}
What about if I were to write a function which returns an array of Group objects based on a user id?
class User()
{
//stuff
$groupArray = Group::getAllByUserId($this->getId())
//stuff
}
or
class User()
{
//stuff
$group = new Group();
$groupArray = $group->findAllByUserId($this->getId());
//stuff
}
The second method creates an empty group object which is never used. Does it matter?
Am I misunderstanding the concept of static? I know it is useful for not having to instantiate a class, so if the function instantiates one anyway, does that kind of defeat the purpose? If so, what would be an example of when a static function would be used?
Anything else I should be considering in this over simplified example?
You don't need a static function int he case you show above.
Static functions are really just global functions with a namespace.
Use them when the global state of the application needs to be controlled, or if multiple copies of the function lead to inonsistant results.
Callbacks sometimes need to be static, especially if they are passed as a string.
I'm trying to learn when static functions should be used
Oh, it's so simple: never.
To understand it, read:
http://www.objectmentor.com/resources/articles/ocp.pdf
http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/
I find a good rule of thumb is thinking "If I don't have a [class-name], would I expect to be able to call [method-name]?"
If I don't have a user, would I expect to be able to call findByID?
Probably not. This is one of the exceptions I come across; a "load" or a "save" method sometimes makes sense to be static.
A perfect example of when to use non-static methods is (most methods in) a Database class - you should always have a database object before you try to run a query on it.
An example of when to use a static method would be a "helper" class, essentially a collection of handy functions. Say you have some methods that help you output HTML, you might have HTML::image(), HTML::url() and HTML::script(). On these, you shouldn't need a HTML object to create an image, URL, and so on.
As for stopping multiple copies of objects being created (one argument for using static methods), you should use a Singleton pattern instead (Google it) to ensure only one copy of the object ever exists.
You should probably check out this question on Active Record vs data mapper:
https://stackoverflow.com/questions/2169832/data-mapper-vs-active-record
One take from this question is that static methods on the class for loading/saving aren't really the core functionality of the class in most cases. Further, storing and loading is a kind of abstract concept that is separate from your class objects in most cases.
Isa "user" a data storage and retrieval object? In most cases, no, it is a person represented in your system that has various properties and functions. When you start tying the persistence of that object into the object, you break encapsulation and make it harder to maintain the code. What if next week you want to load your users out of memcache? It's hardly relevant to if a user can have some property or functionality.
Or in more specific words, is it "ok" to not be relying on setters and getters?
I'm dealing with a class that checks the availability of rooms and sets public properties of which there are more than a dozen. Things such as:
unitNumber
roomTypes ( array )
codeCorporate
codeGroup
numberKids
numberAdults
numberRooms
currency
minRate
maxRate
soapServer
units ( array )
hotelId
And after an object is instantiated those properties are set with $this-> inside various methods. However the code that deals with the object often sets public properties directly instead of using getter/setter methods:
$object->something = 3;
foreach ($object->things as $thing ) { }
If I have the time to refactor this class..
Should I stick all of these properties in a data array that's a private property, and define __set and __get methods?
Should I make a single getter method for each of the properties?
In my opinion, it is rarely a good idea to have any public members. It increases coupling between classes, and makes refactoring very complicated (should you need it.)
Setters/Getters are the way to go, and the very small performance penalty that you pay for it is usually either optimized away, or trumped by elegance.
To answer your question about array vs. single-getter-per-var, it's a matter of taste. I tend to only keep variables of a similar type within an array, and separate the rest.
I personally have yet to find a truly good reason for a public property, though im open for suggestion :-)
Although i much prefer specified getters/setters for each property (whether that's a proxy to a generalized get($name) or not). I assume you have other code already that uses direct assignment so in that case i would say to proceed with using the magic __get/__set methods.
I think most people will recommend using setters & getters. Right now you're limited to simply setting & fetching the property, but what if you want to log when that property is accessed? Or perhaps you want to run the value by a validation function first (email, phonenumber, zip code, etc). Maybe you'll need to call another function, or set another property. I think you see where I'm heading with this. By using setters & getters, you add a valuable layer of encapsulation to your classes, and 99% of the time this is worth the extra typing you'll need to do ;) Imagine trying to do the examples above without setters & getters. It'd be a big headache to say the least.
Edit: I forgot to mention Doctrine. It's an object relation mapper (ORM) that can automatically setup setters & getters for you (amongst other things). You can check it out at http://www.doctrine-project.org/
I would take a step back and ask some more general questions:
Why am I having to expose this much information; what is using it and why?
Is this class really just a data structure without behavior, in which case should be a private class to some other class?
Does this class serve a single purpose, or is it on the path to becoming monolithic?
You may discover that you are able to create views of an instance of a class to export to a database, display in a form, etc. Check out the "Builder" and "Acyclic Visitor" patterns to start with.
Regarding accessors, I do not see a need to use them for what you are describing: retrieving class properties and internal state information, aka a struct. However, for attributes of a class I could see the benefit in certain cases, but more for retrieving attributes, not for mutations of your object's state.
If I may add my grain of salt several months later :
It is very un-OO to have public properties. Everything should be encapsulated, simply because (among other reasons) using direct attribute manipulation doesn't give you ways to easily refactor or perform (more) control checks when some external source modifies the field. For example, let's say you have a class with many fields that is used throughout a project several times, and that project contains several thousands of files; it's a project that has been running and expanded for a few years now. Let's say that the company is changing it's business model, or that a problem is found with some of the field's data type and now is required to have some validation; will you duplicate that validation in all those thousands of source code that is directly accessing the public member? In PHP, the solution may be simple, but not in most OO programming language (i.g. Java). The fact is that OO is based on encapsulation. In short, encapsulation doesn't only produce clean code, but also highly maintainable (not to say cost-effective and cohesive) code.
Your suggestion of having a private member (array) being manipulated by __get / __set is good. This way, if you need some extra validation along the road, simply create your setter and/or your getter and it will be the end of it. Some may argue with that being counter productive as the code completion cannot kick-in on __get / __set. IMHO, relying on code completion is simply lazy coding. But then again, having every member have it's own getter and/or setter allows you to write a more comprehensive API documentation. Personally, I usually use that technique for internal or very general purpose classes. If all your fields do not require any validation, or there are as you said several dozen of them, then using magic methods would be acceptable, in my opinion.
The bottom line is to avoid direct member access on class instances, period. How you decide to achieve this is strictly up to you. Just make sure that the API is well documented the more abstract you make it.
On a final note, in PHP, if you already have classes that are being used that are not encapsulating their fields, for example something like
class SomeObject {
public $foo;
public $bar;
public $baz;
//...
}
you can simply fix this class without having to refactor anything with something like :
class SomeObject {
private $_foo; // having underscore as prefix helps to know what's private/protected
private $_bar; // inside the code.
private $_baz;
public function __get($name) {
$methodName = 'get'.ucfirst($name);
if (method_exists($this, $methodName)) {
return $this->{$methodName}();
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function __set($name, $value) {
$methodName = 'set'.ucfirst($name);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function getFoo() { return $this->_foo; }
public function setFoo($value) { $this->_foo = $value; }
public function getBar() { return $this->_bar; }
public function setBar($value) { $this->_bar = $value; }
public function getBaz() { return $this->_baz; }
public function setBaz($value) { $this->_baz = $value; }
}
And then
$obj = new SomeObject();
$obj->foo = 'Hello world'; // legacy code support
$obj->setFoo('Hello world'); // same thing, but preferred
And you satisfy both the OO paradigm and having direct access to attributes of an instance. You could also have __call() check for prefix 'get' or 'set' and call __get() and __set() accordingly, but I would not go that far, though this would truly enable general purpose classes to access it's private members via ->member and ->getMember()/->setMember()
What are getters and setters in PHP5?
Can someone give me a good example with an explanation?
This is concept for data hiding (or encapsulation) in OOP. For example if you want to have a certain property in your class let's say 'Amount' and give the client of you class the option to change or extract its value You should make your variable 'Amount' private (not visible for those who use your class) and generate two methods a getter and a setter that manipulates your value (that are public).
The reason is to be able to validate data or manipulate it before setting or getting your value. Here is a brief example:
class test {
private $count; //those who use your class are not able to see this property, only the methods above
public function setCount( $value )
{
//make some validation or manipulation on data here, if needed
$this->count = $value;
}
public function getCount()
{
return $this->count;
}
}
Attributes of classes can be private. That means only the object can read and write its own private attributes. Therefore you need methods to do that. The methods that read and return an attribute value are called getters and those that write attributes are called setters. With these methods the classes can control what’s going out and what’s coming in. This concept is called encapsulation.
Getters and Setters are quite new concept in PHP 5 in the form of two magical functions __get() and set(). These two functions set or get property value of an object dramatically as explained in the following example.
class Datatype{
private $thing;
public function _set($k,$v){
$this->$k = $v;
}
public function __get($k){
return $this->$k;
}
}
The PHP manual is really not very verbose on the issue, but there is a very detailed example that should explain a lot. Magic methods: Property overloading
I'm going to try something with the format of this question and I'm very open to suggestions about a better way to handle it.
I didn't want to just dump a bunch of code in the question so I've posted the code for the class on refactormycode.
base class for easy class property handling
My thought was that people can either post code snippets here or make changes on refactormycode and post links back to their refactorings. I'll make upvotes and accept an answer (assuming there's a clear "winner") based on that.
At any rate, on to the class itself:
I see a lot of debate about getter/setter class methods and is it better to just access simple property variables directly or should every class have explicit get/set methods defined, blah blah blah. I like the idea of having explicit methods in case you have to add more logic later. Then you don't have to modify any code that uses the class. However I hate having a million functions that look like this:
public function getFirstName()
{
return $this->firstName;
}
public function setFirstName($firstName)
{
return $this->firstName;
}
Now I'm sure I'm not the first person to do this (I'm hoping that there's a better way of doing it that someone can suggest to me).
Basically, the PropertyHandler class has a __call magic method. Any methods that come through __call that start with "get" or "set" are then routed to functions that set or retrieve values into an associative array. The key into the array is the name of the calling method after getting or setting. So, if the method coming into __call is "getFirstName", the array key is "FirstName".
I liked using __call because it will automatically take care of the case where the subclass already has a "getFirstName" method defined. My impression (and I may be wrong) is that the __get & __set magic methods don't do that.
So here's an example of how it would work:
class PropTest extends PropertyHandler
{
public function __construct()
{
parent::__construct();
}
}
$props = new PropTest();
$props->setFirstName("Mark");
echo $props->getFirstName();
Notice that PropTest doesn't actually have "setFirstName" or "getFirstName" methods and neither does PropertyHandler. All that's doing is manipulating array values.
The other case would be where your subclass is already extending something else. Since you can't have true multiple inheritances in PHP, you can make your subclass have a PropertyHandler instance as a private variable. You have to add one more function but then things behave in exactly the same way.
class PropTest2
{
private $props;
public function __construct()
{
$this->props = new PropertyHandler();
}
public function __call($method, $arguments)
{
return $this->props->__call($method, $arguments);
}
}
$props2 = new PropTest2();
$props2->setFirstName('Mark');
echo $props2->getFirstName();
Notice how the subclass has a __call method that just passes everything along to the PropertyHandler __call method.
Another good argument against handling getters and setters this way is that it makes it really hard to document.
In fact, it's basically impossible to use any sort of document generation tool since the explicit methods to be don't documented don't exist.
I've pretty much abandoned this approach for now. It was an interesting learning exercise but I think it sacrifices too much clarity.
The way I do it is the following:
class test {
protected $x='';
protected $y='';
function set_y ($y) {
print "specific function set_y\n";
$this->y = $y;
}
function __call($function , $args) {
print "generic function $function\n";
list ($name , $var ) = split ('_' , $function );
if ($name == 'get' && isset($this->$var)) {
return $this->$var;
}
if ($name == 'set' && isset($this->$var)) {
$this->$var= $args[0];
return;
}
trigger_error ("Fatal error: Call to undefined method test::$function()");
}
}
$p = new test();
$p->set_x(20);
$p->set_y(30);
print $p->get_x();
print $p->get_y();
$p->set_z(40);
Which will output (line breaks added for clarity)
generic function set_x
specific function set_y
generic function get_x
20
generic function get_y
30
generic function set_z
Notice: Fatal error: Call to undefined method set_z() in [...] on line 16
#Brian
My problem with this is that adding "more logic later" requires that you add blanket logic that applies to all properties accessed with the getter/setter or that you use if or switch statements to evaluate which property you're accessing so that you can apply specific logic.
That's not quite true. Take my first example:
class PropTest extends PropertyHandler
{
public function __construct()
{
parent::__construct();
}
}
$props = new PropTest();
$props->setFirstName("Mark");
echo $props->getFirstName();
Let's say that I need to add some logic for validating FirstNames. All I have to do is add a setFirstName method to my subclass and that method is automatically used instead.
class PropTest extends PropertyHandler
{
public function __construct()
{
parent::__construct();
}
public function setFirstName($name)
{
if($name == 'Mark')
{
echo "I love you, Mark!";
}
}
}
I'm just not satisfied with the limitations that PHP has when it comes to implicit accessor methods.
I agree completely. I like the Python way of handling this (my implementation is just a clumsy rip-off of it).
Yes that's right the variables have to be manually declared but i find that better since I fear a typo in the setter
$props2->setFristName('Mark');
will auto-generate a new property (FristName instead of FirstName) which will make debugging harder.
I like having methods instead of just using public fields, as well, but my problem with PHP's default implementation (using __get() and __set()) or your custom implementation is that you aren't establishing getters and setters on a per-property basis. My problem with this is that adding "more logic later" requires that you add blanket logic that applies to all properties accessed with the getter/setter or that you use if or switch statements to evaluate which property you're accessing so that you can apply specific logic.
I like your solution, and I applaud you for it--I'm just not satisfied with the limitations that PHP has when it comes to implicit accessor methods.
#Mark
But even your method requires a fresh declaration of the method, and it somewhat takes away the advantage of putting it in a method so that you can add more logic, because to add more logic requires the old-fashioned declaration of the method, anyway. In its default state (which is where it is impressive in what it detects/does), your technique is offering no advantage (in PHP) over public fields. You're restricting access to the field but giving carte blanche through accessor methods that don't have any restrictions of their own. I'm not aware that unchecked explicit accessors offer any advantage over public fields in any language, but people can and should feel free to correct me if I'm wrong.
I've always handled this issue in a similar with a __call which ends up pretty much as boiler plate code in many of my classes. However, it's compact, and uses the reflection classes to only add getters / setters for properties you have already set (won't add new ones). Simply adding the getter / setter explicitly will add more complex functionality. It expects to be
Code looks like this:
/**
* Handles default set and get calls
*/
public function __call($method, $params) {
//did you call get or set
if ( preg_match( "|^[gs]et([A-Z][\w]+)|", $method, $matches ) ) {
//which var?
$var = strtolower($matches[1]);
$r = new ReflectionClass($this);
$properties = $r->getdefaultProperties();
//if it exists
if ( array_key_exists($var,$properties) ) {
//set
if ( 's' == $method[0] ) {
$this->$var = $params[0];
}
//get
elseif ( 'g' == $method[0] ) {
return $this->$var;
}
}
}
}
Adding this to a class where you have declared default properties like:
class MyClass {
public $myvar = null;
}
$test = new MyClass;
$test->setMyvar = "arapaho";
echo $test->getMyvar; //echos arapaho
The reflection class may add something of use to what you were proposing. Neat solution #Mark.
Just recently, I also thought about handling getters and setters the way you suggested (the second approach was my favorite, i.e. the private $props array), but I discarded it for it wouldn't have worked out in my app.
I am working on a rather large SoapServer-based application and the soap interface of PHP 5 injects the values that are transmitted via soap directly into the associated class, without bothering about existing or non-existing properties in the class.
I can't help putting in my 2 cents...
I have taken to using __get and __set in this manor http://gist.github.com/351387 (similar to the way that doctrine does it), then only ever accessing the properties via the $obj->var in an outside of the class. That way you can override functionality as needed instead of making a huge __get or __set function, or overriding __get and __set in the child classes.