Вопрос по arrays, php, casting, object – Приведение объекта в массив - вызывается ли какой-нибудь магический метод?

30

У меня есть объект класса Foo:

class Foo extends Bar {
    protected $a;
    protected $b;
}

$obj = new Foo();

Что я хочу (и должен) сделать, это привести этот объект к массиву, например так:

$arr = (array)$obj;

Есть ли какой-нибудь магический (или не магический :)) метод, который вызывается в данный момент? Или есть какой-то другой способ его перехватить? Я знаю, что могу написать простой метод, например.asArray() в Foo, но я ищу более "родной" PHP способы.

Ваш Ответ

6   ответов
38

No

Error: User Rate Limit Exceeded__toArrayError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded2006Error: User Rate Limit Exceeded

[2006-08-20 11:12 UTC] [email protected]

Why not simply have a method asArray() maybe even as par of an interface:

interface ArrayConversion { function asArray(); }

See, we have __toString as it is supported in language constructs like echo, print and other internal functions. But we decided against an autoconversion for arrays already. So itwill never be supported in any language construct. That said there is no needed for this and nothing you would win against the above interface. In fact you would make it php more complex because you'd add just one more magic feature.

Error: User Rate Limit Exceeded

но эй, разве мы не получили конструкцию goto по крайней мере?shivers
Странно, что он должен так сказать, потому что на самом деле у php есть преобразование объекта в массив:php.net/manual/en/…
Вопрос на самом деле в том, чтобы иметь возможность реализовать собственную логику приведения.
13

Error: User Rate Limit Exceeded

$s = (string)$obj;

Error: User Rate Limit Exceeded__toString()Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededtoArray()Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededSerializableError: User Rate Limit Exceeded

1

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededError: User Rate Limit Exceeded

<?php
class Foo {
    public    $foo  = 1;
    protected $bar  = 2;
    private   $baz  = 3;
}

$foo = new Foo();

$reflect = new ReflectionClass($foo);
$props   = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);

foreach ($props as $prop) {
    print $prop->getName() . "\n";
}

var_dump($props);

?>

The above example will output something similar to:
foo
bar
array(2) {
  [0]=>
  object(ReflectionProperty)#3 (2) {
    ["name"]=>
    string(3) "foo"
    ["class"]=>
    string(3) "Foo"
  }
  [1]=>
  object(ReflectionProperty)#4 (2) {
    ["name"]=>
    string(3) "bar"
    ["class"]=>
    string(3) "Foo"
  }
}
3

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

$obj = new ArrayObject(['a' => 'alpha']);
var_dump($obj['a']); //alpha
var_dump($obj->getOffset('a'));//alpha

Error: User Rate Limit ExceededArrayObject

$obj = new ArrayObject(['a' => 'alpha']);
//Access Property
var_dump($obj['a']); //alpha
var_dump($obj->offsetGet('a'));//alpha
var_dump($obj->a); //null Notice: Undefined property: ArrayObject::$a

//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!

//Setting Properties
$obj['b'] = 'beta'; //OK
$obj->c = 'gamma'; //value becomes object property!!!
var_dump($obj);
/* OBJECT DUMP
object(ArrayObject)[13]
  public 'c' => string 'gamma' (length=5)
  private 'storage' =>
    array (size=2)
      'a' => string 'alpha' (length=5)
      'b' => string 'beta' (length=4)
 */

//Property validation as array
var_dump(isset($obj['a']));//true
var_dump(isset($obj['b']));//true
var_dump(isset($obj['c']));//false
//Property validation as object
var_dump(isset($obj->a));//false
var_dump(isset($obj->b));//false
var_dump(isset($obj->c));//true

//Typecasting
var_dump((array)$obj);
/*
array (size=2)
  'a' => string 'alpha' (length=5)
  'b' => string 'beta' (length=4)
 */

//var_dump((string)$obj);// Catchable fatal error: Object of class ArrayObject could not be converted to string

Error: User Rate Limit ExceededArrayObject::STD_PROP_LISTError: User Rate Limit ExceededArrayObject::ARRAY_AS_PROPSError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

$obj = new ArrayObject(['a' => 'alpha'], ArrayObject::ARRAY_AS_PROPS);
//Access Property
var_dump($obj['a']); //alpha
var_dump($obj->offsetGet('a'));//alpha
var_dump($obj->a);//alpha

//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!

//Setting Properties
$obj['b'] = 'beta'; //OK
$obj->c = 'gamma'; //OK
var_dump($obj);
/* OBJECT DUMP
object(ArrayObject)[14]
  private 'storage' =>
    array (size=3)
      'a' => string 'alpha' (length=5)
      'b' => string 'beta' (length=4)
      'c' => string 'gamma' (length=5)
 */

//Property validation as array
var_dump(isset($obj['a']));//true
var_dump(isset($obj['b']));//true
var_dump(isset($obj['c']));//false !!!
//Property validation as object
var_dump(isset($obj->a));//true
var_dump(isset($obj->b));//true
var_dump(isset($obj->c));//true

//Typecasting
var_dump((array)$obj);
/*
array (size=2)
  'a' => string 'alpha' (length=5)
  'b' => string 'beta' (length=4)
 */

Error: User Rate Limit Exceeded__get(), __set(), __isset()Error: User Rate Limit Exceeded__unset().

Error: User Rate Limit ExceededserializeError: User Rate Limit Exceeded$storageError: User Rate Limit Exceeded__toStringError: User Rate Limit Exceeded

class FooObject extends ArrayObject
{
    public function __get($index)
    {
        if ($this->offsetExists($index)) {
            return $this->offsetGet($index);
        } else {
            throw new UnexpectedValueException('Undefined key ' . $index);
        }
    }

    public function __set($index, $value)
    {
        $this->offsetSet($index, $value);
        return $this;
    }

    public function __isset($index)
    {
        return $this->offsetExists($index);
    }

    public function __unset($index)
    {
        return $this->offsetUnset($index);
    }

    public function __toString()
    {
        return serialize($this);
    }
}

Error: User Rate Limit Exceeded

$obj2 = new FooObject(['a' => 'alpha']);
//Access Property
var_dump($obj2['a']); //alpha
var_dump($obj2->offsetGet('a'));//alpha
var_dump($obj2->a); //alpha

//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!

//Setting Properties
$obj2['b'] = 'beta'; //OK
$obj2->c = 'gamma'; //OK
var_dump($obj2);
/* OBJECT DUMP
object(FooObject)[14]
  private 'storage' (ArrayObject) =>
    array (size=3)
      'a' => string 'alpha' (length=5)
      'b' => string 'beta' (length=4)
      'c' => string 'gamma' (length=5)
 */

//Property validation as array
var_dump(isset($obj2['a']));//true
var_dump(isset($obj2['b']));//true
var_dump(isset($obj2['c']));//true
//Property validation as object
var_dump(isset($obj2->a));//true
var_dump(isset($obj2->b));//true
var_dump(isset($obj2->c));//true

//Typecasting
var_dump((array)$obj2);
/*
array (size=3)
  'a' => string 'alpha' (length=5)
  'b' => string 'beta' (length=4)
  'c' => string 'gamma' (length=5)
 */
1

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

30

Error: User Rate Limit ExceededArrayAccessError: User Rate Limit Exceeded

Также следует отметить, что для зацикливания элементов, содержащихся в объекте, расширяетсяArrayAccess с помощьюforeach, вы также должны реализовать\IteratorAggregate или же\Iterator, Обычно те, кто хочет воспроизвести функциональность массива в объекте, используютimplements \Countable, \IteratorAggregate, \ArrayAccess Увидеть\ArrayObject.
Хотя этот ответ и хорош, этот ответ на самом деле не отвечает на этот вопрос. Вы должны по крайней мере включить слово «нет» где-то там :)
Хороший вопрос, но где-то в начале ответа укажите, что реализацияArrayAccess интерфейса недостаточно для приведения объекта в массив.

Похожие вопросы