Is it worth making get and set methods in OOP? - php

I have seen some some projects in which classes are having get and set methods to manipulate insert data. Let me have an example here :
class Student extends dbClass
{
private $TableID;
private $FullName;
private $Gender;
private $Address;
function setTableID($Value)
{
$this->TableID = $Value;
}
function getTableID()
{
return $this->TableID;
}
function setFullName($Value)
{
$this->FullName = $Value;
}
function getFullName()
{
return $this->FullName;
}
function setGender($Value)
{
$this->Gender = $Value;
}
function getGender()
{
return $this->Gender;
}
function setAddress($Value)
{
$this->Address = $Value;
}
function getAddress()
{
return $this->Address;
}
function UpdateStudent()
{
$sql = "UPDATE INTO usertable SET
FullName = '".$this->getFullName()."',
Gender = '".$this->getGender()."',
Address = '".$this->getAddress()."'
where TableID='".$this->getTableID()."'";
$this->query($sql);
}
}
Above is the example class that i have seen. And below is the process how they are using it :
$student = new Student;
$student->setTableID = 1;
$student->setFullName('My Name');
$student->setGender('Male');
$student->setAddress('this is my address');
$studen->UpdateStudent();
Is it worth doing this way? I personally think its useless to set field and then get and update records in it. It really takes a lot of time to make it for every module. What is the best way to handle such thing?
Is there any security concerned doing it in this way?

Is it worth doing this way?
It depends.
Abstracting a field from the user by exposing a "smart" property (i.e. getter and/or setter) has two disadvantages:
You need to write more code; if the property doesn't really do anything smart, this is code that does nothing useful.
The user of the property is slightly inconvenienced because they have to type a little more as well.
And it has one advantage:
In the future you can add logic to the properties even if there was none before without breaking your users' code.
If this advantage is meaningful (e.g. you are writing a reusable software library) then it makes great sense to write properties instead of bare fields. If not, you are doing work for no benefit.
What is the best way to handle such thing?
You can override the magic __get and __set functions (perhaps in a base class so you can inherit the override as well) to automatically forward property accesses to your getters and setters. Simplified code:
public function __get($name) {
$getter = 'get'.$name;
if (method_exists($this, $getter)) {
return $this->$getter();
}
$message = sprintf('Class "%1$s" does not have a property named "%2$s" or a method named "%3$s".', get_class($this), $name, $getter);
throw new \OutOfRangeException($message);
}
public function __set($name, $value) {
$setter = 'set'.$name;
if (method_exists($this, $setter)) {
return $this->$setter($value);
}
$getter = 'get'.$name;
if (method_exists($this, $getter)) {
$message = sprintf('Implicit property "%2$s" of class "%1$s" cannot be set because it is read-only.', get_class($this), $name);
}
else {
$message = sprintf('Class "%1$s" does not have a property named "%2$s" or a method named "%3$s".', get_class($this), $name, $setter);
}
throw new \OutOfRangeException($message);
}
Caveat emptor: Since __get and __set are overridden, __isset and __unset should be overridden as well!
Is there any security concerned doing it in this way?
No, none at all (assuming you don't insert bugs accidentally).

In languages that do not have properties (public member "variables" which actually lead to function calls) using getter/setters instead of public variables is usually recommended. Otherwise you cannot add logic (e.g. when setting a variable) later if people are already using your plain field.
Since PHP is such a language (unfortunately) the answer is yes, use them.

Making setters and getters helps enforce OOP encapsulation. Im not sure for PHP, but for many other languages (Java, C++), a good IDE (eclipse/netbeans) will auto-generate these setters and getters for you.
It may not be immediately obvious for simple types, but if any sort of more complex processing has to be performed, then it becomes more obvious.

An example as to why to sometimes use getters and setters:
I have code that sets a value in 200 different files:
$cat->name = 'Fery' // in file one
$favoriteCat->name = 'Tery' // in another file
$fatCat->name = 'jery' // in another file
// 200 more calls in alot of places
Imagine the customer suddenly has a new requirement: "all cat names must be prepended by 'Sweet'
Now we must find all declarations of cats and replace their assignments:
$cat->name = 'Sweet '.'Fery'
// times 200
On the other hand, If we used a setter method all we need to do is add the code to add 'Sweet ' in one place:
public function setCatname($catname)
{
$this->catName = 'Sweet ' . $catname;
}

Related

When to use magic methods in PHP? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Are Magic Methods Best practice in PHP?
These are simple examples, but imagine you have more properties than two in your class.
What would be best practice?
a) Using __get and __set
class MyClass {
private $firstField;
private $secondField;
public function __get($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
public function __set($property, $value) {
if (property_exists($this, $property)) {
$this->$property = $value;
}
}
}
$myClass = new MyClass();
$myClass->firstField = "This is a foo line";
$myClass->secondField = "This is a bar line";
echo $myClass->firstField;
echo $myClass->secondField;
/* Output:
This is a foo line
This is a bar line
*/
b) Using traditional setters and getters
class MyClass {
private $firstField;
private $secondField;
public function getFirstField() {
return $this->firstField;
}
public function setFirstField($firstField) {
$this->firstField = $firstField;
}
public function getSecondField() {
return $this->secondField;
}
public function setSecondField($secondField) {
$this->secondField = $secondField;
}
}
$myClass = new MyClass();
$myClass->setFirstField("This is a foo line");
$myClass->setSecondField("This is a bar line");
echo $myClass->getFirstField();
echo $myClass->getSecondField();
/* Output:
This is a foo line
This is a bar line
*/
In this article: http://blog.webspecies.co.uk/2011-05-23/the-new-era-of-php-frameworks.html
The author claims that using magic methods is not a good idea:
First of all, back then it was very popular to use PHP’s magic functions (__get, __call etc.). There is nothing wrong with them from a first look, but they are actually really dangerous. They make APIs unclear, auto-completion impossible and most importantly they are slow. The use case for them was to hack PHP to do things which it didn’t want to. And it worked. But made bad things happen.
But I would like to hear more opinions about this.
I have been exactly in your case in the past. And I went for magic methods.
This was a mistake, the last part of your question says it all :
this is slower (than getters/setters)
there is no auto-completion (and this is a major problem actually), and type management by the IDE for refactoring and code-browsing (under Zend Studio/PhpStorm this can be handled with the #property phpdoc annotation but that requires to maintain them: quite a pain)
the documentation (phpdoc) doesn't match how your code is supposed to be used, and looking at your class doesn't bring much answers as well. This is confusing.
added after edit: having getters for properties is more consistent with "real" methods where getXXX() is not only returning a private property but doing real logic. You have the same naming. For example you have $user->getName() (returns private property) and $user->getToken($key) (computed). The day your getter gets more than a getter and needs to do some logic, everything is still consistent.
Finally, and this is the biggest problem IMO : this is magic. And magic is very very bad, because you have to know how the magic works to use it properly. That's a problem I've met in a team: everybody has to understand the magic, not just you.
Getters and setters are a pain to write (I hate them) but they are worth it.
You only need to use magic if the object is indeed "magical". If you have a classic object with fixed properties then use setters and getters, they work fine.
If your object have dynamic properties for example it is part of a database abstraction layer, and its parameters are set at runtime then you indeed need the magic methods for convenience.
I use __get (and public properties) as much as possible, because they make code much more readable. Compare:
this code unequivocally says what i'm doing:
echo $user->name;
this code makes me feel stupid, which i don't enjoy:
function getName() { return $this->_name; }
....
echo $user->getName();
The difference between the two is particularly obvious when you access multiple properties at once.
echo "
Dear $user->firstName $user->lastName!
Your purchase:
$product->name $product->count x $product->price
"
and
echo "
Dear " . $user->getFirstName() . " " . $user->getLastName() . "
Your purchase:
" . $product->getName() . " " . $product->getCount() . " x " . $product->getPrice() . " ";
Whether $a->b should really do something or just return a value is the responsibility of the callee. For the caller, $user->name and $user->accountBalance should look the same, although the latter may involve complicated calculations. In my data classes i use the following small method:
function __get($p) {
$m = "get_$p";
if(method_exists($this, $m)) return $this->$m();
user_error("undefined property $p");
}
when someone calls $obj->xxx and the class has get_xxx defined, this method will be implicitly called. So you can define a getter if you need it, while keeping your interface uniform and transparent. As an additional bonus this provides an elegant way to memorize calculations:
function get_accountBalance() {
$result = <...complex stuff...>
// since we cache the result in a public property, the getter will be called only once
$this->accountBalance = $result;
}
....
echo $user->accountBalance; // calculate the value
....
echo $user->accountBalance; // use the cached value
Bottom line: php is a dynamic scripting language, use it that way, don't pretend you're doing Java or C#.
I vote for a third solution. I use this in my projects and Symfony uses something like this too:
public function __call($val, $x) {
if(substr($val, 0, 3) == 'get') {
$varname = strtolower(substr($val, 3));
}
else {
throw new Exception('Bad method.', 500);
}
if(property_exists('Yourclass', $varname)) {
return $this->$varname;
} else {
throw new Exception('Property does not exist: '.$varname, 500);
}
}
This way you have automated getters (you can write setters too), and you only have to write new methods if there is a special case for a member variable.
I do a mix of edem's answer and your second code. This way, I have the benefits of common getter/setters (code completion in your IDE), ease of coding if I want, exceptions due to inexistent properties (great for discovering typos: $foo->naem instead of $foo->name), read only properties and compound properties.
class Foo
{
private $_bar;
private $_baz;
public function getBar()
{
return $this->_bar;
}
public function setBar($value)
{
$this->_bar = $value;
}
public function getBaz()
{
return $this->_baz;
}
public function getBarBaz()
{
return $this->_bar . ' ' . $this->_baz;
}
public function __get($var)
{
$func = 'get'.$var;
if (method_exists($this, $func))
{
return $this->$func();
} else {
throw new InexistentPropertyException("Inexistent property: $var");
}
}
public function __set($var, $value)
{
$func = 'set'.$var;
if (method_exists($this, $func))
{
$this->$func($value);
} else {
if (method_exists($this, 'get'.$var))
{
throw new ReadOnlyException("property $var is read-only");
} else {
throw new InexistentPropertyException("Inexistent property: $var");
}
}
}
}
Second code example is much more proper way to do this because you are taking full control of data which are given to class.
There are cases in which the __set and __get are useful but not in this case.
You should use stdClass if you want magic members, if you write a class - define what it contains.
The best practice would be to use traditionnal getters and setters, because of introspection or reflection. There is a way in PHP (exactly like in Java) to obtain the name of a method or of all methods. Such a thing would return "__get" in the first case and "getFirstField", "getSecondField" in the second (plus setters).
More on that: http://php.net/manual/en/book.reflection.php
I am now returning to setters and getters but I am also putting the getters and setters in the magic methos __get and __set. This way I have a default behavior when I do this
$class->var;
This will just call the getter I have set in the __get. Normally I will just use the getter directly but there are still some instances where this is just simpler.

Properties in PHP

Since PHP has no notion of properties like C# what is the best way to expose certain attributes of a class? Is it recommended to have separate get and set functions or should the member variable be made public?
I am designing a class whose objects will be contained in another class. There should be a way to set/get properties of the object.
On the whole I would recommend exposing public variables on your PHP class, except where you need to perform a more complex action, in which case you would use getter and setter functions.
So where you would use this in C#
public string MyProp { get; set; }
I would recommend this in PHP
public $MyProp;
Using public attribute or private with getter/setter will both do the trick.
I will proceed like this :
If the attribute is critical, use a getter and setter like this :
class myClass
{
private $myAttr;
public function getmyAttr()
{
return $this->myAttr;
}
public function setmyAttr($attr)
{
//Do some verification on $attr
$this->myAttr = $attr;
}
}
If the attribute is less critical , you could simply set is visibility to public.
Because of the lack of strong type in php i will always prefer the private attribute with getter and setter. it let you ensure that the attribute is always what it should be (not "1" instead of 1 for example).
It depends, it is not very rare to make attributes public which are not very security sensitive. But if you do want to keep them private you could create something like this:
class withAttributes{
private $property;
public function getPrivateProperty{
return $this->property;
}
}
In the other class:
$object = new withAttributes();
$attribute = $object->getPrivateProperty();
Hope this helps
There's no idiomatic way built in the language, however you could try using the magic __get and __set methods to emulate something simillar.
Consider this pretty dumb example:
Class Foo {
private $bar;
private $baz;
public function __get($name) {
if (property_exists($this, $name)) {
if ($name == 'bar') {
return strtoupper($this->{$name});
} else {
return $this->{$name};
}
}
return null; // this is what php would do, consider throwning an exception instead
}
public function __set($name, $value) {
if (property_exists($this, $name)) {
if ($name == 'bar') {
$this->{$name} = strtolower($value);
} else {
$this->{$name} = $value;
}
}
// we just ignore this call, consider throwing exceptions, or you could make the class open to property addition in runtime too
}
}
$f = new Foo;
$f->bar = 'tickle me elmo';
print $f->bar; // prints uppercase
This way later on, if you decide to implement some read/write logic, you can hook it in the magic methods. From performance standpoint, these magic methods are slower than ordinary method calls, also arguably more surprising for the users of these classes than explicit getter/setter methods.
If you want to create something more like the built-in StdObject or basic array consider implementing the ArrayAccess interface for the [] syntax.

PHP OOP a lot of setters, getters

I need to create approx. 5-7 classes, every class will contain a lot of members (let us say each class will contain 20 members). I could create them using public access, like:
class A {
public $myPropertyOne = '';
public $myPropertyTwo = '';
...
}
My preferred way of course to make these members private and create get/set methods for each property. I.e.
class A {
private $myPropertyOne = '';
private $myPropertyTwo = '';
public function getMyPropertyOne() {
return $this->myPropertyOne;
}
public function setMyPropertyOne($myPropertyOne) {
$this->myPropertyOne = $myPropertyOne;
}
public function getMyPropertyTwo() {
return $this->myPropertyTwo;
}
public function setMyPropertyTwo($myPropertyTwo) {
$this->myPropertyTwo = $myPropertyTwo;
}
}
But considering a class will have 20 properties, I will have in addition to this add 40 methods. And my concern here is how will this slow down the script and much more memory this will require (remember I am going to have several classes like this).
Another solution could be to use magic functions __set, __get but I don't want to, because the code completion in development IDE will not suggest properties which is crucial for me.
If this would be a compiled language (like C++) I would not have a question and would use the solution with getters, setters but since the PHP is interpreted language I am interested in my scripts to use less RAM and be as fast as possible.
Thanks in advance, any thoughts regarding this question would be much appreciated!
My Opinion
Thank you all for your answers, I just wanted to share my opinion in case someone will look for an answer to this question.
I cannot fully agree with those who say that you should not care about performance as this is task of optimizers, I think this is important factor (well atleast as for me), when we're dealing with interpreted language such as PHP we will always have to think about memory and speed (this all reminds me the time when I was developing system apps for DOS, heh :) and you always have been limited with poor CPU and kilobytes of total RAM so you got happy if you could save an additional byte), in PHP development you have the same picture as regardless of how many server you add, users' count will be always higher so that you always have to decide if you want to follow classic/safe/proper method or to avoid this and get some gain in speed or memory.
So.... my opinion is that the best way here is to use public access for all member and avoid getters/setters for all properties and use private access with get/set methods for properties which requires data validation or initialization before a value will be set.
For example:
class B {
public $myPropertyOne = '';
public $myPropertyTwo = '';
private $myPropertyThree = array();
public function getMyPropertyThree() {
return $this->myPropertyThree;
}
public function setMyPropertyThree($val) {
if(!is_array($val)) {
return;
}
$this->myPropertyThree = $val;
}
}
Thank you for spending time on my question!
Simple test shows instances take the same amount of memory, unaffected by the number of methods in a class:
Class with no methods:
class Test1 { }
Class with 20 methods:
class Test2 {
function test1() { return true; }
function test2() { return true; }
function test3() { return true; }
function test4() { return true; }
function test5() { return true; }
function test6() { return true; }
function test7() { return true; }
function test8() { return true; }
function test9() { return true; }
function test10() { return true; }
function test11() { return true; }
function test12() { return true; }
function test13() { return true; }
function test14() { return true; }
function test15() { return true; }
function test16() { return true; }
function test17() { return true; }
function test18() { return true; }
function test19() { return true; }
function test20() { return true; }
}
Test loop, same for both tests:
$test = array();
$base = memory_get_usage();
for ($i = 0; $i < 10000; $i++) {
$test[] = new ClassToBeTested();
}
$used = memory_get_usage() - $base;
print("used: $used\n");
Result for class Test1 (no methods):
used: 3157408
Result for class Test2 (20 methods):
used: 3157408
I've run it in two separate scripts, since running the two tests in a single script apparently exposed some PHP internal allocation, and the second test consumed less memory than the first, no matter which one is first or second.
While you surely take more memory for the actual class definition, apparently this cost is incurred only once per class, not per instance. You don't have to worry about the memory usage.
But considering a class will have 20 properties
Having this many properties is usually an indicator of misplaced information. Check whether you can group some of those into Classes of their own.
Refactoring: Extract Class
I will have in addition to this add 40 methods.
Not at all. Unless these classes are dumb data structs, you dont want any Getters and Setters on them because they break encapsulation. Put methods in the public API with which you tell the objects to do things.
Getter Eradicator
Getters and Setters are evil
Tell Don't Ask
And my concern here is how will this slow down the script and much more memory this will require (remember I am going to have several classes like this).
This is not an issue.
In PHP, are objects methods code duplicated or shared between instances?
Another solution could be to use magic functions __set, __get but I don't want to, because the code completion in development IDE will not suggest properties which is crucial for me.
Modern IDEs can autocomplete on magic methods.
Code Completion for private/protected member variables when using magic __get()
However, if you are already concerned about performance at the microlevel, then you dont want magic methods because those are definitely slower.
__get/__set/__call performance questions with PHP
Apart from that, Magic Methods are not substitutes for getters and setters but error handlers that get triggered when an inaccessible property or method was called.
PHP __get and __set magic methods
Also, magic methods are unobvious and make for hard to read APIs.
To make properties of your class that implemented by magic methods to be highlited by IDE just use #property PHPDoc #property tag, like this:
<?php
/**
* #property int id Blog post ID
* #property string title Blog post Title
*/
class Post {
}
More on PHPDoc' #property here: http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.property.pkg.html
As for other issues questioned - Karoly Horvath' comment fully covers those PHP OOP a lot of setters, getters.
As stated before, it's quite strange that your class should have so many properties. However, it can sometimes (fairly rarely though) happen. But normally, those properties should have a sort of link together : so you could store them in a hashmap and not a property. Then you just neeed one method as a getter.
Now, it will surely be more resources consuming, true. As for autocompletion, use constants : you'll just type something like :
$my_class->getFromHashMap($parameter)
And when typing your parameter, you'll use the constant as it's stored in the class : here, the autocomplete should be able to help you.
Take in mind that my code considered that properties' name have been declared in lowercase...
<?php
class Modelo {
var $attr1 = "default";
var $attr2 = 0;
public function __call($name, $arguments)
{
if (method_exists($this, ($method = $name))){
return $this->$method();
}
else{
$attribute = split("get",$name);
if(count($attribute)==2){
$attribute = strtolower($attribute[1]);
if(isset($this->$attribute)){
return ($this->$attribute);
}
}else{
$attribute = split("set",$name);
if(count($attribute)==2){
$attribute = strtolower($attribute[1]);
if(isset($this->$attribute) && count($arguments)==1){
$this->$attribute=$arguments[0];
}else{
die("$name number of arguments error: ".join($arguments,","));
}
}else{
die("$name doesn't exist!");
}
}
}
}
}
echo "<pre>";
$m = new Modelo();
print_r(
array(
"objetct"=>$m
,"getAttr1"=>$m->getAttr1()
,"getAttr2"=>$m->getAttr2()
)
);
echo "setAttr1\n";
$m->setAttr1("by set method");
print_r(
array(
"objetct"=>$m
,"getAttr1"=>$m->getAttr1()
,"getAttr2"=>$m->getAttr2()
)
);
?>
You could try this:
trait get_set
{
public function set($what, $value)
{
$this->{$what} = $value;
}
public function get($what)
{
return $this->{$what};
}
}
It will work on public and protected variables. You can add if(!isset($this->{$what})error()

Best practice: PHP Magic Methods __set and __get [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Are Magic Methods Best practice in PHP?
These are simple examples, but imagine you have more properties than two in your class.
What would be best practice?
a) Using __get and __set
class MyClass {
private $firstField;
private $secondField;
public function __get($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
public function __set($property, $value) {
if (property_exists($this, $property)) {
$this->$property = $value;
}
}
}
$myClass = new MyClass();
$myClass->firstField = "This is a foo line";
$myClass->secondField = "This is a bar line";
echo $myClass->firstField;
echo $myClass->secondField;
/* Output:
This is a foo line
This is a bar line
*/
b) Using traditional setters and getters
class MyClass {
private $firstField;
private $secondField;
public function getFirstField() {
return $this->firstField;
}
public function setFirstField($firstField) {
$this->firstField = $firstField;
}
public function getSecondField() {
return $this->secondField;
}
public function setSecondField($secondField) {
$this->secondField = $secondField;
}
}
$myClass = new MyClass();
$myClass->setFirstField("This is a foo line");
$myClass->setSecondField("This is a bar line");
echo $myClass->getFirstField();
echo $myClass->getSecondField();
/* Output:
This is a foo line
This is a bar line
*/
In this article: http://blog.webspecies.co.uk/2011-05-23/the-new-era-of-php-frameworks.html
The author claims that using magic methods is not a good idea:
First of all, back then it was very popular to use PHP’s magic functions (__get, __call etc.). There is nothing wrong with them from a first look, but they are actually really dangerous. They make APIs unclear, auto-completion impossible and most importantly they are slow. The use case for them was to hack PHP to do things which it didn’t want to. And it worked. But made bad things happen.
But I would like to hear more opinions about this.
I have been exactly in your case in the past. And I went for magic methods.
This was a mistake, the last part of your question says it all :
this is slower (than getters/setters)
there is no auto-completion (and this is a major problem actually), and type management by the IDE for refactoring and code-browsing (under Zend Studio/PhpStorm this can be handled with the #property phpdoc annotation but that requires to maintain them: quite a pain)
the documentation (phpdoc) doesn't match how your code is supposed to be used, and looking at your class doesn't bring much answers as well. This is confusing.
added after edit: having getters for properties is more consistent with "real" methods where getXXX() is not only returning a private property but doing real logic. You have the same naming. For example you have $user->getName() (returns private property) and $user->getToken($key) (computed). The day your getter gets more than a getter and needs to do some logic, everything is still consistent.
Finally, and this is the biggest problem IMO : this is magic. And magic is very very bad, because you have to know how the magic works to use it properly. That's a problem I've met in a team: everybody has to understand the magic, not just you.
Getters and setters are a pain to write (I hate them) but they are worth it.
You only need to use magic if the object is indeed "magical". If you have a classic object with fixed properties then use setters and getters, they work fine.
If your object have dynamic properties for example it is part of a database abstraction layer, and its parameters are set at runtime then you indeed need the magic methods for convenience.
I use __get (and public properties) as much as possible, because they make code much more readable. Compare:
this code unequivocally says what i'm doing:
echo $user->name;
this code makes me feel stupid, which i don't enjoy:
function getName() { return $this->_name; }
....
echo $user->getName();
The difference between the two is particularly obvious when you access multiple properties at once.
echo "
Dear $user->firstName $user->lastName!
Your purchase:
$product->name $product->count x $product->price
"
and
echo "
Dear " . $user->getFirstName() . " " . $user->getLastName() . "
Your purchase:
" . $product->getName() . " " . $product->getCount() . " x " . $product->getPrice() . " ";
Whether $a->b should really do something or just return a value is the responsibility of the callee. For the caller, $user->name and $user->accountBalance should look the same, although the latter may involve complicated calculations. In my data classes i use the following small method:
function __get($p) {
$m = "get_$p";
if(method_exists($this, $m)) return $this->$m();
user_error("undefined property $p");
}
when someone calls $obj->xxx and the class has get_xxx defined, this method will be implicitly called. So you can define a getter if you need it, while keeping your interface uniform and transparent. As an additional bonus this provides an elegant way to memorize calculations:
function get_accountBalance() {
$result = <...complex stuff...>
// since we cache the result in a public property, the getter will be called only once
$this->accountBalance = $result;
}
....
echo $user->accountBalance; // calculate the value
....
echo $user->accountBalance; // use the cached value
Bottom line: php is a dynamic scripting language, use it that way, don't pretend you're doing Java or C#.
I vote for a third solution. I use this in my projects and Symfony uses something like this too:
public function __call($val, $x) {
if(substr($val, 0, 3) == 'get') {
$varname = strtolower(substr($val, 3));
}
else {
throw new Exception('Bad method.', 500);
}
if(property_exists('Yourclass', $varname)) {
return $this->$varname;
} else {
throw new Exception('Property does not exist: '.$varname, 500);
}
}
This way you have automated getters (you can write setters too), and you only have to write new methods if there is a special case for a member variable.
I do a mix of edem's answer and your second code. This way, I have the benefits of common getter/setters (code completion in your IDE), ease of coding if I want, exceptions due to inexistent properties (great for discovering typos: $foo->naem instead of $foo->name), read only properties and compound properties.
class Foo
{
private $_bar;
private $_baz;
public function getBar()
{
return $this->_bar;
}
public function setBar($value)
{
$this->_bar = $value;
}
public function getBaz()
{
return $this->_baz;
}
public function getBarBaz()
{
return $this->_bar . ' ' . $this->_baz;
}
public function __get($var)
{
$func = 'get'.$var;
if (method_exists($this, $func))
{
return $this->$func();
} else {
throw new InexistentPropertyException("Inexistent property: $var");
}
}
public function __set($var, $value)
{
$func = 'set'.$var;
if (method_exists($this, $func))
{
$this->$func($value);
} else {
if (method_exists($this, 'get'.$var))
{
throw new ReadOnlyException("property $var is read-only");
} else {
throw new InexistentPropertyException("Inexistent property: $var");
}
}
}
}
Second code example is much more proper way to do this because you are taking full control of data which are given to class.
There are cases in which the __set and __get are useful but not in this case.
You should use stdClass if you want magic members, if you write a class - define what it contains.
The best practice would be to use traditionnal getters and setters, because of introspection or reflection. There is a way in PHP (exactly like in Java) to obtain the name of a method or of all methods. Such a thing would return "__get" in the first case and "getFirstField", "getSecondField" in the second (plus setters).
More on that: http://php.net/manual/en/book.reflection.php
I am now returning to setters and getters but I am also putting the getters and setters in the magic methos __get and __set. This way I have a default behavior when I do this
$class->var;
This will just call the getter I have set in the __get. Normally I will just use the getter directly but there are still some instances where this is just simpler.

What are the advantages of using getters and setters instead of functions or simply public fields in PHP? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
This post was edited and submitted for review 6 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I'm not a PHP developer, so I'm wondering what the advantages and disadvantages are in PHP to using explicit getter/setters, in a pure OOP style, with private fields (the way I like):
class MyClass {
private $firstField;
private $secondField;
public function getFirstField() {
return $this->firstField;
}
public function setFirstField($x) {
$this->firstField = $x;
}
public function getSecondField() {
return $this->secondField;
}
public function setSecondField($x) {
$this->secondField = $x;
}
}
or just public fields:
class MyClass {
public $firstField;
public $secondField;
}
You can use php magic methods __get and __set.
<?php
class MyClass {
private $firstField;
private $secondField;
public function __get($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
public function __set($property, $value) {
if (property_exists($this, $property)) {
$this->$property = $value;
}
return $this;
}
}
?>
Why use getters and setters?
Scalability: It's easier refactor a getter than search all the var assignments in a project code.
Debugging: You can put breakpoints at setters and getters.
Cleaner: Magic functions are not good solution for writting less, your IDE will not suggest the code. Better use templates for fast-writting getters.
Google already published a guide on optimization of PHP and the conclusion was:
No getter and setter Optimizing PHP
And no, you must not use magic methods. For PHP, Magic Methods are evil. Why?
They are hard to debug.
There is a negative performance impact.
They require writing more code.
PHP is not Java, C++, or C#. PHP is different and plays with different rules.
Encapsulation is important in any OO language, popularity has nothing to do with it. In dynamically typed languages, like PHP, it is especially useful because there is little ways to ensure a property is of a specific type without using setters.
In PHP, this works:
class Foo {
public $bar; // should be an integer
}
$foo = new Foo;
$foo->bar = "string";
In Java, it doesn't:
class Foo {
public int bar;
}
Foo myFoo = new Foo();
myFoo.bar = "string"; // error
Using magic methods (__get and __set) also works, but only when accessing a property that has lower visibility than the current scope can access. It can easily give you headaches when trying to debug, if it is not used properly.
If you preffer to use the __call function, you can use this method. It works with
GET => $this->property()
SET => $this->property($value)
GET => $this->getProperty()
SET => $this->setProperty($value)
kalsdas
public function __call($name, $arguments) {
//Getting and setting with $this->property($optional);
if (property_exists(get_class($this), $name)) {
//Always set the value if a parameter is passed
if (count($arguments) == 1) {
/* set */
$this->$name = $arguments[0];
} else if (count($arguments) > 1) {
throw new \Exception("Setter for $name only accepts one parameter.");
}
//Always return the value (Even on the set)
return $this->$name;
}
//If it doesn't chech if its a normal old type setter ot getter
//Getting and setting with $this->getProperty($optional);
//Getting and setting with $this->setProperty($optional);
$prefix = substr($name, 0, 3);
$property = strtolower($name[3]) . substr($name, 4);
switch ($prefix) {
case 'get':
return $this->$property;
break;
case 'set':
//Always set the value if a parameter is passed
if (count($arguments) != 1) {
throw new \Exception("Setter for $name requires exactly one parameter.");
}
$this->$property = $arguments[0];
//Always return the value (Even on the set)
return $this->$name;
default:
throw new \Exception("Property $name doesn't exist.");
break;
}
}
In addition to the already great and respected answers in here, I would like to expand on PHP having no setters/getters.
PHP does not have getter and setter syntax. It provides subclassed or magic methods to allow "hooking" and overriding the property lookup process, as pointed out by Dave.
Magic allows us lazy programmers to do more with less code at a time at which we are actively engaged in a project and know it intimately, but usually at the expense of readability.
Performance Every unnecessary function, that results from forcing a getter/setter-like code-architecture in PHP, involves its own memory stack-frame upon invocation and is wasting CPU cycles.
Readability: The codebase incurs bloating code-lines, which impacts code-navigation as more LOC mean more scrolling,.
Preference: Personally, as my rule of thumb, I take the failure of static code analysis
as a sign to avoid going down the magical road as long as obvious long-term benefits elude me at that time.
Fallacies:
A common argument is readability. For instance that $someobject->width is easier to read than $someobject->width(). However unlike a planet's circumference or width, which can be assumed to be static, an object's instance such as $someobject, which requires a width function, likely takes a measurement of the object's instance width.
Therefore readability increases mainly because of assertive naming-schemes and not by hiding the function away that outputs a given property-value.
__get / __set uses:
pre-validation and pre-sanitation of property values
strings e.g.
"
some {mathsobj1->generatelatex} multi
line text {mathsobj1->latexoutput}
with lots of variables for {mathsobj1->generatelatex}
some reason
"
In this case generatelatex would adhere to a naming scheme of actionname + methodname
special, obvious cases
$dnastringobj->homeobox($one_rememberable_parameter)->gattaca->findrelated()
$dnastringobj->homeobox($one_rememberable_parameter)->gttccaatttga->findrelated()
Note: PHP chose not to implement getter/setter syntax. I am not claiming that getters/setter are generally bad.
class MyClass {
private $firstField;
private $secondField;
private $thirdField;
public function __get( $name ) {
if( method_exists( $this , $method = ( 'get' . ucfirst( $name ) ) ) )
return $this->$method();
else
throw new Exception( 'Can\'t get property ' . $name );
}
public function __set( $name , $value ) {
if( method_exists( $this , $method = ( 'set' . ucfirst( $name ) ) ) )
return $this->$method( $value );
else
throw new Exception( 'Can\'t set property ' . $name );
}
public function __isset( $name )
{
return method_exists( $this , 'get' . ucfirst( $name ) )
|| method_exists( $this , 'set' . ucfirst( $name ) );
}
public function getFirstField() {
return $this->firstField;
}
protected function setFirstField($x) {
$this->firstField = $x;
}
private function getSecondField() {
return $this->secondField;
}
}
$obj = new MyClass();
echo $obj->firstField; // works
$obj->firstField = 'value'; // works
echo $obj->getFirstField(); // works
$obj->setFirstField( 'value' ); // not works, method is protected
echo $obj->secondField; // works
echo $obj->getSecondField(); // not works, method is private
$obj->secondField = 'value'; // not works, setter not exists
echo $obj->thirdField; // not works, property not exists
isset( $obj->firstField ); // returns true
isset( $obj->secondField ); // returns true
isset( $obj->thirdField ); // returns false
Ready!
I made an experiment using the magic method __call.
Not sure if I should post it (because of all the "DO NOT USE MAGIC METHODS" warnings in the other answers and comments) but i'll leave it here.. just in case someone find it useful.
public function __call($_name, $_arguments){
$action = substr($_name, 0, 4);
$varName = substr($_name, 4);
if (isset($this->{$varName})){
if ($action === "get_") return $this->{$varName};
if ($action === "set_") $this->{$varName} = $_arguments[0];
}
}
Just add that method above in your class, now you can type:
class MyClass{
private foo = "bar";
private bom = "bim";
// ...
// public function __call(){ ... }
// ...
}
$C = new MyClass();
// as getter
$C->get_foo(); // return "bar"
$C->get_bom(); // return "bim"
// as setter
$C->set_foo("abc"); // set "abc" as new value of foo
$C->set_bom("zam"); // set "zam" as new value of bom
This way you can get/set everything in your class if it exist so, if you need it for only a few specific elements, you could use a "whitelist" as filter.
Example:
private $callWhiteList = array(
"foo" => "foo",
"fee" => "fee",
// ...
);
public function __call($_name, $_arguments){
$action = substr($_name, 0, 4);
$varName = $this->callWhiteList[substr($_name, 4)];
if (!is_null($varName) && isset($this->{$varName})){
if ($action === "get_") return $this->{$varName};
if ($action === "set_") $this->{$varName} = $_arguments[0];
}
}
Now you can only get/set "foo" and "fee".
You can also use that "whitelist" to assign custom names to access to your vars.
For example,
private $callWhiteList = array(
"myfoo" => "foo",
"zim" => "bom",
// ...
);
With that list you can now type:
class MyClass{
private foo = "bar";
private bom = "bim";
// ...
// private $callWhiteList = array( ... )
// public function __call(){ ... }
// ...
}
$C = new MyClass();
// as getter
$C->get_myfoo(); // return "bar"
$C->get_zim(); // return "bim"
// as setter
$C->set_myfoo("abc"); // set "abc" as new value of foo
$C->set_zim("zam"); // set "zam" as new value of bom
.
.
.
That's all.
Doc:
__call() is triggered when invoking inaccessible methods in an object context.
Well, PHP does have magic methods __get, __set, __isset & __unset, which is always a start. Alas proper (get it?) OO properties is more than magic methods. The main problem with PHP's implementation is that magic methods are called for all inaccessible properties. Which means you have to Repeat Yourself (eg. by calling property_exists()) in the magic methods when determining if name is actually a property of your object. And you can't really solve this general problem with a base class unless all your classes inherit from ie. ClassWithProperties, since PHP lacks multiple inheritance.
In contrast, Python new style classes gives you property(), which lets you explicitly define all your properties. C# has special syntax.
http://en.wikipedia.org/wiki/Property_(programming)
After reading the other advices, I'm inclined to say that:
As a GENERIC rule, you will not always define setters for ALL properties, specially "internal" ones (semaphores, internal flags...). Read-only properties will not have setters, obviously, so some properties will only have getters; that's where __get() comes to shrink the code:
define a __get() (magical global getters) for all those properties which are alike,
group them in arrays so:
they'll share common characteristics: monetary values will/may come up properly formatted, dates in an specific layout (ISO, US, Intl.), etc.
the code itself can verify that only existing & allowed properties are being read using this magical method.
whenever you need to create a new similar property, just declare it and add its name to the proper array and it's done. That's way FASTER than defining a new getter, perhaps with some lines of code REPEATED again and again all over the class code.
Yes! we could write a private method to do that, also, but then again, we'll have MANY methods declared (++memory) that end up calling another, always the same, method. Why just not write a SINGLE method to rule them all...? [yep! pun absolutely intended! :)]
Magic setters can also respond ONLY to specific properties, so all date type properties can be screened against invalid values in one method alone. If date type properties were listed in an array, their setters can be defined easily. Just an example, of course. there are way too many situations.
About readability... Well... That's another debate: I don't like to be bound to the uses of an IDE (in fact, I don't use them, they tend to tell me (and force me) how to write... and I have my likes about coding "beauty"). I tend to be consistent about naming, so using ctags and a couple of other aids is sufficient to me... Anyway: once all this magic setters and getters are done, I write the other setters that are too specific or "special" to be generalized in a __set() method. And that covers all I need about getting and setting properties. Of course: there's not always a common ground, or there are such a few properties that is not worth the trouble of coding a magical method, and then there's still the old good traditional setter/getter pair.
Programming languages are just that: human artificial languages. So, each of them has its own intonation or accent, syntax and flavor, so I won't pretend to write a Ruby or Python code using the same "accent" than Java or C#, nor I would write a JavaScript or PHP to resemble Perl or SQL... Use them the way they're meant to be used.
Generally speaking, the first way is more popular overall because those with prior programming knowledge can easily transition to PHP and get work done in an object-oriented fashion. The first way is more universal. My advice would be to stick with what is tried and true across many languages. Then, when and if you use another language, you'll be ready to get something accomplished (instead of spending time reinventing the wheel).
There are many ways to create sourcecode in a netbeans-convention. This is nice. It makes thinks such easyer === FALSE. Just use the traditionel, specially if you are not sure which one of the properties should be encapsuled and which one not. I know, it is a boi.... pla... code, but for debugging-works and many other thinks it is the better, clear way. Dont spend to much time with thousend of arts how to make simple getters and setters. You cannot implement too some design patterns like the demeter-rule and so on, if you use magics. In specific situation you can use magic_calls or for small, fast and clear solutions. Sure you could make solutions for design-patters in this way too, but why to make you live more difficult.
Validating + Formatting/Deriving Values
Setters let you to validate data and getters let you format or derive data. Objects allow you to encapsulate data and its validation and formatting code into a neat package that encourages DRY.
For example, consider the following simple class that contains a birth date.
class BirthDate {
private $birth_date;
public function getBirthDate($format='Y-m-d') {
//format $birth_date ...
//$birth_date = ...
return $birth_date;
}
public function setBirthDate($birth_date) {
//if($birth_date is not valid) throw an exception ...
$this->birth_date = $birth_date;
}
public function getAge() {
//calculate age ...
return $age;
}
public function getDaysUntilBirthday() {
//calculate days until birth days
return $days;
}
}
You'll want to validate that the value being set is
A valid date
Not in the future
And you don't want to do this validation all over your application (or over multiple applications for that matter). Instead, it's easier to make the member variable protected or private (in order to make the setter the only access point) and to validate in the setter because then you'll know that the object contains a valid birth date no matter which part of the application the object came from and if you want to add more validation then you can add it in a single place.
You might want to add multiple formatters that operate on the same member variable i.e. getAge() and getDaysUntilBirthday() and you might want to enforce a configurable format in getBirthDate() depending on locale. Therefore I prefer consistently accessing values via getters as opposed to mixing $date->getAge() with $date->birth_date.
getters and setters are also useful when you extend objects. For example, suppose your application needed to allow 150+ year birth dates in some places but not in others. One way to solve the problem without repeating any code would be to extend the BirthDate object and put the additional validation in the setter.
class LivingBirthDate extends BirthDate {
public function setBirthDate($birth_date) {
//if $birth_date is greater than 150 years throw an exception
//else pass to parent's setter
return parent::setBirthDate($birth_date);
}
}
This post is not specifically about __get and __set but rather __call which is the same idea except for method calling. As a rule, I stay away from any type of magic methods that allow for overloading for reasons outlined in the comments and posts HOWEVER, I recently ran into a 3rd-party API that I use which uses a SERVICE and a SUB-SERVICE, example:
http://3rdparty.api.com?service=APIService.doActionOne&apikey=12341234
The important part of this is that this API has everything the same except the sub-action, in this case doActionOne. The idea is that the developer (myself and others using this class) could call the sub-service by name as opposed to something like:
$myClass->doAction(array('service'=>'doActionOne','args'=>$args));
I could do instead:
$myClass->doActionOne($args);
To hardcode this would just be a lot of duplication (this example very loosely resembles the code):
public function doActionOne($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
public function doActionTwo($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
public function doActionThree($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
protected function executeCoreCall($service)
{
$cURL = new \cURL();
return $cURL->('http://3rdparty.api.com?service='.$service.'&apikey='.$this->api.'&'.http_build_query($this->args))
->getResponse();
}
But with the magic method of __call() I am able to access all services with dynamic methods:
public function __call($name, $arguments)
{
$this->args = $arguments;
$this->response = $this->executeCoreCall("APIService.{$name}");
return $this;
}
The benefit of this dynamic calling for the return of data is that if the vendor adds another sub-service, I do not have to add another method into the class or create an extended class, etc. I am not sure if this is useful to anyone, but I figured I would show an example where __set, __get, __call, etc. may be an option for consideration since the primary function is the return of data.
EDIT:
Coincidentally, I saw this a few days after posting which outlines exactly my scenario. It is not the API I was referring to but the application of the methods is identical:
Am I using api correctly?
Update: Don't use this answer since this is very dumb code that I found while I learn. Just use plain getter and setter, it's much better.
I usually using that variable name as function name, and add optional parameter to that function so when that optional parameter is filled by caller, then set it to the property and return $this object (chaining) and then when that optional parameter not specified by caller, i just return the property to the caller.
My example:
class Model
{
private $propOne;
private $propTwo;
public function propOne($propVal = '')
{
if ($propVal === '') {
return $this->propOne;
} else {
$this->propOne = $propVal;
return $this;
}
}
public function propTwo($propVal = '')
{
if ($propVal === '') {
return $this->propTwo;
} else {
$this->propTwo = $propVal;
return $this;
}
}
}

Categories