Should I use public setter to set private attribute value inside class? - php

Lets assume I have a class Test, which has got a private attribute called $_list, and a public setter.
Public setter is used to set the attribute value from the outside.
class Test {
private $_list;
public function getList() {
return $this->_list;
}
public function setList($list) {
$this->_list = $list;
}
public function initialize() {
$list = array();
/* ... Some code that fills the $list with values etc. ... */
// 1) Set value directly
$this->_list = $list;
// 2) Use public setter
$this->setList($list);
}
}
The question is - do I need to use public setter to set private attribute value inside class?
Which way is are better - #1 or #2? And why?
Which way do you prefer?
I would like to see a complete answer with the explaination of advantages and disadvantages of each way.
Thanks.

As it was written above, both are acceptable, but the correct answer is: Rather use the direct attribute access, but sometimes you better use the setters.
Number 1, (property access) Pros:
Easily readable and slighty faster
Gives you the approach that this is an simple attribute of the object
Number 2, (setter) Pros:
You can do custom action on setting the attribute (e.g. initialize other attributes, caches, or call a method on the parameter object)
You treat the attribute as a sub-element of the class, which may have own logic implemented.
I think that proposing that there is no logic behind using a variable is more important. If it is simple, make it look simple. If it's not, you can still use setters.
You could also ask the same about getters versus property access, the above applies as well.

Related

OOP generic practice (Symfony demo)

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

how to do something before setting a public attribute of the object?

If I get a class looks like this :
class a {
public $aa;
public $ab;
}
$t = new a();
now,
If I type $t->, I would got a tip list under zend Studio, but now I need to do something like this:
class a {
public $aa;
public $ab;
public function __get( $name ){
$this->$name = x;
return $this->$name;
}
}
so, what should I do? First I still want to get that tip list, and only public attribute could be listed. and idea about this?
It seems to me, that you're having two interlocking problems here.
If you add public fields to your class, then you can see them in autocomplete suggestions and it is easier for you to write code, but if you do that, then __get is not executed because this is a visible property and __get is only called for the invisible properties.
If you remove the public fields (or make them private so as to make them invisible), then your __get is executed but you don't get any autocomplete suggestions as there are no visible fields. This way your code works, but it is harder for you to write the code as you get no autocomplete suggestions.
So my suggestion to you would be to forget the __get functionality altogether. Pretend that it does not exist (since it does not do what you want it to do anyway). Use member functions instead of public properties and you'll get the autocomplete suggestions as well as your code executed. Yes you'll have to implement more methods that way, but that's life, you can't always have everything you want, you have to compromise.
What you can do is use something from the Java book and define methods for getters and setters (so either function getName() and function setName($value) or if you prefer you can use function name($value = null) and either set or get depending on the passed in value) or you can assign those values in a constructor if you don't care about the laziness part and the only thing you'll do is assign values.

Which approach is better when passing settings to an object?

I want to set initial values of fields in an object, using $config. Which approach is better in terms of cleaner and more maintainable code?
Also, I would like to add that object will be initialized in a factory and not directly by client.
1. I pass $config to the object
<?php
class UserGreeting {
private $config;
public function __construct($config){
$this->config=$config;
}
public function greetings(){
echo 'Hello, '.$this->config->get('username');
}
}
?>
Pros:
Easy to pass multiple parameters
Cons:
The class is coupled with $config ( is it?). What I mean is that
apart from particular $config interface and parameters naming
conventions, I can't just plug this class into another program
without introducing $config
Client code doesn't have to know which parameters are used by the
object, but that is more general thought
2. I set fields manually outside the object
<?php
class UserGreetingFactory{
public function __construct($config){
$this->config=$config;
}
public function getUserGreeting(){
$userGreeting=new UserGreeting();
$userGreeting->setUserName='John Doe';
return $userGreeing;
}
}
class UserGreeting {
private userName;
public function setUserName($userName){
$this->userName=$userName;
}
public function greetings(){
echo "Hello, {$this->userName}";
}
}
?>
Pros:
The class doesn't care where his parameters are coming from
Can reuse easily
Easier to test(is it?). I mean that I don't have to deal with setting
up $config
Cons:
Factory\Builder has to know which parameers to pass
Lots of extra code for setters and passing parameters
First solution with ctor injection. But instead of a special config i would just pass the actual objects. In your case an User object.
<?php
class UserGreeting
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function greet()
{
printf('Hello, %s!', $this->user->getName());
}
}
Considering your idea's, I'd stick to a single variable. If you want to pass the variables per-method you'll have a lot of excessive code.
From an OOP point of view, you shouldn't put it in a single variable. An object has properties. An username is in fact a property so you should use it as property. That means that in PHP classes you'd need to make it a public variable and set the variables when you create the object.
The first way is better because of dependency injection. This code will be easier to test and to maintain.
The third way is to use Visitor pattern to inject dependencies.
You could use a static class with static methods. In effect they are like CONSTS, but you can enforce all kinds of rules within the static config class - that they conform to an interface for example.
Config::getUserName();
That way if you are going to be faced with a family of config objects, you can be assured they all have at least an entry for each expected value - otherwise a warning is chucked.
Might depend on your situation of course, and I expect there are many situations where you would not want to do this - but I will offer it up all the same.

OOP PHP and 'Get-Set'

I'm wondering is there anyway to create 'Get-Set' method only once that can be use to every attribute
The following code is not correct. Just to make sure you know what I'm looking for
class someClass {
private $attrA;
private $attrB;
private $attrC;
public function get($attr){
return $this->$attr;
}
public function set($attr, $value){
$this->$attr = $value;
}
}
Yes, you can use the magic methods __get() and __set() in the exact way you describe.
More info on the official web site.
Do you want public fields or public properties ?
In case you want properties, where an operation or validation is done when trying to read or trying to modify a property's value, then, I strongly recommend make individual "getter (s)" and individual "setter (s)" for your properties.
It looks difficult at first, but eventually it will make your code extensible and customizable...
Otherwise, just do plain public fields.

PHP: What are Getter and Setters?

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

Categories