Ta odpowiedź została przepisana.
Większość odwzorowań danych działa, reprezentując jeden obiekt na klasę lub "model" jest zwykle uformowanym terminem. Jeśli chcesz zezwolić na wiele akcesji za pośrednictwem pojedynczego obiektu (tj. $model->find()
), jest on zwykle demagowany, aby metoda nie zwracała samej instancji, a zamiast niej tablicy MongoCursor
żądnej ładowania klas w przestrzeń.
Taki paradygmat jest zwykle połączony z "Aktywnym zapisem". Jest to metoda, z której korzystają ORMy, ODM i frameworki w celu komunikacji z bazami danych w taki czy inny sposób, nie tylko w MongoDB, ale także w przypadku SQL i innych baz danych (Cassandra, CouchDB itp.).
Należy od razu zauważyć, że nawet jeśli aktywny rekord daje dużą moc, nie powinien być pokryty całą aplikacją. Są chwile, w których bezpośrednie korzystanie z sterownika byłoby bardziej korzystne. Większość ORMów, ODMów i frameworków zapewnia możliwość szybkiego i bezproblemowego dostępu bezpośrednio do sterownika z tego powodu.
Istnieje, jak można by rzec, brak mapera danych o niewielkiej wadze. Jeśli zamierzasz zamapować zwrócone dane na klasy, to zużyje zasoby, koniec. Zaletą tego jest moc, jaką otrzymujesz podczas manipulowania swoimi obiektami.
Rekord aktywny jest naprawdę dobry w dostarczaniu zdarzeń i wyzwalaczy z poziomu PHP.Dobrym przykładem jest ORM zrobiłem dla Yii: https://github.com/Sammaye/MongoYii może ona dostarczyć haki do:
afterConstruct
beforeFind
afterFind
beforeValidate
afterValidate
beforeSave
afterSave
Należy zauważyć, że jeśli chodzi o wydarzenia, takie jak beforeSave
i afterSave
MongoDB nie posiada wyzwalaczy (https://jira.mongodb.org/browse/SERVER-124), więc ma to sens, że aplikacja powinna zająć. Oprócz oczywistego powodu, dla którego aplikacja radzi sobie z tym zadaniem, znacznie lepiej radzi sobie z funkcjami składowania, ponieważ może wywoływać twoje natywne funkcje PHP, aby manipulować każdym dokumentem zapisanym przed dotknięciem bazy danych.
Większość odwzorowań danych działa przy użyciu własnej klasy CRUD w PHP, aby reprezentować ich również. Na przykład, aby utworzyć nowy rekord:
$d=new User();
$d->username='sammaye';
$d->save();
Jest to dość dobre podejście skoro stworzyć „nowe” (https://github.com/Sammaye/MongoYii/blob/master/EMongoDocument.php#L46 pokazuje, jak przygotować się do nowego rekordu w MongoYii) klasę, aby „nowy” rekord. Jest to rodzaj dość ładnie semantycznie.
Funkcje aktualizacji są zwykle dostępne poprzez funkcje odczytu, nie można aktualizować modelu, o którym nie wiesz. Prowadzi nas to do kolejnego etapu zapełniania modeli.
Aby obsłużyć zapełnianie modelu różnych ORMów, ODM i frameworki zatwierdzają różne metody. Na przykład moje rozszerzenie MongoYii używa fabrycznej metody o nazwie model
w każdej klasie, aby przywrócić nową instancję samego siebie, dzięki czemu mogę nazwać dynamiczne find
i findOne
i inne podobne metody.
Niektóre ORMy, ODM i frameworki udostępniają funkcje odczytu jako bezpośrednie funkcje static
, czyniąc je własnymi metodami fabrycznymi, podczas gdy niektóre używają wzorca singleton, jednak nie wybrałem (https://stackoverflow.com/a/4596323/383478).
Większość, jeśli nie wszystkie, zaimplementować jakąś formę kursora. Służy do zwracania wielokrotności modeli i bezpośrednio owija (zwykle) MongoCursor
, aby zastąpić metodę current()
, zwracając wstępnie wypełniony model.
Na przykład wywołanie:
User::model()->find();
zwróci EMongoCursor
(w MongoYii), które następnie sotre fakt, że klasa User
został użyty do wystąpienia kursor i po nazwie jak:
foreach(User::model() as $k=>$v){
var_dump($v);
}
Wywołanie metody current()
tutaj: https://github.com/Sammaye/MongoYii/blob/master/EMongoCursor.php#L102 zwrócenie nowej pojedynczej instancji modelu.
Istnieje kilka ORMów, ODMów i frameworków, które implementują szybkie ładowanie macierzy.Oznacza to, że po prostu załadują cały wynik prosto do pamięci RAM jako zestaw modeli. Osobiście nie podoba mi się to podejście, jest marnotrawstwem, a także nie wróży dobrze, gdy trzeba użyć rekordu aktywnego w przypadku większych aktualizacji z powodu dodania nowych funkcji w miejscach, które wymagają dodania do starych rekordów.
Jednym z ostatnich tematów, zanim przejdę dalej, jest bezzasadna natura MongoDB. Problem z używaniem klas PHP w MongoDB polega na tym, że chcesz mieć wszystkie funkcje PHP, ale ze zmienną naturą MongoDB. Łatwo to przekroczyć w SQL, ponieważ ma predefiniowany schemat, po prostu zapytanie o to i wykonane zadania; jednak MongoDB nie ma czegoś takiego.
To sprawia, że obsługa schematów w MongoDB jest dość niebezpieczna. Większość ORM, ODM i frameworków wymaga wcześniejszego zdefiniowania schematu w miejscu (to jest Doctrine 2) przy użyciu zmiennych private
przy pomocy metod get
i set
. W MongoYii, aby moje życie stało się łatwe i eleganckie, postanowiłem zachować naturę bezochronną MongoDB za pomocą magii, która wykrywa (https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L26 jest moją __get
i https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L47 jest moją __set
), jeśli właściwość była niedostępna w klasie, jeśli pole było w polu wewnętrzna tablica _attributes
, a jeśli nie, to po prostu zwróć null
. Podobnie, dla ustawienia atrybutu ustawiłbym po prostu zmienną intrernal _attributes
.
Co do czynienia z jak przypisać ten schemat zostawiłem zadanie wewnętrznego września użytkownikowi jednak do czynienia z ustawienie właściwości z form itp użyłem zasady walidacji (https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L236) wywołanie funkcji o nazwie getSafeAttributeNames()
która zwraca listę atrybutów który miał zasady walidacji przeciwko nim. Jeśli nie mają reguł sprawdzania poprawności, te atrybuty, które istniały w przychodzącej tablicy $_POST
lub $_GET
, nie zostaną ustawione. Dało to możliwość stworzenia schematu, a jednocześnie bezpiecznej struktury modelu.
Tak więc omówiliśmy, jak właściwie używać dokumentu głównego, a także zapytać, w jaki sposób program odwzorowujący dane obsługuje pod-dokumenty. Doctrine 2 i wiele innych udostępnia dokumenty subdomenowe oparte na pełnej klasy (http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/embedded-mapping.html), ale może to być niezwykle zaradne. Zamiast tego zdecydowałem, że udostępnię funkcje pomocnicze, które pozwolą na elastyczne wykorzystanie poddokumentów bez chęci załadowania ich do modeli i tak pochłaniającej pamięci RAM. Zasadniczo to, co zrobiłem, to pozostawić je, ponieważ zapewniają walidację (https://github.com/Sammaye/MongoYii/blob/master/validators/ESubdocumentValidator.php) do sprawdzania poprawności wewnątrz nich. Oczywiście walidator sam się odradza, więc jeśli miałbyś regułę w walidatorze, która używałaby walidatora ponownie do wydania walidacji zagnieżdżonego poddokumentu, to działałoby.
Więc myślę, że, która kończy bardzo podstawową dyskusję na temat ORM-ów, ODM-ów i frameworków, używają maperów danych. Oczywiście prawdopodobnie mógłbym napisać cały esej na ten temat, ale jest to wystarczająco dobra dyskusja na minutę, w którą wierzę.
Jeśli wyjaśnisz więcej o tym, jakiego rodzaju odpowiedzi chcesz, możemy prawdopodobnie zapewnić, to znaczy, że nie chcesz tego napisać, czego chcesz? – Sammaye
Przedstawiono mi bardzo konstruktywne i użyteczne podejście, a ja już nauczyłem się wiele o waszej technice i wdrożeniu. Dziękuję za to! Ponadto, jestem otwarty na wszelkie inne podejście, które istnieje, jestem gotów to zobaczyć, jeśli istnieje. Próbuję zbadać wszystkie możliwości i wzorce tego problemu. – Dyin