ORM orientat spre domeniu, creat cu pasiune pentru PHP 5.4+.

Penumbra nu este terminata, fundatia si arhitectura sunt acolo, dar baza de cod nu are aproape niciun test de unitate. Deoarece penumbra a fost initial un exercitiu de invatare cu scopul de a crea un orm care nu influenteaza modelul domeniului, acest proiect a pastrat o calitate buna a codului, dar devine rapid evident ca nu pot sa dezvolt si sa mentin singur acest proiect, mai ales cu scoala. Sunt necesari colaboratori seriosi, va rugam sa nu ezitati sa clonati depozitul si sa priviti in jurul bazei de cod, daca aveti intrebari, intrebari sau doriti sa incepeti sa contribuiti, va rugam sa ma trimiteti un e-mail la: [email protected].

Va rugam sa fiti constienti de faptul ca acesta este primul meu proiect open source mare, asa ca orice sfaturi / recomandari sunt binevenite.

Da! Penumbra ofera functii pe care niciun alt ORM nu le are. Penumbra este 100% mapograf de date si isi propune sa ramana complet decuplat de modelele de domeniu, oferind in acelasi timp o interfata de interogare puternica in limbaj.

  • Functionalitatea ORM ruleaza, dar departe de a fi stabila.
  • In general, mentine o calitate buna a codului.
  • Este nevoie de multa munca doar pentru a infiinta.
  • Baza de cod de dimensiuni decente (~ 15.000 LOC).
  • Structura API nu este finalizata.
  • Suita de teste ingrozitoare.
  • Lipsa comentariilor de documentare / cod.
  • Sunt necesare colaboratori seriosi.
  • Pentru a oferi o abordare mentinuta si sensibila la domeniul complex ORM.
  • Pentru a recompensa utilizatorul cu modele de domeniu nepoluate si flexibile.
  • Pentru a oferi o interogare fluenta integrata in limbaj (similar cu LINQ al lui C #)
  • Pentru a reduce cantitatea de interogari catre platforma de baza si pentru a ajuta la eliminarea interogarilor n + 1.

Penumbra isi propune sa ofere o restrictie cat mai mica modelelor de domeniu

  • Interogati in functie de domeniu, nu de baza de date.
  • Abstrati-va din baza de date de baza.
  • Mentineti completarea automata IDE completa.
  • Eliminati hassle de siruri magice si preveniti injectia SQL.
  • API de agregare puternic, Numar, Maxim, Minim, Mediu, Suma, Implod, Toate, Orice
  • Accepta variabilele utilizate pentru functia de interogari parametrizate ($ _) utilizarea ($ Value) {…
  • Suporta campuri dinamice, apeluri de metode, apeluri de functii etc.
  • Chiar si accepta proprietati de relatie pentru imbinari fara sudura!

Cerere de entitate (SELECT) – Exemplu:

$ MiddleAgedUsersRequest = $ UserRepository-> Request () -> Where (function (User $ User) {return $ User-> GetAge ()> 20 && $ User-> GetAge () <50;}) -> OrderByDescending (function ( Utilizator $ Utilizator) {return $ Utilizator-> GetLastLoginDate ();}); $ SomeActiveMiddleAgedUsers = $ MiddleAgedUsersRequest-> AsArray ();

Va mapa la ceva de-a lungul liniei:

SELECTATI Utilizatorii. * DE LA UTILIZATORII UNDE Users.Age> 20 AND Users.Age <50 ORDER BY Users.LastLoginDate DESC;

Cerere de date complexe (SELECT) – Exemplu:

$ UserStatistics = $ UserRepository-> Request () -> From ($ MiddleAgedUsersRequest) -> Where (functie (User $ User) {return $ User-> IsActive ();}) -> GroupBy (function (User $ User) { returneaza $ User-> GetAge ();}) -> Select (functie (User $ User, IAggregate $ Users) {return [‘Age’ => $ User-> GetAge (), ‘Amount’ => $ Users-> Count (), ‘AverageVisits’ => $ Users-> Average (functie (User $ User) {return $ User-> GetVisitsPerDay ();})),]; });

Va mapa la ceva de-a lungul liniei:

SELECTATI Utilizatorii.Varsta AS Varsta, COUNT (*) AS Cantitatea, AVG (Users.VisitsPerDay) AS AverageVisits FROM (SELECT Users. * FROM Users WHERE Users.Age> 20 AND Users.Age <50 ORDER BY Users.LastLoginDate DESC) AS Utilizatori UNDE Users.IsActive GROUP BY Users.Age;

Proceduri (ACTUALIZARE) – Exemplu:

$ InactiveUserProcedure = $ UserRepository-> Procedura (functie (User $ User) {$ User-> SetIsActive (false); $ User-> SetInactivationDate (new DateTime ());}) -> Where (functie (User $ User) { returneaza $ User-> GetLastLoginDate () <(new DateTime ()) -> sub (new DateInterval (‘P2Y’));}); $ InactiveUserProcedure-> Execute ();

Va mapa la ceva de-a lungul liniei:

UPDATE Users SET Users.IsActive = 0, Users.InactivationDate = ACUM () UNDE Users.LastLoginDate <DATE_SUB (ACUM (), INTERVAL 2 YEAR)

NOTA: Functiile furnizate nu au fost niciodata executate, sunt analizate si apoi mapate pe platforma subiacenta ca interogari.

Un obiectiv principal al Penumbra este de a profita cat mai mult de baza de date de baza.

  • Penumbra va utiliza insertii / up-ups in serie si sterge acolo unde este posibil.
  • Eliminarea temutului scenariu de interogare N + 1 introdus de incarcarea lenesa excesiva. Cu penumbra, exista curent mai multe implementari de incarcare a relatiei:
    • Dornic – Relatiile sunt incarcate impreuna cu parintele si copiii sunt uniti acolo unde este cazul.
    • Domeniu de aplicare global lenes – Relatiile nu sunt incarcate cu entitatea parinte, dar atunci cand este necesara una, la nivel global, fiecare relatie descarcata va fi incarcata.
    • Domeniul solicitarii lenes (recomandat) – Relatiile sunt incarcate atunci cand este necesar pentru toate entitatile din graficul obiectului cererii.
    • Domeniul de aplicare parinte lenes (N + 1 probabil) – Relatiile sunt incarcate atunci cand este necesar pentru fiecare entitate parinte.

Exemplu:

Utilizatorul este entitatea parinte, un utilizator are multe postari si o postare are un autor si multe etichete. Iata scenariul tipic N + 1.

$ User = $ UserRepository-> LoadById (1); foreach ($ User-> GetPosts () ca $ Post) {$ Post-> GetAuthor () -> GetFullName (); foreach ($ Post-> GetTags () ca $ Tag) {$ Tag-> GetName (); }}

Iata acum numarul de interogari executate pentru fiecare mod de incarcare (N = Numarul de mesaje);

  • Eager – 3 (utilizatorul | postarile s-au alaturat autorului | toate etichetele), cand utilizatorul este incarcat.
  • Sfera globala lenesa – Pentru incarcarea unei singure solicitari, aceasta este echivalenta cu Modul lentei sferei cererii de mai jos.
  • Solicitati sfera lenes – 4 (utilizatorul | postari | toti autorii | toate etichetele), postarile vor fi incarcate atunci cand sunt iterate si toate etichetele vor fi incarcate cand este iterata prima data.
  • Domeniul de aplicare parinte lenes – (N * 2) + 2 – (utilizator | mesaje | fiecare post de autor | fiecare post de tag – uri).

NOTA: Modul de incarcare a relatiei este per-relatie, exemplul de mai sus presupune ca fiecare relatie va avea acelasi mod de incarcare pentru simplitate.