За последние 24 часа нас посетил 17801 программист и 1715 роботов. Сейчас ищут 947 программистов ...

Волшебный __get() и "сосиска" в несколько свойств

Тема в разделе "Вопросы от блондинок", создана пользователем lexa, 20 мар 2009.

  1. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Волшебный __get() и "сосиска" в несколько свойств

    Решил тут ознакомиться с интерфейсами обьектов и наткнулся на ArrayAccess и Iterator.

    Соорудил для интереса класс для работы с БД типа:
    PHP:
    1. <?php
    2. $users = new User;
    3.  
    4. foreach ($users as $user){
    5.    echo $user->name.' ('.$user->group->name.')<br />';
    6. }
    Но вот в чём беда, если делать "ленивый" селект из базы, т.е. хватать через __get() свойства и вписывать их по ходу (создавая +1 полупустую итерацию за которую всё хватается и вписывается), то упрёмся в ограниченый __get(). Из цепочки $user->group->name всё можно получить только по одиночке: user, group и name. Это отсосёка та ещё.

    Как можно получить всю цепочку, я бы сказал, цепищу?

    P.S. Я делал в __get() "хваталку" отдельным классом и всё шикарно работало за исключением того, что при получении обработанной цепочки (вроде user_group_name) с ней можно делать много чего, но только не return. Вот хз почему, но всё работает, кроме ретурна.

    P.P.S. Для ознакомления смотрел всякие готовые вещи, но в Kohana, например, метод current() итератора снова и снова создаёт запрос. Т.е. на 20 циклов +20 запросов, а селект в нём *, т.е. всего подряд. Решил "Кохону"-шмохану больше не смотреть.
     
  2. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    не понял в чем трабла. что занчит по одиночке? что за ограниченый __get()? почему не работает ретурн???
     
  3. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Ночью писал, когда мозг уже сгорел. :)

    Есть сосиська: $user->group->name. Каждый из свойст класса это необьявленное свойство, которое ловится через магический метод __get(). Через __get() класса $user она хватается, но хватается кусками как: group и как name, но не как group->name или group['name'].

    Если делать в __get() return $this, то сосиську можно отловить, но не так как надо. Если делать return с отдельным классо (специальный для отлова), то сосиска ловится и формируется, как надо. Но. Но return полученой и отформированной из друго класса нельзя сделать return из текущей __get(). Можно echo, var_dump(), в массив запихать и будет работать. Но не return. Ни в каком виде return не делается. Я даже через ob_start() ловил, но до return строка тупо не доходит, теряется где-то.

    Вот такая вот загвоздка. Проверил на пхп 5.2.4 и 5.2.6 не ретурнит хоть тресни.

    Вооот.
     
  4. topas

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

    С нами с:
    16 авг 2006
    Сообщения:
    2.258
    Симпатии:
    36
    Не совсем понял в чем проблема, но может parent::__get($name) поможет?
     
  5. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Ыыы, даже телепат подкочал. Мысли в кучку у меня. :)

    PHP:
    1. <?php
    2. class User extends SQL {
    3.     // пустой, тока связи описаны и окаканы
    4. }
    5.  
    6. class SQL_vars {
    7.     public $get;
    8.  
    9.     function __get($name){
    10.         $this->get[] = $name;
    11.     }
    12.  
    13.     // тут функция формирования из полученых переменных в _строку_ нужного вида
    14. }
    15.  
    16. class SQL {
    17.     // тут рабочии переменные, чтобы в __get() не лезли
    18.  
    19.     function __construct($name){
    20.         $this->vars = new SQL_vars;
    21.     }
    22.  
    23.     function __get($name){
    24.         $this->vars->$name;
    25.         return $this->vars;
    26.     }
    27. }
    Так вот, return $this->vars не работает. С ней можно сделать var_dump($this->vars), echo $this->vars или в массив запихать как ключ или значение или иную белеберду, но не return.

    Вопрос. Почему, блин?
     
  6. topas

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

    С нами с:
    16 авг 2006
    Сообщения:
    2.258
    Симпатии:
    36
    lexa
    Давай полный код этих классов, вместе подумаем.

    У меня следующая конструкция работает как и ожидается.

    PHP:
    1.  <?php
    2.  class User extends SQL {
    3.      // пустой, тока связи описаны и окаканы
    4.  }
    5.  
    6.  class SQL_vars {
    7.      public $get;
    8.  
    9.      function __get($name){
    10.          return $this->get[$name];
    11.      }
    12.  
    13.      function __set($name, $value){
    14.          $this->get[$name] = $value;
    15.      }
    16.  
    17.      // тут функция формирования из полученых переменных в _строку_ нужного вида
    18.  }
    19.  
    20.  class SQL {
    21.      // тут рабочии переменные, чтобы в __get() не лезли
    22.  
    23.      private $vars;
    24.  
    25.      function __construct(){
    26.          $this->vars = new SQL_vars;
    27.      }
    28.  
    29.      function __get($name){
    30.          return $this->vars->$name;
    31.      }
    32.  
    33.      function __set($name, $value){
    34.          $this->vars->__set($name, $value);
    35.      }
    36. }
    37.  
    38. $user = new User('fuck');
    39. $user->group = 'Guest';
    40.  
    41. var_dump($user->group); // Guest
     
  7. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Мм, код целый дать не могу, его уже нет. Я переделал позавчера "ленивую" загрузку сделал не через пустую итерацию, а тупо подлючаем (джойним, т.е.) то, что есть в селектах, ордере и прочем. Получилось шикарная надстройка над DbSimple. Неожиданно как-то вылупилось. :) Потом куда-нить сюда выложу показать.

    SQL_vars::__get() у меня каждое второе вхождение возвращал как строку, а каждое первое как $this.

    Ладно, не важно. Спасибо за попытку разобраться.
     
  8. topas

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

    С нами с:
    16 авг 2006
    Сообщения:
    2.258
    Симпатии:
    36
    lexa
    обязательно выложи, будет интересно