Pull to refresh

Самопальная ORM для Битрикс

Reading time 3 min
Views 11K
Не смотря на то, что модуль с поддержкой ORM разработчики битрикса анонсировали ещё в конце прошлого года, и того, что этот модуль заявлен в списке доступных в практически всех редакциях, реально его пока что нет в комплекте, как нет по нему и документации. Оставим за кадром неэтичность включения отсутствующих фич в описание продукта в разделе покупки, вернемся к ORM. Раз его нет — почему бы не реализовать нечто подобное самостоятельно?





Для нетерпеливых — сразу дам ссылку на исходники модуля, на GitHub'е. Это как-бы прототип — потому что имеет некоторые проблемы, да и не все моменты решены красиво, но тем не менее, он уже работает. Так что всё-таки наш продукт. Хоть и прототип. На написание кода ушло менее 4х часов, со всеми вытекающими.

Полезности


  • Реализован механизм создания объектов нужных классов через фабрику.
    $item=new ORM(5); //создаем объект инфоблока с номером 5
    $item=ORM::Factory(5); //аналогично
    
    $item=new ORM("news"); //создаем объект инфоблока с CODE=news
    
    $item=ORM::Factory("news"); //сначала будет попытка создать объект класса newsBitrixOrm или NewsBitrixOrm, если таковой не будет найдет - попытка создать объект инфоблока с CODE=news
    

  • Есть поддержка сеттеров и геттеров, автоматически применяемых при работе с полями.
    class NewsBitrixORM extends ORM{
        protected $IBlockID=1;
        protected $auto_getters = array("NAME"=>"GetNameValue");
        protected $auto_setters = array("NAME"=>"SetNameValue");
        
        public function GetNameValue($value){
            return str_replace(" (имя новости!)", "", $this->_data["NAME"]);
        }
        public function SetNameValue($value){
            $this->_data["NAME"]=$value." (имя новости!)";
            $this->_changed_fields["NAME"]="NAME";
            return true;
        }
    }
    

  • Реализованы все базовые действия (создание, удаление, изменение, поиск по различным фильтрам).
    $ormNews = ORM::Factory(4);
    $list=$ormNews->Where("WIDTH","=","140")->FindAll();
    foreach ($list as $_news){
        $_news->NAME="Новость с номером {$_news->ID}";
        $_news->WIDTH=24;
        echo "<pre>".print_r($_news->AsArray(true),true)."</pre>";
        if ($_news->ID%2==0) $_news->Delete(); else {
            $_news->NAME.=" [обновлена!]";
            $_news->Save();
        }
    }
    

  • Работа как со стандартными полями, так и с пользовательскими свойствами идет совершенно одинаково.
  • Есть своя особенность при работе с полями типа «список». Например, у нас есть свойство COLOR. При работе с ним будет видно два поля — COLOR, содержащее текстовое значение выбранного элемента списка, и COLOR__ID (два подчеркивания), содержащее ID выбранного варианта. Для изменения значения нужно назначить ему ID другого варианта списка (например $item->ID=5), при этом автоматически COLOR__ID получит это значение, а COLOR — изменит текстовое значение.


Недостатки


  • некоторое уменьшение скорости. Работает с уже существующим API для работы с данными инфоблоков, а не напрямую с базой. С другой стороны, эти части можно и переписать, после чего весь код, завязанный на данную ORM продолжит работать
  • работает исключительно с элементами (не с папками)
  • отсутствуют нормальные механизмы для сложных запросов со вложениями запросами, с OR-запросами.
  • отсутствует возможность наполнять свойства-массивы (множественные свойства) запросом вида $obj->item[]=«значение»; Вместо него пока приходится использовать AddToArrayValue(«item»,«значение»). Как обойти этот момент, пока что не придумал.
  • отсутствует решения для создания зависимостей между инфоблоками (один к одному, один ко многим и т.п.)
Tags:
Hubs:
+2
Comments 11
Comments Comments 11

Articles