Негласно: Как ORM “думает”?

Если Вы еще не собрали "мусор" свой репозиторий (например, использование git repack -d или git gc, но обратите внимание, что сборка "мусора" может также произойти автоматически), то Ваша фиксация все еще there †“, это больше не просто достижимо через ГОЛОВУ.

можно попытаться найти фиксацию путем просмотра вывода git fsck --lost-found.

Более новые версии Мерзавца имеют что-то позвонившее "повторно пороть", которое является журналом всех изменений, которые внесены в судей (в противоположность изменениям, которые внесены в содержание репозитория). Так, например, каждый раз Вы переключаете ГОЛОВУ (т.е. каждый раз, когда Вы делаете git checkout для переключения ответвлений), который будет зарегистрирован. И, конечно, Ваш git reset также управлял ГОЛОВОЙ, таким образом, это было также зарегистрировано. Можно получить доступ к более старым состояниям судей похожим способом, которым можно получить доступ к более старым состояниям репозитория, при помощи @ знак вместо ~, как git reset HEAD@{1}.

Это взяло меня некоторое время для понимания то, что различие между ГОЛОВОЙ {1} и HEAD~1, таким образом, вот немного объяснения:

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog

Так, HEAD~1 означает, "переходят к фиксации перед фиксацией, которые ВОЗГЛАВЛЯЮТ в настоящее время точки в", в то время как HEAD@{1} означает, "переходят к фиксации, которые НАПРАВЛЯЮТСЯ, указал, прежде чем это указало, где это в настоящее время указывает на".

, Который легко позволит Вам находить свою потерянную фиксацию и восстанавливать ее.

5
задан 3 revs, 2 users 100% 21 July 2009 в 17:54
поделиться

4 ответа

Связанные вызовы методов ортогональны вопросу ORM, они используются повсеместно в ООП. Цепной метод просто возвращает ссылку на текущий объект, позволяя вызвать возвращаемое значение. В PHP

class A {
    public function b() {
        ...
        return $this;
    }

    public function c($param) {
        ...
        return $this;
    }       
}


$foo = new A();
$foo->b()->c('one');
// chaining is equivilant to
// $foo = $foo->b();
// $foo = $foo->c();

есть два метода построения запросов. В ActiveRecord, как в ORM, есть код, который проверяет метаданные базы данных. В большинстве баз данных есть какие-то команды типа SQL или SQL для просмотра этих метаданных. (MySQL DESCRIBE TABLE , Oracle USER_TAB_COLUMNS таблица и т. Д.)

В некоторых ORM вы описываете свои таблицы базы данных на нейтральном языке, таком как YAML. Другие могут сделать вывод о структуре базы данных по тому, как вы создали свои объектные модели (я хочу сказать, что это делает Django, но я давно не смотрел на это). Наконец, есть гибридный подход, в котором используется любой из двух предыдущих методов, но предоставляется отдельный инструмент для автоматической генерации YAML / etc. или файлы классов.

Если имена и типы данных таблицы известны, довольно легко прагматично написать SQL-запрос, который возвращает все строки или определенный набор строк, отвечающих определенным критериям.

Что касается вашего последнего вопроса,

Как ORM управляет запросами, пока поддерживая произвольный характер всех что от него ожидается?

Я бы сказал, ответ «не очень хорошо». Как только вы выйдете за рамки метафоры «одна таблица - один объект», у каждой ORM будет свой подход и философия в отношении того, как следует использовать запросы SQL для моделирования объектов. В общем, это так же просто, как добавление новых методов, которые создают запросы на основе предположений ORM (например, метод «findManyToManyRowset» Zend_Db_Table)

3
ответ дан 14 December 2019 в 13:43
поделиться

Связанные аксессоры на самом деле не имеют большого значения: вы возвращаете $ this из метода установки. Бум, готово, работает на любом количестве уровней.

0
ответ дан 14 December 2019 в 13:43
поделиться

Я создал презентацию на тему создания PHP DataMapper, которая может быть вам интересна. Он был записан на видео в Oklahoma City Coworking Collaborative, когда я представил его группе пользователей PHP:

Видео: http://blip.tv/file/2249586/

Слайды презентации: http://www.slideshare.net/vlucas/building-data-mapper-php5-presentation

Презентация в основном была ранней концепцией phpDataMapper , хотя с тех пор многое изменилось.

Надеюсь, они помогут вам немного лучше понять внутреннюю работу ORM.

1
ответ дан 14 December 2019 в 13:43
поделиться

Как ORM удается реализовать такие функции, как связанные аксессоры, и насколько глубоки они обычно ожидаются работать?

Похоже, никто на это не ответил. Я могу быстро описать, как Doctrine делает это на PHP.

В Doctrine ни одно из полей, которые вы видите в объектной модели, фактически не определены для этого класса. Итак, в вашем примере, $ car-> owner, нет фактического поля под названием «владельцы», определенного в классе $ car.

Вместо этого ORM использует магические методы вроде __ get и __set .Поэтому, когда вы используете выражение типа $ car-> color, внутри PHP вызывает Doctrine_Record #__ get ('color').

На данный момент ORM может удовлетворить это в любом случае. Здесь очень много возможных дизайнов. Он может хранить эти значения в массиве, называемом, например, $ _values, а затем возвращать $ this -> _ values ​​['color']. В частности, Doctrine отслеживает не только значения для каждой записи, но и ее статус относительно сохранения в базе данных.

Один из примеров, который не является интуитивным, связан с отношениями Doctrine. Когда вы получаете ссылку на $ car, у нее есть связь с таблицей People, которая называется «владельцы». Таким образом, данные для владельцев $ car-> фактически хранятся в отдельной таблице от данных для самого $ car. Таким образом, у ORM есть два варианта:

  1. Каждый раз, когда вы загружаете $ user, ORM автоматически объединяет все связанные таблицы и помещает эту информацию в объект. Теперь, когда вы делаете $ car-> owner, эти данные уже есть. Однако этот метод медленный, потому что у объектов может быть много отношений, и эти отношения сами могут иметь отношения. Таким образом, вы добавляете много объединений и не обязательно даже используете эту информацию.
  2. Каждый раз, когда вы загружаете $ user, ORM замечает, какие поля загружаются из таблицы User, и заполняет их, но любые поля, загруженные из связанных таблиц, не загружаются. Вместо этого к этим полям прикрепляются некоторые метаданные, чтобы пометить их как «не загруженные, но доступные».Теперь, когда вы пишете выражение $ car-> owner, ORM видит, что отношение «владельцы» не загружено, и выдает отдельный запрос, чтобы получить эту информацию, добавить ее в объект и затем вернуть эти данные. Все это происходит прозрачно, и вам не нужно этого осознавать.

Конечно, Doctrine использует №2, поскольку №1 становится громоздким для любого реального производственного сайта с умеренной сложностью. Но у него также есть побочные эффекты. Если вы используете несколько отношений в $ car, то Doctrine будет загружать каждое из них отдельно, когда вы к нему обращаетесь. Таким образом, вы выполняете 5-6 запросов, хотя, возможно, требуется только 1.

Doctrine позволяет оптимизировать эту ситуацию, используя язык запросов Doctrine. Вы сообщаете DQL, что хотите загрузить объект автомобиля, но также присоединяете его к его владельцам, производителю, названиям, залоговым правам и т. Д., И он загружает все эти данные в объекты.

Уф! Длинный ответ. По сути, вы попали в самую суть вопроса: «Какова цель ORM?» и "Почему мы должны его использовать?" ORM позволяет нам продолжать думать в объектном режиме в большинстве случаев, но абстракция не идеальна, и утечки в абстракции, как правило, проявляются в виде снижения производительности.

2
ответ дан 14 December 2019 в 13:43
поделиться
Другие вопросы по тегам:

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