0

What I'd like ti achieve is that when I call $obj->CAT[15]; the $obj would check if the property CAT exists if not, get the value on the fly

public function __get($var){
if($var == "CAT") return $this->cats->get_cat($cat_id);
}

so my question is... how to get array's value 15 from my example? to pass it to my get_cat method?

6
  • you can do would $obj->_('CAT[15]') and implement the _() method. i know it's changing the syntax, but it's will work (dunno if that works for you) Commented Oct 5, 2011 at 10:54
  • its not possible to know $cat_id since it will be provided, after __get returned a value Commented Oct 5, 2011 at 10:59
  • Sadly it's still in alpha, but php 5.4 will have array dereferencing, so $obj->CAT[15] will be valid syntax. See the complete list of changes. Also check out this nice overview of new features Commented Oct 5, 2011 at 11:02
  • 1
    @axelarge, $obj->CAT[15] is already valid syntax. The new array dereferencing stuff covers array-like values returned from functions, like: foo()[0]. Commented Oct 5, 2011 at 11:08
  • @IonuțG.Stan: would you mind to show me how? this is too advanced for me.. but I have to learn :) Commented Oct 5, 2011 at 11:25

3 Answers 3

6

Have __get return an instance of ArrayAccess which will delegate to get_cat in its offsetGet method.

Something like this:

class CachedCategories implements ArrayAccess
{
  private $memcachedClient;

  public function __construct($memcachedClient)
  {
    $this->memcachedClient = $memcachedClient;
  }

  // Called when using `$cats[18] = "foo"`
  public function offsetSet($key, $value)
  {
    $this->memcachedClient->set($key, $value);
  }

  // Called when using `$cat = $cats[18]`
  public function offsetGet($key)
  {
    return $this->memcachedClient->get($key);
  }

  // Called when using `isset($cats[18])`
  public function offsetExists($key)
  {
    return $this->memcachedClient->get($key) !== false;
  }

  // Called when using `unset($cats)`
  public function offsetUnset($key)
  {
    $this->memcachedClient->delete($key);
  }
}

$cats = new CachedCategories($someMemcachedClient);
$cats[18];
Sign up to request clarification or add additional context in comments.

5 Comments

In this case it would be much simpler to just implement a get_cart function as suggested by GolezTrol. But if you need to use __get you can try this one.
ArrayAccess: sounds intriguing, how do I do that?
@DS_web_developer, there's a simple example in the manual: php.net/manual/en/…
LOOKS AWESOME! Thank you very much for your patience and time!
@IonuțG.Stan: not only it looks great but it is already working great!!! Gotta love StackOverflow :)
0
class Test
{
    protected $cats;
    function __construct()
    {
        $this->cats = new ArrayObject(); // or your own implementation
        $this->cats[33] = "hey";
    }
    public function __get($name)
    {
        if($name == "CAT") return $this->cats;
    }
}

$a = new Test();
echo $a->CAT[33];

see http://www.php.net/ArrayAccess to implement your own list/map

hope this helps!

1 Comment

No, I don't want to pre-populate some other array...I have my values in memcached, so my get_cat method fetches the value from it on the fly... the whole point is not to use extra memory if not necessary
0

If I understood correctly what you want to achieve, you could use a closure:

class kittengarten
{
   var $cats;
   function __construct()
   {
      $this->cats[0]='Jerry';
      $this->cats[1]='John';
      $this->cats[2]='Barack';
   }
   public function __get($var)
   {
      if($var == "CAT")
      {
         $array_of_cats=$this->cats;
         return function($num) use ($array_of_cats)
         {
            return $array_of_cats[$num];
         };
      }
   }

}
$kittengarten=new kittengarten();
echo 'The third directly accessed cat is '.$kittengarten->cats[2];
$cat=$kittengarten->CAT;
if (is_string($cat)) echo $kittengarten->CAT; 
else echo 'The third cat accessed using closure is '.$cat(2);

Output:

The third directly accessed cat is Barack

The third cat accessed using closure is Barack

3 Comments

I don't want to pre-populate the array since there are 3000+ categories in it...I have to think about scalability and this array would be initialized for evry app instance.../per request / per user.. the memory is suffering now... thats why I a trying to do it on the fly /per category
You do not need to pre-populate; $this->cats is in __construct just for example. The $cat(2) thing will work even if you populate $this->cats later.
Oh, I got it, you already have lots of $obj->CAT[15]'s and do not want to change this! Ionuț G. Stan's answer is what you need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.