views:

49

answers:

4

Hi all,

If I have a class (like below) and in a function I set a variable (below:$this->example) but I havent declared the variable at the top of the class (e.g var $example;) where and how can I use this variable? I tried using it straight away in another function but it didn't work (I guess I could have made a mistake but it worked after I declared it in the top of the class)

I have seen this in Symfony for setting variables that you can use in the view and also I came accross it in Phorms to name a couple of examples.

Sorry if this is obvious, I would just like to understand how I can use these variables, including getting the name of the variable(e.g $this->example, by name I mean "example").

class ExampleClass{
  var $another_var;
  function __construct($data){
    $this->example = $data;
    $this->another_var = $data;
  }

  function exampleFunction(){
    $test = $this->example; //this doesnt work
    $another_test = $this->another_var; //this obviously does
  }
}

Any help would be much appreciated

Regards

Luke

EDIT: (from my reply to DrColossus)

I want to be able to set any variable name in a function and in another function grab any variables set with there name.For example in Symfony I can set $this->completly_random_name = $x in an action class function, then in the view I can use $completly_random_name. There is no way that symfony has set every possible combination of variable names in the top of the parent class.

A: 

class properties are defined as public by default, but you shouldn't do that. you should define properties private/protected and define getter/setter methods to work with them from outside the class. it's much easier to maintain afterwards..

kgb
A: 
class ExampleClass{
  private $another_var;
  private $example;

  public function __construct($data){
    $this->example = $data;
    $this->another_var = $data;
  }

  public function getExample() {
    return $this->example;
  }

  public function setExample($example) {
    $this->example = $example;
  }

  public function exampleFunction()
    $test = $this->example; //now that you have a private $example, this will work
    $another_test = $this->another_var; //this obviously does
  }
}

Use Getters/Setters that are public to access private variables.

edit Aistina was quicker than me, his examples show how you can access/retrieve any variable name.

DrColossos
Hi DrColossos, I dont want to set the variable in the top of the class. I want to be able to set any variable name in a function and in another function grab any variables set with there name. For example in Symfony I can set $this->completly_random_name = $x in a function, then in the view I can use $completly_random_name. There is no way that symfony has set every possible combination of variable names in the top of the parent class. Does this make sense.
Luke
A: 

I'm not a pro on this, but my OO conditioned Mind tells me, that its bad practice not to define class member variables no matter what language is used.

Maybe the Frameworks you referred to are using this pattern in subclasses where the members are defined in a superclass?

To the second question: you should take a look at php's reflection classes Reflection helps you to find out about the structure (constructors, methods, properties) of a class.

tweber
+2  A: 

Skipping the talk of how you normally shouldn't do this, you can accomplish what you want using PHP's magic __get and __set functions.

class MyClass {
  // add one member var that holds all the data
  private $myMagicData = array();

  private $another_var;

  function __construct($data){
    $this->example = $data; // this will auto-call the __set function
    $this->another_var = $data; // this won't, since $this->another_var was declared above
  }

  function __get($name) {
    return array_key_exists($name, $this->myMagicData) ? $this->myMagicData[$name] : null;
  }

  function __set($name, $value) {
    $this->myMagicData[$name] = $value;
  }

  function exampleFunction(){
    $test = $this->example; // this will auto-call the __get function
    $another_test = $this->another_var; // this won't
  }
}

Documentation on these and other magic functions.


Why you shouldn't do this.

In my opinion, using the magic __get and __set functions promotes poor programming practice. Let me demonstrate using a famous example: If a glass is half-filled, is the glass half-full or half-empty? The correct answer from a programmer's point of view is that the glass is too large. What I mean by this is, when you add the magic functions as demonstrated above, you can just keep on assigning variables and it won't care, but are they necessary?

Over time, your code will change and you might no longer need old variables that were previously assigned. Normally, you would just remove the variable declaration, meaning your class will now consume less (unneeded) memory. If you forgot to remove one of the old assignments, you'll find out soon enough. With the magic function functionality, how are you going to keep track of which variables you need, and which you don't?

Remember that code should be written primarily for humans to read, and only secondarily for machines to execute. If a second person were to join you and he wonders what variables he has access to in the view, he would either have to go through the code assigning the variables, or print_r($this->myMagicData), rather than just looking at the section of the class where the variables are declared.

And, of course, there is also the overhead of the magic functions getting called, which may or may not be a concern depending on the situation.

So, to summarize, manually declaring the variables you need helps:

  1. Keep track of what data you are and aren't using
  2. Makes your code easier to read for both you and others
  3. Performs faster

Hope this helps!

Aistina
Fantastic Aistina, thank you very much. Where can I get the talk on why you shouldnt do this, I would like to understand before I go and abuse bad practices?
Luke
@Luke Please read my edit.
Aistina
Really useful description thanks, if I was only using the magic methods to set variables for a view using extract(), would you call this lazy, Im not looking to get away with not declaring class variables, I just want nicer code to set variables for a view, currently I have a set function called like Render::set(array('variable_name'=>$variable)) but with the above method the user/me could assign variables: $this->variable_name = $variable, it just seems nice and neater to me. Thanks for your help, RegardsLuke
Luke
@Luke it is not up to me to judge, and the decision lies solely with you. I'm just saying that I, personally, would never use this unless I had no other choice. Just keep in mind what I wrote above and you'll probably be fine.
Aistina