php magic method to catch array_push

我只是一个虾纸丫 提交于 2020-01-02 08:55:32

问题


I am looking for a way to intercept the action in array_push, because when it will be retrieve it each value of the array has another info like:

class ClassName {

    var $test = array();

    function __set($attr, $value) {
      $this->$attr = 'My extra value'.$value;
    }    

    function index(){
      array_push($this->test, "some val");
      array_push($this->test, "some other val");

      print_r($this->test);

    }
}

$o = new ClassName();
$o->index();

And expected to get something like:

Array
(
    [0] => My extra value some val
    [1] => My extra value some other val
)

But i get:

Array
(
    [0] => some val
    [1] => some other val
)

Thanks to all


回答1:


Instead of using an array, you can use a class that implements the ArrayAccess interface. This way you have full control over what occurs when you append to the array.

http://php.net/manual/en/class.arrayaccess.php

The drawback is that not all array functions will work on the object (ie sorting etc), but you can push like so:

$object[] = 'new value';

The alternative is to simply make a wrapper function for adding to the array.

public function addToArray($key, $value) {
   if ($key === null) {
      $this->test[] = 'My extra value ' . $value;
   } else {
      $this->test[$key] = 'My extra value ' . $value;
   }
}



回答2:


I don't totally understand what you're asking, but are you trying to do this:

$this->test['key'] = "some val";

That will allow you to setup your own output nicely. Because array_push() will throw on another nested level.

Update: Maybe something along these lines?

function push($prefix)
{
    $refl = new ReflectionClass($this);
    $prop = $refl->getProperties();
    foreach($prop as $p) {
        $this->{$p} = $prefix . $this->{$p};
    }
}



回答3:


To achieve what you're looking for, I suggest you create yourself a function that prefixes any value independent to it's use:

function prefix($value) {
    return 'My extra value '.$value;
}

You can then make use of that function inside the index() function:

function index()
{
    $test = array("some val", "some other val");
    foreach($test as $value)
    {
        $this->test[] = $this->prefix($value);
    }
    print_r($this->test);
}



回答4:


From the PHP manual:

__set() is run when writing data to inaccessible properties.
__get() is utilized for reading data from inaccessible properties.

This is only called on reading/writing inaccessible properties. Your property however is public, which means it is accessible. Changing the access modifier to protected solves the issue.

Try this:

    class ClassName {

        private $test = array();

        public function __set($attr, $value) {
          $this->test[$attr] = $value;

        }    

        public function __get($attr) {
        return $this->test[$attr];
        }    

        public function index(){

          array_push($this->test, "some val");
          array_push($this->test, "some other val");

          return $this->test;

        }
    }

    $o = new ClassName();
    $o->setData = 'My extra value';
    print_r($o->index());



回答5:


The PHP manual says the following about magic methods:

__set() is run when writing data to inaccessible properties. (Emphasis mine)

Because the test property is inside the method and the function that is accessing it is inside the method, the function will see the variable directly and will not use the magic setter.

Additionally, even if you try to use array_push on the magic setter outside the class itself, that still will not work. You will get the error array_push() expects parameter 1 to be array, object given.

If you want to support array_push, you should write your own push($item) method:

function push($item) {
    $this->test[] = 'My extra value' . $item
}

or:

function push() {
    $items = func_get_args();

    // Using array_map is one of the many ways to do this.
    // You could also do it with a simpler `foreach` but I like this way.
    $prepend = function($item) {
        return 'My extra value' . $item;
    };
    $items = array_map($prepend, $items);
    array_push($this->test, $items);
}

if you want to support pushing multiple items at once.



来源:https://stackoverflow.com/questions/10094007/php-magic-method-to-catch-array-push

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!