За последние 24 часа нас посетили 62313 программистов и 1677 роботов. Сейчас ищут 1144 программиста ...

ArrayAccess

Тема в разделе "Прочие вопросы по PHP", создана пользователем [vs], 9 ноя 2009.

  1. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Давеча столкнулся с неожиданной ошибкой:
    PHP:
    1. <?php
    2. class obj implements arrayaccess {
    3.     private $container = array();
    4.     public function offsetSet($offset, $value) {
    5.         $this->container[$offset] = $value;
    6.     }
    7.     public function offsetExists($offset) {
    8.         return isset($this->container[$offset]);
    9.     }
    10.     public function offsetUnset($offset) {
    11.         unset($this->container[$offset]);
    12.     }
    13.     public function offsetGet($offset) {
    14.         return isset($this->container[$offset]) ? $this->container[$offset] : null;
    15.     }
    16. }
    17.  
    18. $array = new obj;
    19. $array['a'] = array();
    20. $array['a']['b'] = 1;
    21.  
    Так что же это получается - чтобы работать с вложеными массивами, надо их копировать?
    PHP:
    1.  
    2. <?php
    3. $a = $array['a'];
    4. $a['b'] = 1;
    5. $array['a'] = $a;
    6.  
     
  2. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Они тоже должны быть объектами твоего типа.

    PHP:
    1. <?php
    2. $array = new obj;
    3. $array['a'] = new obj;
    4. $array['a']['b'] = 1;
     
  3. kostyl

    kostyl Guest

    точно, когда ты возвращаешь свойство массивом ты же не можешь написать $A->asdf ? Или можешь?
     
  4. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Точно!
    Настрочил такой класс:
    PHP:
    1. <?php
    2. class orray implements arrayaccess
    3. {
    4.         private $container = array();
    5.         public function offsetSet($offset, $value)
    6.         {
    7.                 if (is_array($value))
    8.                 {
    9.                         $val = new self();
    10.                         foreach ($value as $k => $v)
    11.                         {
    12.                                 $val[$k] = $v;
    13.                         }
    14.                         $value = $val;
    15.                 }
    16.                 $this->container[$offset] = $value;
    17.         }
    18.         public function offsetExists($offset)
    19.         {
    20.                 return isset($this->container[$offset]);
    21.         }
    22.         public function offsetUnset($offset)
    23.         {
    24.                 unset($this->container[$offset]);
    25.         }
    26.         public function offsetGet($offset)
    27.         {
    28.                 return isset($this->container[$offset]) ? $this->container[$offset] : null;
    29.         }
    30.  }
    31.  
    32. $array = new orray;
    33. $array['a'] = array(array(array()));
    34. $array['a'][0][0]['name'] = 'vasya';
    35. echo $array['a'][0][0]['name'];
    Работает :)
     
  5. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк

    можешь.
     
  6. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    [vs]
    Рекомендую ArrayObject

    Наследуйся от него.
     
  7. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Да и не нужен мне такой функционал.
     
  8. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    [vs]
    Те же самые замечания что касаются ArrayObject
    касаются и твоего класса.

    Производительность съедается перегрузкой.
     
  9. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Тут BM приведен: http://ru.php.net/ArrayObject
    Код (Text):
    1. ArrayObject fill            0.01441502571106    
    2. ArrayObject read_key        0.018320083618164    
    3. ArrayObject read_foreach    2.1559031009674
    4.  
    5. array() fill                0.012364864349365    
    6. array() read_key            0.013092041015625    
    7. array() read_foreach        0.011217832565308      
    Медленнее всего работает итерация foreach. Поэтому в 20 раз лучше получить сначала переменную с обычным массивом, потом делать foreach. Раз так, то этот функционал мне не нужен.
     
  10. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    И ты туда же....
    Блин вы меня убиваете своими спичечными оптимизациями...


    Инициализация 1000 000 (fill)
    Код (Text):
    1. Твой класс  7.8214108943939
    2. ArrayObject 0.78190612792969
    3. Array       0.66266989707947
    for с переприсвоением 1000 000 (for write_key)
    Код (Text):
    1. Твой класс  1.0682549476624
    2. ArrayObject 0.2873969078064
    3. Array       0.21040177345276
    for с чтением 1000 000 (for read_key)
    Код (Text):
    1. Твой класс  0.80967402458191
    2. ArrayObject 0.2388379573822
    3. Array       0.21538090705872
    foreach с переприсвоением 1000 000 (foreach write_key)
    Код (Text):
    1. ArrayObject 0.31118583679199
    2. Array       0.44690585136414
    foreach с чтением 1000 000 (foreach read_key)
    Код (Text):
    1. ArrayObject 0.32870888710022
    2. Array       0.25177001953125
    Upd: Добавил for read_key, foreach read_key

    Еще вопросы?
     
  11. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Нифига, мой класс создается быстрее, чем arrayacces. А если, как ты предалагаешь, наследовать от него, то получается всё остальное еще медленнее.
    Правда, тут выяснилось, что работа с вложеными массивами реализована в arrayobject, поэтому наследовать ничего не надо. Буду использовать его.
     
  12. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Это еще откуда? Ты наверняка что-то другое хотел сказать.

    ArrayAccess - интерфейс. Он создаваться не может.

    И обращаю внимание "инициализация" у меня в сообщении - это не создание класса. Это заполнение первоначальными значениями в цикле.
     
  13. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Да-да, я хотел сказать arrayobject.
     
  14. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Не может твой класс инстанцироваться быстрее чем ArrayObject...

    Вот тебе еще, кстати
    PHP:
    1. <?php
    2. $arrayObject = new ArrayObject(range(0,999999));
    3. $array = range(0,999999);
    Код (Text):
    1. ArrayObject 0.32296681404114
    2. array       0.38041400909424
    Upd: я был несколько не прав.
    Твой класс действительно инстанцируется быстрее.

    for 1000 000
    $a = new ТвойКласс();
    $a = new ArrayObject();
    $a = array();

    Код (Text):
    1. Твой класс   0.59917187690735
    2. ArrayObject  0.97328877449036
    3. array        0.24841785430908
     
  15. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Simpliest
    У тебя php неправильный
    PHP:
    1. for ($i = 0; $i< 1000; $i++)
    2. {
    3.      $array = new arrayobject(range(0,9999));
    4. }
    Код (Text):
    1. 4.8389
    PHP:
    1. for ($i = 0; $i< 1000; $i++)
    2. {
    3.      $array = array(range(0,9999));
    4. }
    Код (Text):
    1. 4.2088
    А инстанцирование действительно проходит быстрее
    PHP:
    1. for ($i = 0; $i< 10000000; $i++)
    2. {
    3.      $array = new orray;
    4. }
    Код (Text):
    1. 13.333
    PHP:
    1. for ($i = 0; $i< 10000000; $i++)
    2. {
    3.      $array = new arrayobject;
    4. }
    Код (Text):
    1. 22.417
    Upd. долго писал сообщение
     
  16. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    5.3
    плюс присвоение в цикле это было $a[$key] = $val;
    а не $a = new ArrayObject(range(0,999999);

    Вобщем, я не вижу смысл отказываться от ArrayObject в пользу самописных классов :)