I use magic methods _set, _get:
public function __set($name, $value)
{
array_push($this->groups, $value);
}
public function __get($name)
{
return $this->$name;
}
And use this like as:
// Set
$menu->groupName = 'Регистрация';
// Get
echo $menu->groupName
Why echo $menu->groupName does not work? it returns nothing. It should return text 'Регистрация'.
I tried just return in _get:
return $name;
In your __set you process assigning to nonexistent property as adding it's value to array $this->groups. This code does not create property for you.
When you want to access nonexistent property __get works. But in it you want to access groupName property, but you didn't create it.
To debug your code, add a line
echo'<pre>',print_r($this),'</pre>';
to you __get method:
public function __get($name)
{
echo'<pre>',print_r($this),'</pre>'; // TODO
return $this->groups[0];
}
You will see that "Регистрация" is there, but it is in $groups property.
So, you can either modify __get to
public function __get($name)
{
return $this->groups[0];
}
as you don't have other values in $groups.
Or modify full code:
public function __set($name, $value)
{
$this->groups[$name] = $value;
}
public function __get($name)
{
return isset($this->groups[$name]) ? $this->groups[$name] : 'NO VALUE';
}
From The PHP Documentation on overloading:
The overloading methods are invoked when interacting with properties or methods that have not been declared or are not visible in the current scope. The rest of this section will use the terms "inaccessible properties" and "inaccessible methods" to refer to this combination of declaration and visibility.
In short, the properties you want to be handled by your overloading method MUST be either private, protected, or undefined.
Moreover, overloading itself isn't commonly used within PHP. In most cases, it's better to create your own get() and set() methods, rather than inherit the complexities associated with the overloading magic methods. Even then, custom get/set methods are only practical if you are doing more than just storing the data.
Where Overloading Makes Sense:
Overloading is great for security, validation, and data transformation, because it allows you to control the visibility of information within your application.
With overloading you can create variables that:
Can only be read
Can only be written to
Can only be read or written to a certain number of times
Can be validated before writing
Can update other variables
Etc.
Related
There seems to be a lot of questions on setters and getters in PHP. However, none of them seem to mention that they do not work with public variables.
I have a series of public variables, which on setting need the same type of data checking (mainly strip_tags()).
What is the most code efficient way to do this whilst keeping the variables public?
The only option which seems to be available is creating a method 'setPropertyName' for all of my variables, which seems unnecessary to me.
Thanks for any help.
You can make them private, and using a public __set() and __get() to fetch the variables if they exists, and apply the validation/sanitation operations when they set.
For example:
class Foo {
private $variable;
private $otherVariable;
public function __get($key) {
return $this->$key;
}
public function __set($key, $value) {
$this->$key = strip_tags($value);
}
}
$foo = new Foo;
$foo->variable = "test"; //Works.
echo $foo->variable; //test
One thing you could try is the magic method __call($name,$args), then you wouldn't need to code the setPropertyName and getPropertyName functions:
function __call($name,$args){
$variable=lcfirst(substr($name,3));
if(!isset($this->$variable))
return false;
if(substr($name,0,3)=='set')
$this->$variable=$args[0];
else
return $this->$variable;
return true;
}
That being said, magic methods __get and __set work great with public variables if utilized properly. Below is how I utilize them:
public $variables=array();
function __get($name){
return isset($this->variables[$name])?$this->variables[$name]:false;
}
function __set($name,$value){
$this->variables[$name]=$value;
}
Then you can access them by using $this->name; rather than $this->getName();
Put both of them together and then you can do it however you want.
Again, this is a backbone. If you want to strip tags, you can put that in the code either in the setter or getter functions, or modify the call function to check for a 2nd argument that will strip the tags $this->setName($value,true);//strip tags
It is actually probably best practice to actually explicitly define your getters and setters. That being said you can use the __set() and __get() magic methods to provide common handling for requests to properties that are inaccessible from outside the class (protected and private).
So, all you would need to do is make your properties protected/private and specify __get() and __set() methods (also might need __isset() and __unset() as well if you will be checking the properties using isset() or trying to unset() properties).
Again, it is really best practice (IMO) to make all class properties inaccessible from outside the class and explicitly make setters/getters as need to provide access.
Matt Zandstra gives the following example in his text "PHP Objects Patterns and Practice" to illustrate the __get() method:
class Person {
function __get( $property ) {
$method = "get{$property}";
if ( method_exists( $this, $method ) ) {
return $this->$method();
}
}
function getName() {
return "Bob";
}
function getAge() {
return 44;
}
}
In reality, we know we would never actually create such methods (getName and getAge) to return such static values, but instead - we would create name and age properties in the object and return those using the $this operator.
My question is whether this example actually shows utility. And if it does not, could somebody provide a better example of why one would use __get() for the same sort of purpose?
Justification for asking
If we were to use name and age properties in the object, then the __get() function would not be fired anyway, because attempting to get these properties with:
$person = new Person();
$name = $person->name;
would cause either the name property to actually be returned if it were public, or cause a visibility error if it were private or protected. The __get() function would not be executed in either of these 'real' cases... am i missing something?
I'm fully aware that the above code works.
I am not convinced that it is a practical example.
You are absolutely right - I am impressed that you are quoting from a book, that example just plain sucks.
Using the magic __get method to call methods is just wrong, there are other magic methods just for that kind of usage:
__call()
__callStatic()
__invoke()
__get() and __set() should be used to read and write non declared object properties.
The actual functionality of magical methods is totally up to the developer to handle in any way they see fit. The difference is in how they are invoked.
$obj->property; // invokes __get(), if defined
$obj->method(); // invokes __call(), if defined
$obj(); // invokes __invoke() if defined (php 5.3+)
etc. So if you want to have __get() call a method internally, you can. How you want to handle it depends entirely on how you want to design your application.
About __get(), if you have a public member and try to call it with ->, the __get() will not fire. However, if you try to access a non-accessible member (either protected, private, or nonexistent) __get() will fire and you can handle it how you like.
It is my understanding that the main purpose of __get() at least according to php is to eliminate the need to write getters for every member. Compare with __set() for setters. I don't want to get into this here, but I think the use of getters/setters should raise some red flags about design. However, __get()'s intended purpose does not have to be adhered to except for the standards of those developing the application.
Two examples of how __get() might be used are to initialize a property that may not be needed upon instantiation (e.g. by a DB query) thus reducing overhead. Another may be if you have properties stored in an array, magical get may return the value mapped to the key of the requested property.
With the php magic functions, you can do some very cool things and you can write code that is more extensible by using these special invocations. Something I like to do:
class application {
public function __call($_, $_) {
throw new Exception("PUT and DELETE not supported");
}
public function POST() {
//update data
header("Location: $_SERVER[PHP_SELF]", true, 303);
}
public function GET() {
//display data
}
public static function inst() {
return new self;
}
}
application::inst()->$_SERVER['REQUEST_METHOD']();
Of course, this is using __call() rather than __get(), but the principle's the same. In this case it's just a sanity check.
As php.net states
"__get() is utilized for reading data
from inaccessible properties."
This means that __get() (if it's defined) is called whenever you try to access a property that does not exist or is private / protected. The above example shows a way for getting the values of those private properties by calling their accessors (getters) whenever someone tries to get the values.
For example, calling
echo $a -> publicPropery or echo $a -> getPublicProperty()
would result in the same thing. However if you call $a -> privateProperty you would get an error, and
$a -> getPrivateProperty()
would be OK.
But, if you defined __get() whenever you call $a -> privateProperty, __get() is executed and redirected to $a -> getPrivateProperty(). In this case you would always succeed in getting the value and still keeping security in mind. Even more, since you check for the existance of the property getter in __get() you could show an appropriate error or throw an exception if someone tries to access unexisting properties, which will override php's visibility errors.
<?php
class data {
public $name="Ankur DalsaniYa"; \\ I wont to change name
public function __get($var) {
print "Attempted to retrieve '<b>$var</b>' and failed...\n";
//$var is print the Unknown and Not Define but call variable print
}
}
$data = new data;
echo "<br> Not Define Variable Call : ";
print $data->title; // Not Defined variable Call then call __get function
echo "<br><br> Define Variable Call : ";
print $data->name; // Define variable Call then Not call __get function
?>
I'm creating a dynamic class that responds to magic __call() method. The problem is, since I'm building this on top of a already existing framework (Kohana), it checks if the method of the class exists using ReflectionClass::hasMethod, and it doesn't seem to trigger the __call() magic method for checking for it's existance. What could I do in this case? Seems like if you add the method dynamically (like $this->{$name} = function(){}) it still can't "see" it
Without more details, I'm unsure if this would suffice, however you could create proxy class to perform intermediate functionality:
class MyProxy {
protected $_object = null;
protected $_methods = array();
public function __construct($object) {
if (!is_object($object)) {
throw new InvalidArgumentException('$object must be an object');
}
$this->_object = $object;
}
public function __call($name, $arguments) {
return $this->callMethod($name, $arguments);
}
public function setMethod($name, Closure $method) {
$this->_methods[(string) $key] = $method;
}
public function callMethod($name, array $arguments) {
if (isset($this->_methods[$name])) {
return call_user_func_array($this->_methods[$name], $arguments);
}
return call_user_func_array(array($this->_object, $name), $arguments);
}
}
By calling $proxy->setMethod('foo', function () { });, you can dynamically "attach" methods to the object. When you call $proxy->foo(), it'll first do a look-up against the dynamically attached methods; if it finds one, it'll call it. Otherwise, it'll just delegate to the internal object.
Now, the problem with this approach is that attached methods aren't bound to the proxy. In other words, $this doesn't exist in the scope of an attached method.
This can be fixed though, with features from PHP 5.4+.
public function setMethod($name, Closure $method) {
$this->_methods[(string) $name] = Closure::bind($method, $this);
}
We've refined setMethod to rebind the passed closure to the proxy. Now, in the scope of an attached method, $this will point to the proxy object.
We could have rebound it to the enclosed object, but then the attached methods couldn't talk to the proxy (or other attached methods). For completeness, you'll want to add __get and __set magic, to forward property access/mutate calls to the internal object (or handle them in the proxy, whatever)
Besides, the internal object has no clue about the proxy, so it's methods (from the class definition) won't know about any of this dynamic magic anyway.
Seems like if you add the method dynamically (like $this->{$name} = function(){}) it still can't "see" it
Right, as you're creating a new property, not a method. At time of writing, PHP did not support calling anonymous functions in properties without going through __call, which isn't Reflection-friendly. Properties-with-anonymous-functions-as-methods work properly in PHP 5.4.
The only other way to add a method to a class in a way that Reflection will pick up on is using the highly experimental "runkit" extension.
On Zend Quick Start Guide here http://framework.zend.com/manual/en/learning.quickstart.create-model.html we can see:
class Application_Model_Guestbook
{
protected $_comment;
protected $_created;
protected $_email;
protected $_id;
public function __set($name, $value);
public function __get($name);
public function setComment($text);
public function getComment();
...
I normally create my getters and setters without any magic method. I've seen this on the quick guide, and I don't understand why may we need this.
Can anyone help me out?
Thanks a lot
You (usually) never call __set or __get directly. $foo->bar will call $foo->__get('bar') automatically if bar is not visible and __get exists.
In the tutorial you've linked to, the getter and setter get set up to automatically call the appropriate individual get/set functions. So $foo->comment = 'bar' will indirectly call $foo->setComment('bar'). This isn't necessary... it's only a convenience.
In other cases, __get can be useful to create what looks like a read-only variable.
If you "make your own" getters and setters, you'll be making two functions for each property: getPropname() and setPropname. By using PHP's "magic method" setter/getter, you don't write individual methods for each property. You can set/get properties as if they were public. Within the overload functions, you add the logic specific to each property. Example:
public function __set($name, $value) {
switch ($name) {
case 'comments':
// do stuff to set comments
break;
case 'parent_user':
// do stuff to set parent user
break;
}
}
public function __get($name) {
switch ($name) {
case 'comments':
// do stuff to get comments
break;
case 'parent_user':
// do stuff to get parent user
break;
}
}
Now I can access comments by using $obj->comments to either set or get.
To achieve the above functionality without using the overloads, I would have had to write 4 different methods instead. This is really more about code organization, both in terms of the actual file and in terms of creating a standardized interface for objects within a project.
I personally prefer to do as you do and write separate methods for each property that I need a complex getter/setter. To me, it is more clearly organized, and there is a clear separation between "simple" properties of an object and those properties which have greater complexity or one-to-many relationships.
The __get and __set magic methods exist for TWO reasons:
So that you don't have to spend time creating vanilla accessor methods for all of your properties.
To allow you to implement property overloading.
If you have properties that need special treatment, then the magic methods are not for you. However, if your properties simply contain data and there are no dependencies then there's no reason NOT to use the magic methods.
Further on the tutorial it gets you to modify the __get() and __set() methods so you'll see why they're there.
Having magic handling like that can allow you to do some neat stuff like even making "read only" properties and can prevent you from bloating your class with a messy load of getter/setters.
You'll run into problems when you've used __set and want to override the setter functionality in a child class. You'll have to copy the entire code in __set and change only the specific part instead of just simply overwrite one specific setter function -> redundant code
This problem can be avoided by calling the specific setter in __set (thanks to cHao for the tip).
Example:
class Foo1 {
protected $normal;
protected $special;
public function setSpecial($special) {
if ($special == isReallySpecial()) {
$this->special = $special;
}
}
public function __set($key, $value) {
switch ($key) {
case 'normal':
$this->normal = $value;
break;
case 'special':
$this->setSpecial($value);
}
}
}
class Foo2 extends Foo1 {
public function setSpecial($special) {
if ($special == isNotReallySpecial()) {
$this->special = $special;
}
}
}
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.