За последние 24 часа нас посетили 20674 программиста и 1113 роботов. Сейчас ищут 565 программистов ...

ORM

Тема в разделе "Решения, алгоритмы", создана пользователем Ti, 29 апр 2009.

  1. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    скачать ORM v2.3 с примером использования
    ---------------------------------------------------------------------------------------

    ORM v3 в разработке^ww находится в альфа-версии.

    Выше выложена наша реализация ORM (далекой от идеала).
    Теперь я решил создать третью версию.

    Что хочется видеть в результате:
    - очень простое API (см. примеры ниже)
    - жадная выборка
    - ленивая выборка
    - гибкость (возможность юзать голый SQL и QueryBuilder для выборок)
    - небольшой размер
    - небольшое использование памяти
    - быстрота
    - хорошее покрытие тестами
    - поддержка различных БД, в первую очередь PostgreSQL, MySQL, SQLite
    - поддержка различных php расширений для ДБ, в первую очередь PDO
    - привязка к произвольной структуре БД
    - manual
    - физически один объект для объектов полученных из разных мест
    - автоподстановка в редакторах на всех уровнях (классы, свойства, методы)
    - OrmAdmin

    Что скорее всего не будет:
    - связь многие ко многим
    - наследование
    - валидаторы

    Зачем нужна ORM?
    - увеличение производительности разработчика (хорошо реализованная ORM на порядок удобней SQL)
    - снижение ошибок при написании программ (т.к. код получения и изменения в ORM и хорошо протестирован)
    - защита от SQL инъекций (невозможно случайно не экранировать, т.к. об этом заботиться ORM)


    Как это будет выглядеть:
    PHP:
    1. <?
    2. // получаем все объекты MyClass
    3. foreach(ORM()->MyClass as $myObject) { /* ... */ }
    4. // получаем объект по ID 5
    5. $myObject = ORM()->MyClass(5);
    6. echo "$myObject->name $myObject->lastName";
    7. // по условию
    8. foreach(ORM()->MyClass->like('name', '%waka%') as $myObject) { /* ... */ }
    9. // прозрачное объединение таблиц
    10. $list = ORM()->MyClass;
    11. $list->name = 'waka';
    12. $list->MyClass2->name = 'waka waka';
    13. foreach($list as $myObject) { /* ... */ }
    14.  
    15. // создание таблиц
    16. $class = ORM()->add('MyClass');
    17. $class->add('name', 'text', 255);
    18. $class->add('lastName', 'text', 255);
    19. $class->add('myObject', 'MyClass2');
    20. $class->save();
    21.  
    22. // удаление объекта
    23. $myObject->delete();   
    24. // удаление по условию
    25. ORM()->MyClass->like('name', '%waka%')->delete();
    26.  
    27. // обновление по условию
    28. ORM()->MyClass->like('name', '%waka%')->set('name', 'waka waka')->update();
    29.  
    30. // создание объекта
    31. $object = ORM()->MyClass();
    32. $object->name = 'waka';
    33. $object->save();
    34.  
    35. // физически один объект
    36. ORM()->MyClass(5) === ORM()->MyClass(5); // true
    37. ?>
    Я намеренно отказался от конструкций new MyClass(5) для получения и new MyClass для создания
    т. к. нельзя гарантировать "физически один объект для объектов полученных из разных мест"

    У меня есть полное представление как это будет работать.

    Проект OpenSource, лицензия BSD. TDD.

    Жду от вас:
    1. Желающие участвовать в разработке.
    2. Вопросы
    3. Предложения
    4. Критика

    Спасибо.
     
  2. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Что мне это даст?
     
  3. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    хорошую ORM

    или ты спрашиваешь, зачем тебе вообще нужна ORM?
     
  4. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    да, зачем она мне, я всё никак понять не могу, но все почему-то тыкают в неё пальцем =)
     
  5. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Есть Doctrine. И оно тяжелое. Использую там, где с ресурсами не считаются вообще. Не для WEB. Точка. Я сказал © Д.Ф.Купер
     
  6. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Зачем нужна ORM?
    - увеличение производительности разработчика (хорошо реализованная ORM на порядок удобней SQL)
    - снижение ошибок при написании программ (т.к. код получения и изменения в ORM и хорошо протестирован)
    - защита от SQL инъекций (невозможно случайно не экранировать, т.к. об этом заботиться ORM)

    Мне в Doctrine много вещей не нравиться, но в топе этого списка громосткий синтаксис, много букв

    Я очень люблю jQuery - просто и лаконично.
    Если провести аналогию, моя реализация - это jQuery, Doctrine - это работать с голым DOM, а SQL - это голый HTML
     
  7. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    уменьшения пр-ти скрипта
    ок
    кстати говоря, не всё нужно экранировать, столкнулся недавно с такой проблемой...

    ну ладно.
    реализуй мне выборку дерева категорий (id,parent_id)
     
  8. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    вообще, хочу реализацию посмотреть, её нет ещё как я понимаю?
     
  9. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    PHP:
    1. <?
    2. // реализация
    3. class Tree extends ORM_Object {
    4.     function getChilds() {
    5.         return ORM(__CLASS__)->equals('parent', $this);
    6.     }
    7. }
    8.  
    9.  
    10. // использование
    11. function showTree(Tree $root, $level = 0) {
    12.     echo str_repeat('&nbsp;', 3*$level);
    13.     echo $child->title;
    14.     echo '<br />';
    15.     foreach ($root->getChilds() as $child) showTree($child, $level+1);
    16. }
    17. showTree(ORM()->Tree(1));
    есть второй версии (со всеми вытекающими)

    1. незначительно
    2. критичные места всегда можно на замнить на SQL
    3.
     
  10. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    во второй версси так же дерево выбирается? если да, дай ссылочку
     
  11. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Практически так же.
    работающий пример дерева в example.php

    http://ti.y1.ru/orm2.zip
    84 кб.

    база test, юзер test, пароль test (поменять в bootstrap.php)

    ORM2 разрабатывался в составе framework, я оставил из него только необходимое для ORM и OrmAdmin (см /acp)
    ORM2 допускал создание таблиц только средствами ORM, схему сохранял в базе.
    только PostgreSQL под PDO.
     
  12. kostyl

    kostyl Guest

    Есть желание, времени очень мало, но желание все таки есть, так что много сделать не смогу, если конечно вообще смогу на том уровне что надо, но очень бы хотелось попробывать...
     
  13. Sergey89

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

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Почему наследования не будет?
     
  14. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Реальных задач требующих наследования в ORM не возникало.
    Кроме того всегда можно самому сделать "базовый" класс членом: получаем все фишки множественного наследования + меньшее связывание. (наследование в ORM так и реализуется)
    Если оно понадобится не сложно будет его реализовать.
     
  15. kostyl

    kostyl Guest

    Да, наследование сильно-слабая вещь ООП, лучше членом делать... Но вот многие-ко многим я бы хотел иметь...
     
  16. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Мы делали в прошлой версии многие-ко-многим. Но от этого были одни проблемы и не однозначности т.к. связующая таблица не представленна явно, следовательно, сложно с ней оперировать.
    Удобней использовать третий класс для связей многие-ко-многим.
     
  17. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Пришёл к выводу, что сочетание слов "небольшой размер" в употреблении к ORM это оксюморон. :)

    Я тут себе делал ORM (или AR, хз где разница у них). Желание было сделать небольшую надстройку над DbSimple с удобным интерфейсом. Лично для меня, удобство, помимо всего прочего, заключается в поведении одного и того же действия в зависимости от контекста. Вышло 42 КБ и не учитывая обращения к другим классам (собственно, к самому DbSimple и классу для работы с массивами).

    Не то чтобы я гений минимализма или ваще гений, но и не имбецил. За исключением некоторых глюков и пары нерешённых (философских: делать что-то или не делать :)) вопросов, вышло всё, как я хотел - в том числе и миниатюрно, и удобно, и пришпандорить можно почти к любой готовой структуре. Но очевидно, что 42 КБ на самом деле это не есть миниатюрность. Так же как очевидно, что выборка вроде $list->MyClass2->name это два "select *". Даже не джоин, блин.

    Могу в приват ссылку кинуть, если чё-нить захотца, то бери. Там лицензия LGPL (не нравятся мне BSD, MIT и иные подобные), но коли возмёшь, то сменю те "экспортные" куски под лицензию, которая будет у твоего кода (BSD).

    Нафигишкин? Посмотри на Criteria - какой она страшный штука. (Не описался, юморю.)

    И второй вопрос. У тебя есть $list->свойство = 'вака-вака' и $list->add() это разные вещи? Возможно, я несколько шизанулся в том плане, что считаю, что следует исходить из контекста, но всё же почему не:
    Код (Text):
    1. $list->'lastName' = array('type' => 'text', 'length' => 255);
    2. $list->alter();
    Или что-то подобное. По ходу иногда поля нужно не только добавлять, но и менять существующие. Возмёт кто-то твой ORM себе, встроит в движок (бсяшность этому способстует), а обновление движка придётся через попку делать. Штука же не редкая: люди косячат, люди ленятся вбивать нормальную длинну для полей в БД, люди забывают ставить индексы и т.д. и т.п. Ох, уж эти люди.
     
  18. Ti

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

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

    это решает жадная выбока

    да. Первое добавляет параметр в выборку, воторой добавляет поле в таблицу

    в моем случае это будет выглядеть так:
    Код (Text):
    1. <?
    2. ORM()->myClass->lastName->setType('text', 255);
     
  19. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Знаете, работал я тут в конторе, которая занимается созданием АСУ для клиентов. Контора старая, опытная, шишек понабивала просто тысячами себе уже. У них своя разработка, на базе котороё они делают все проекты. Ничего похожего в и-нете нету, ни халявного, ни платного (а система между тем весьма универсальна, и даже неплохо маштабируется и оптимизируется по необходимости, т.е. допиливается для производительности - это там предусмотренно). Так вот, там подобие ORM какраз есть. DataMapping используется. Обновляете объект, он потом обновляет всё в базе. Нужна выборка в 7 джойнов? Пожайлуста - там это делалось не тупым перебором в циклах, а они дошли до системы, где задавался шаблонный запрос и в итоге 7 модулей могли сделать 1 запрос и получить все данные для отоборажения. Да, конечно не всё было идиально и местами некоторые вещи делались через хаки (которые обуславливались тем, что это real time системы). Многое нельзя было сделать из-за ограниченности по версиям софта (проекты длятся по 1-2 года, некоторые по 5-6 лет и до сих пор идёт наращивание функционала).
    Мораль бастни такова, что без тесной взаимосвязи самого приложения с ORM не будет эффективного и быстрого механизма. Там он работал потому, что это было само приложение. Там event-driven система, модули - это по сути ORM прослойки, в которые по необходимости дописывались пользовательские события через хуки, а всё остальное делает сама система. Сделать модуль с редактированием, добавлением, удалением, JavaScript data list занимало до 2-х часов всего. С абсолютного нуля.

    Так что не занимайтесь чепухой. Либо вам нужно по сути спроектировать целую систему и далеко не в одиночку, либо взять готовое. А можно просто пользоваться SQL, сделать лёгкое абстрогирование и не мучать свои мозги, используя их силу для решения прикладных задачь.
     
  20. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Psih
    Твоя история абсолютно ничего не доказывает.
    Прошу писать по теме.
     
  21. А я наверно так никогда и не пойму, чем плох SQL...
     
  22. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Ti
    Она доказывает то, что ОРМ в отрыве от приложения это идиотизм, потому что PHP это не C/Java/etc, где нету такой сильной нагрузки на память и CPU в силу природы этих языков программирования и обсалютно другой логикой построения приложений и возможностях куда более широких чем в PHP.

    А вообще SQL есть SQL. ORM идёт лесом в любом более-менее нагруженном проекте, потому что вы явно будете использовать особенности базы данных и всёравно будете кормить ему SQL руками. В итоге "Нахера мне ОРМ, если я пишу запросы руками?! Выкину ка я эти лишние 100кб кода и будет работать быстрее.". Я это уже проходил, даже DBSimple щас ненужное излишество, от которого толку 0.
     
  23. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Psih
    Я твою позицию давно понял. Как ты еще на хардварный уровень не ушел? С твоей религией тот факт что ORM в 150 раз удобней SQL тоже идет лесом? О чем тут спорить?

    Недавно я поменял работу. Сейчас приходится писать SQL. Я так, простите за мой французкий, заебался. Хочу ORM. Пока не реализую написанное выше, моя душа не будет спокойна.

    Еще раз прошу не офтопить. Нужнен ORM миру или не нужен прошу обсуждать в другом треде.
     
  24. Shasoft

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

    С нами с:
    18 май 2009
    Сообщения:
    1
    Симпатии:
    0
    Вопрос: Правильно ли я понимаю, что каждый метод из данного примера
    PHP:
    1. ORM()->MyClass->like('name', '%waka%')->set('name', 'waka waka')->update();
    возвращает массив объектов? Т.е. реализация аналогичная jquery?

    И если да, то верно ли, что каждый метод -- это один запрос в БД?
     
  25. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    Возращает Iterator объектов.

    Запрос выполняется "по первому требовнию"

    ORM() возращает коллекцию классов (Iterator)
    ORM()->MyClass коллекция объектов MyClass (Iterator)
    ->like('name', '%waka%') добавляет условие
    >set('name', 'waka waka') устанавливает значение
    update() - выполняет запрос UPDATE

    один запрос.


    PHP:
    1. foreach(ORM()->MyClass->like('name', '%waka%') as $myObject) ;
    один запрос (перед итерацией)
    [sql]SELECT * FROM my_class WHERE name LIKE '%waka%'[/sql]