0

I have a set of variables that i need for multiple other classes. I extended a 'nice' getter function (that guesses for the var name and produces 'set'/'get' functions on the fly) to work with setters to.

Example:

In interface/parent/whatever: public $name;

In some other class that loads the 'mySetterGetter' class: $set_get = new mySetterGetter(); $set_get->get_name();.

Sadly I can't use variables in an interface and can't extend a class with multiple parent classes. Is there some other way to load these "interfaces"/extend the Set/Get class?

What I need to do is the following:

// This should be my "interface" one
class myIntegerInterface
{
public $one;
public $two;
public $three;
}
// This should be my "interface" two
class myStringInterface
{
public $foo;
public $bar;
public $whatever;
}

// This is my setter/getter class/function, that needs to extend/implement different variable classes
class mySetterGetter implements myIntegerInterface, myStringInterface
{
/**
 * Magic getter/setter method
 * Guesses for a class variable & calls/fills it or throws an exception.
 * Note: Already defined methods override this method.
 * 
 * Original @author Miles Keaton <mileskeaton@gmail.com> 
 * on {@link http://www.php.net/manual/de/language.oop5.overloading.php#48440}
 * The function was extended to also allow 'set' tasks/calls.
 * 
 * @param (string) $val | Name of the property
 * @param unknown_type $x | arguments the function can take
 */
function __call( $val, $x )
{
    $_get = false;

    // See if we're calling a getter method & try to guess the variable requested
    if( substr( $val, 0, 4 ) == 'get_' )
    {
        $_get = true;
        $varname = substr( $val, 4 );
    }
    elseif( substr( $val, 0, 3 ) == 'get' )
    {
        $_get = true;
        $varname = substr( $val, 3 );
    }

    // See if we're calling a setter method & try to guess the variable requested
    if( substr( $val, 0, 4 ) == 'set_' )
    {
        $varname = substr( $val, 4 );
    }
    elseif( substr( $val, 0, 3 ) == 'set' )
    {
        $varname = substr( $val, 3 );
    }

    if ( ! isset( $varname ) )
        return new Exception( "The method {$val} doesn't exist" );

    // Now see if that variable exists:
    foreach( $this as $class_var => $class_var_value )
    {
        if ( strtolower( $class_var ) == strtolower( $varname ) )
        {
            // GET
            if ( $_get )
            {
                return $this->class_var_value;
            }
            // SET
            else 
            {
                return $this->class_var_value = $x;
            }
        }
    }

    return false;
}
}
kaiser
  • 21,817
  • 17
  • 90
  • 110
  • I wonder, why do you need that kind of magic? Why not work via the properties directly and introduce __get and __set at a later stage if you need to have custom setters and getters? – phant0m Jun 21 '11 at 19:41
  • The whole construct is implemented in a much larger one. I got a loader/extender class, database handling, and much more. The whole construct currently is set to handle different scenarios (creating a page, a dragable box, a table and form fields. The only difference is a) the basic values i need and b) the constructor classes i call for the different scenarios. Therefore it would make my life a lot easier to not write set_/get_ functions for the different szenarios, but let this be handled by the __call method and only define the variables in a single encapsuled file/class. – kaiser Jun 21 '11 at 20:01

1 Answers1

2

It sounds like you want something like this:

// An abstract class that can't be instantiated but which provides a __call method to other classes that extend this one.
abstract class mySetterGetter
{
  function __call($val, $x)
  {
    $_get = false;

    // See if we're calling a getter method & try to guess the variable requested
    if( substr($val, 0, 4) == 'get_' )
    {
      $_get = true;
      $varname = substr($val, 4);
    }
    elseif( substr($val, 0, 3) == 'get' )
    {
      $_get = true;
      $varname = substr($val, 3);
    }

    // See if we're calling a setter method & try to guess the variable requested
    if( substr($val, 0, 4) == 'set_' )
      $varname = substr($val, 4);
    elseif( substr($val, 0, 3) == 'set' )
      $varname = substr($val, 3);

    if ( ! isset($varname) )
      throw new Exception("The method {$val} doesn't exist");

    // Now see if that variable exists:
    foreach( $this as $class_var => $class_var_value )
    {
      if ( strtolower($class_var) == strtolower($varname) )
      {
        // GET
        if ( $_get )
          return $this->class_var_value;
        // SET
        else
        {
          $this->class_var_value = $x[0];

          return;
        }
      }
    }

    return false;
  }
}

// myString
class myString extends mySetterGetter
{
  public $foo;
  public $bar;
  public $whatever;
}

// myInteger
class myInteger extends mySetterGetter
{
  public $one;
  public $two;
  public $three;
}

You can also "fake" inheriting by multiple classes as in this previous Stack Overflow question: Can I extend a class using more than 1 class in PHP?.

Community
  • 1
  • 1
Francois Deschenes
  • 24,816
  • 4
  • 64
  • 61
  • +1, I was confused by how he presented the question, but I think you're right in that this is all he needs. Of course, unfortunately, you can still run into the similar problem where you don't really want to "waste" the inheritance on something like a getter/setter class. – Matthew Jun 21 '11 at 19:33
  • @konforce - I agree with you but I think given the currently available option in PHP, the only option is inheritance. Thanks for the +1. – Francois Deschenes Jun 21 '11 at 19:36
  • I doubt he wants that, since he explicitly states "can't extend a class with multiple parent classes" he probably ins't looking for inheritance. – phant0m Jun 21 '11 at 19:38
  • @phant0m - His example doesn't show that. He could always consider making the parent class extend the abstract getter/setter class. – Francois Deschenes Jun 21 '11 at 19:40
  • @phant0m, yes, but the OP's code is nonsensical. If he is importing the same variables into a single gettersetter class (thus making it non-reusuable), then he might as well just hardcode them all and forget about extending or implementing anything. – Matthew Jun 21 '11 at 19:41
  • Yes, that is correct of course. I had assumed he was after mixins or traits. – phant0m Jun 21 '11 at 19:42
  • @phant0m - Which he probably is but they're not available in PHP (as of yet). – Francois Deschenes Jun 21 '11 at 19:44
  • @Francois Deschenes, yes, I am aware of that :) – phant0m Jun 21 '11 at 19:46
  • @Francois Deschenes +1. @phant0m @konforce I'm already using a "Multi-Extender" to have all my base classes available in every class that builds an object. The basic (abstract) loader class that allows multi extensions won't allow the use of `__call` as it already defines it to use methods from extended classes with `$this->method( $args );`. So I had to go another route and separate my constructor objects from the data objects. Everything now works fine and is close to no effort if i extend anything. Thanks to all of you! – kaiser Jun 22 '11 at 00:42
  • @kaiser: You could mimic them though to some extent: have your class delegate `__call()`, `__set()` and `__get()` to an array of objects of your "mixins". (Not that it would be pretty though) – phant0m Jun 22 '11 at 17:07
  • @phant0m Thanks for the suggestion, but for several reasons I don't want to extend the basic loader. It's currently pretty general and reuseable. Dropping that in would make it case specific - and I'd have to extend it for every following case. Thanks though! – kaiser Jun 22 '11 at 17:11