Summary
Code sample:
Class People {
// private property.
private $name;
// other methods not shown for simplicity.
}
Straight forward. Let me assume that $name
is a PRIVATE class member (or property, variable, field, call it as you wish). Is there any way to do these in PHP:
$someone = new People();
$someone->name = $value;
$somevar = $someone->name;
WITHOUT using __get($name)
and __set($name, $value)
.
Background
I needed to check the assigned $value
, therefore I simply need a getter setter like this:
getName();
setName($value);
And NOT necessarily a getter setter magic method overloading like this:
__get($value);
__set($value, $name);
That said, I simply need a getter setter. But that's NOT what I want. It just doesn't feel like object oriented, for people from static typed language such as C++ or C# might feel the same way as I do.
Is there any way to get and set a private property in PHP as in C# without using getter setter magic method overloading?
Update
Why Not Magic Method?
There are rumors floating around the web that magic method is 10x slower then explicit getter setter method, I haven't tested it yet, but it's a good thing to keep in mind. (Figured out that it's not that slow, just 2x slower, see the benchmark result below)
I have to stuff everything in one huge method if I use magic method rather then split them into different function for each prop开发者_运维知识库erty as in explicit getter setter. (This requirement might have been answered by ircmaxell)
Performance Overhead Benchmarking
I'm curious about performance overhead between using magic method and explicit getter setter, therefore I created my own benchmark for both method and hopefully it can be useful to anyone read this.
With magic method and method_exist:
(click here to see the code)
- Getter costs 0.0004730224609375 second.
- Setter costs 0.00014305114746094 second.
With explicit getter setter:
(click here to see the code)
- Getter costs 0.00020718574523926 second.
- Setter costs 7.9870223999023E-5 second (that's 0.00007xxx).
That said, both setter and getter with magic method and method exists justs costs 2x than the explicit getter setter. I think it's still acceptable to use it for a small and medium scale system.
Nope.
However what's wrong with using __get
and __set
that act as dynamic proxies to getName()
and setName($val)
respectively? Something like:
public function __get($name) {
if (method_exists($this, 'get'.$name)) {
$method = 'get' . $name;
return $this->$method();
} else {
throw new OutOfBoundsException('Member is not gettable');
}
}
That way you're not stuffing everything into one monster method, but you still can use $foo->bar = 'baz';
syntax with private/protected member variables...
ReflectionClass is your salvation
I know it's too late for Hendra but i'm sure it will be helpfull for many others.
In PHP core we have a class named ReflectionClass wich can manipulate everything in an object scope including visibility of properties and methods.
It is in my opinion one of the best classes ever in PHP.
Let me show an example:
If you have an object with a private property and u want to modify it from outside
$reflection = new ReflectionClass($objectOfYourClass);
$prop = $reflection->getProperty("PrivatePropertyName");
$prop->setAccessible(true);
$prop->setValue($objectOfYourClass, "SOME VALUE");
$varFoo = $prop->getValue();
This same thing you can do with methods eighter;
I hope i could help;
If using magical properties doesn't seem right then, as already pointed out by other posters, you can also consider ReflectionClass::getProperty and ReflectionProperty::setAccessible.
Or implement the necessary getter and setter methods on the class itself.
In response to the language features issue that you raised, I'd say that having a dynamically typed language differ from a statically typed one is expected. Every programming language that has OOP implements it somewhat differently: Object-Oriented Languages: A Comparison.
class conf_server
{
private $m_servidor="localhost";
private $m_usuario = "luis";
private $m_contrasena = "luis";
private $m_basededatos = "database";
public function getServer(){
return $this->m_servidor;
}
public function setServer($server){
$this->m_servidor=$server;
}
public function getUsuario(){
return $this->m_usuario;
}
public function setUsuario($user){
$this->m_usuario=$user;
}
public function getContrasena(){
return $this->m_contrasena;
}
public function setContrasena($password){
$this->m_contrasena=$password;
}
public function getBaseDatos(){
return $this->m_basededatos;
}
public function setBaseDatos($database){
$this->m_basededatos->$database;
}
}
精彩评论