Если Вы еще не собрали "мусор" свой репозиторий (например, использование 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}
означает, "переходят к фиксации, которые НАПРАВЛЯЮТСЯ, указал, прежде чем это указало, где это в настоящее время указывает на".
, Который легко позволит Вам находить свою потерянную фиксацию и восстанавливать ее.
Связанные вызовы методов ортогональны вопросу 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)
Связанные аксессоры на самом деле не имеют большого значения: вы возвращаете $ this
из метода установки. Бум, готово, работает на любом количестве уровней.
Я создал презентацию на тему создания PHP DataMapper, которая может быть вам интересна. Он был записан на видео в Oklahoma City Coworking Collaborative, когда я представил его группе пользователей PHP:
Видео: http://blip.tv/file/2249586/
Слайды презентации: http://www.slideshare.net/vlucas/building-data-mapper-php5-presentation
Презентация в основном была ранней концепцией phpDataMapper , хотя с тех пор многое изменилось.
Надеюсь, они помогут вам немного лучше понять внутреннюю работу ORM.
Как 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 есть два варианта:
Конечно, Doctrine использует №2, поскольку №1 становится громоздким для любого реального производственного сайта с умеренной сложностью. Но у него также есть побочные эффекты. Если вы используете несколько отношений в $ car, то Doctrine будет загружать каждое из них отдельно, когда вы к нему обращаетесь. Таким образом, вы выполняете 5-6 запросов, хотя, возможно, требуется только 1.
Doctrine позволяет оптимизировать эту ситуацию, используя язык запросов Doctrine. Вы сообщаете DQL, что хотите загрузить объект автомобиля, но также присоединяете его к его владельцам, производителю, названиям, залоговым правам и т. Д., И он загружает все эти данные в объекты.
Уф! Длинный ответ. По сути, вы попали в самую суть вопроса: «Какова цель ORM?» и "Почему мы должны его использовать?" ORM позволяет нам продолжать думать в объектном режиме в большинстве случаев, но абстракция не идеальна, и утечки в абстракции, как правило, проявляются в виде снижения производительности.