QueryBuilder

From A-Eskwiki
Jump to: navigation, search

Om SQL-queries makkelijker te maken heeft de WebCie haar eigen sql-library geschreven, de QueryBuilder. De QueryBuilder maakt queries op dmv van een QueryBuilder-object waaraan properties veranderd worden. Op die manier wordt de query pas gebouwd als de query uitgevoerd moet worden. Hierdoor is er meer mogelijkheid voor controle en sanity checks.

De QueryBuilder bestaat uit de Query-klasse, de QueryBuilder-klasse en alle uitbreidingen. De Query-klasse is een extensie van de QueryBuilder-klasse. Het verschil tussen de twee klasses is dat de QueryBuilder-klasse wordt gebruikt om de query op te bouwen en de Query-klasse wordt gebruikt om van het geheel een werkende query te maken, alsmede verschillende functies zoals het verzamelen van objecten te implementeren.

QueryBuilder starten

Omdat je een query altijd wilt gebruiken voor WhosWho4-objecten heeft elk WhosWho4-object zijn eigen query-classe die een uitbreiding is van de Query-klasse. Zo heb je bv de PersoonQuery-klasse en de LidQuery-klasse. Deze extensies hebben niet hun eigen speciale constructor. in plaats daarvan heeft elk van deze klassen de methode table waarmee een Query-klasse wordt aangemaakt, het object als table bij de query wordt gezet en het ObjectQuery-object wordt gereturnd zodat er meteen methoden op kunnen worden toegepast. Voor uitgebreide klasse zoals Persoon en Lid worden automatisch de onderliggende klassen gejoind zodat je dit niet zelf hoeft te doen en bij deze data kan. Een voorbeeld:

  1. $query = PersoonQuery::table();

Query uitvoeren

Een query kan je uitvoeren met de methode get. get heeft geen argumenten nodig. Als je verder niets aan je Query-object hebt toegevoegd selecteert de query automatisch alle objecten in de table. Met het volgende voorbeeld worden alle entries uit de Persoon-table opgevraagd:

  1. $personen = PersoonQuery::table()->get();

first

De methode first voert de query uit zoals get dat doet en geeft vervolgens alleen het eerste resultaat terug. Met het volgende voorbeeld wordt de eerste entry uit de Persoon-table opgehaald:

  1. $personen = PersoonQuery::table()->first();

aggregate (TODO: in de php-code moet deze functie nog worden aangepast)

De methode aggregate voert een aggregator uit op de query. De toegestane aggregators zijn: COUNT, SUM, MAX, MIN en YEAR. De aggregator pakt op dit moment nog alles ipv een specifieke kolom. aggregate haalt ook de huidige selectie weg. Een voorbeeld om alle entries in de Persoon-table te tellen:

  1. $aantal_personen = PersoonQuery::table()->aggregate('COUNT');

count

Om makkelijker entries te tellen is de speciale methode count. Deze methode telt het aantal entries en haalt ook de orderBys, limits en offset van de query weg.

  1. $aantal_personen = PersoonQuery::table()->count();

verzamel

De methode die het vaakst gebruikt wordt is verzamel. Net zoals verzamel van elke Verzameling van een WhosWho4-object verzamelt deze query-methode alle WhosWho4-objecten die met de query opgehaald worden. Hierbij verdwijnen alle huidige selects van de query. De methode kan twee argumenten krijgen: de naam van de klasse om de objecten van te verzamelen as string en of de objecten distinct moeten zijn als bool. Zonder argumenten is distinct true en worden de objecten opgehaald van de klasse waarvan je het query-object gemaakt hebt. Als voorbeeld, haal alle Persoon-objecten op:

  1. $persoon_objecten = PersoonQuery::table()->verzamel();

Haal alle distinct bugmelders op (dit voorbeeld gebruikt ook join):

  1. $persoon_objecten = BugQuery::table()
  2.         ->join('Persoon')
  3.         ->verzamel('Persoon', true);

geef

Net zoals de methode geef voor objecten heeft de QueryBuilder een soortgelijke methode. De methode geeft een object terug die wordt opgevraagd dmv de query. Net als bij verzamel heeft de methode een argument voor het soort object wat je op wilt halen. Geef het lid-object met ID 5794

  1. $persoon = PersoonQuery::table()
  2.         ->whereInt('contactID', 5794)
  3.         ->geef();

Joins

De QueryBuilder heeft uiteraard ook de mogelijkheid om joins uit te voeren op tables. Nieuwe tabellen worden automatisch op de juiste velden gejoind, dus dit hoef je niet meer zelf te doen. Mocht de QueryBuilder het toch niet zelf kunnen, dan hebben de join-methoden extra argumenten nodig voor het joinen.

(left) join

De standaard join is een left join. Je hoeft als enige argument de table mee te geven om op te joinen. Zo kan je bv de table Persoon joinen met Bug

  1. $query = BugQuery::table()->join('Persoon');

Als het echt nodig is kan je zelf de twee namen van de kolommen meegeven waarop gejoined moet worden

  1. $query = BugQuery::table()->join('Persoon', 'Bug.melder_contactID', 'Persoon.contactID');

Je kan ook ipv een string als naam voor de table bij je join een array plaatsen met als key een string en als value je tablename. De key wordt dan de AS in de query. Dus om in bovenstaand voorbeelde de table Persoon AS p te joinen

  1. $query = BugQuery::table()->join(array('p' => 'Persoon'));

rightJoin

De rightJoin werkt hetzelfde als join alleen voert het een right join uit ipv een left join.

  1. $query = BugQuery::table()->rightJoin('Persoon');

innerJoin

De innerJoin werkt ook hetzelfde als join alleen voert het een inner join uit ipv een left join.

  1. $query = BugQuery::table()->innerJoin('Persoon');

fullJoin

De fullJoin werkt ook hetzelfde als join alleen voert het een full join uit ipv een left join.

  1. $query = BugQuery::table()->fullJoin('Persoon');

Where

Uiteraard heeft een query ook where's nodig. Daarom heeft de QueryBuilder verschillende methoden om where toe te voegen.

whereProp

De belangrijkste where-methode is whereProp. Met deze methode wordt de where automatisch uitgevoerd op een eigenschap van de objecten waarvan de tables in de query zitten (met from of dmv een join). Hiervoor is het ook nodig dat waarmee je wilt matchen in je where van het juiste type is. Zo is een ID een int en wil je daar dus geen string voor meegeven. De whereProp zoekt ook automatisch de table waarbij de property hoort. Als er meerdere mogelijkheden zijn kan je er altijd 'tablename.' voor zetten, net zoals met normale sql.

Je kan whereProp twee of drie argumenten meegeven. Als je twee argumenten meegeeft wordt er een match op gelijkheid aan je query toegevoegd. Hierbij is het eerste argument welke property je wilt matchen en je tweede argument waarmee gematcht wordt. Selecteer alle Bugs met melder $melder ($melder moet een Persoonobject zijn)

  1. $bugs = BugQuery::table()->whereProp('melder', $melder)->verzamel();

Als je drie argumenten meegeeft is het eerste argument nog steeds welke property je wilt matchen, je tweede argument is je operator en je derde argument is waarmee gematcht wordt. De mogelijkheden voor de operatoren zijn Selecteer alle Bugs waarvan melder niet $melder is ($melder moet een Persoonobject zijn)

  1. $bugs = BugQuery::table()->whereProp('melder', '!=', $melder)->verzamel();

whereProp varianten

Met de standaard whereProp kan je alleen een paar operatoren toevoegen aan je where. Daarom zijn er de methoden whereNotProp, whereLikeProp, whereNotLikeProp, whereInProp en whereNotInProp. Wat deze methoden doen zit in de naam van de methoden. Voor de whereLikeProp en whereNotLikeProp heb je twee argumenten nodig, als eerste de property en als tweede de string. Voor de methoden whereInProp en whereNotInProp heb je ook twee argumenten nodig, de property en als tweede de array waar de property in moet zitten. Haal alle bugs op waarbij het email de string 'pepijno' bevat

  1. $bugs = BugQuery::table()->whereLikeProp('melderEmail', '%pepijno%')->verzamel();

OR ipv AND

Als je meerdere whereProp-methoden hebt worden ze in de WHERE automatisch aan elkaar geplakt met het AND keyword. Om ze met OR aan elkaar te plakken gebruik je de methode orWhereProp. Voor alle andere soorten whereProp-methode kan je op dezelfde manier de or voor de methodenaam plakken en dan worden de where-clausules met OR aan elkaar geplakt.

Overige where-methoden

Als je een WHERE-clausule wilt gebruiken kan je ipv whereProp ook standaard where-methoden gebruiken. Deze gebruik je op dezelfde manier als whereProp-methoden, behalve dat je de Prop moet vervangen door het type van de value die je in je WHERE wilt gebruiken. Als je bv wilt kijken of een ID gelijk is aan een int, moet je whereInt gebruiken. Haal alle Bugs op met melder_contactID gelijk aan 5794 (hier kan je als het lid-object van lidnr 5794 hebt ook whereProp gebruiken)

  1. $bugs = BugQuery::table()->whereInt('melder_contactID', 5794)->verzamel();

Naast deze standaard where-methode heb je ook de self explainatory methoden whereNot, whereIn, whereNotIn, whereLike, whereNotLike, whereNull en whereNotNull. Let op dat je dus ook bij deze methoden het type van de value bij de methode naam moet zetten! Ook al deze methode kan je met een OR lijmen door or voor de methodenaam te zetten zoals bv bij orWhereProp.

Nested where's & Closures

Stel, je wilt de volgende WHERE-clausule:

WHERE (a = 0 OR a = 1) AND (a = 2 OR a = 3)

Dit krijg je in de QueryBuilder dmv Closures in php. De bovenstaande where-prop krijg je als volgt

  1. ...->where(function($q) use ($var1, $var2) {
  2.         $q->whereInt('a', 0)
  3.           ->orWhereInt('a', 1);
  4.     })->where(function($q) {
  5.         $q->whereInt('a', 2)
  6.           ->orWhereInt('a', 3);
  7.     })

In een where kan je dus een closure gebruiken om nested where's te krijgen.

Selects

Om selects toe te voegen aan je query gebruik je de methode select. Elk argument wat je aan de methode meegeeft wordt als select toegevoegd. Ipv de argumenten als strings mee te geven kan je ook een array toevoegen met een string als key en de select als value. Dan wordt de key de AS van de select. Om alle contactID's te selecteren van de Persoontable

  1. $ids = PersoonQuery::table()->select('contactID')->get();

Om alle contactID's als 'ID' en alle voornamen te selecteren van de Persoontable

  1. $ids = PersoonQuery::table()->select(array('ID' => 'contactID'), 'voornaam')->get();

Om selects distinct te maken kan je de methode selectDistinct gebruiken.

Order by

Order by's can de QueryBuilder ook aan. Er zijn twee methoden orderByAsc en orderByDesc. Allebei de methoden hebben slechts 1 argument nodig, de kolom om de order op uit te voeren. Selecteer alle Personen geordered op contactID

  1. $personen = PersoonQuery::table()->orderByAsc('contactID')->verzamel();

Limit & offset

Om de limit en offset van een query te bepalen zijn er de twee methoden offset en limit. Beide methoden hebben 1 argument nodig, de offset of limit respectivelijk. Selecteer de personen 200 t/m 300

  1. $personen = PersoonQuery::table()->limit(100)->offset(200)->verzamel();

Havings

Havings werken op dezelfde manier als alle where-methoden, zowel de standaard having als de standaard havingProp. De namen van de methoden zijn precies hetzelfde als de where-methoden, alleen is elke where vervangen door having.