# Yii - 2021
# Inleiding
In *deze les gaan we leren wat een framework is en waarom we Yii gaan leren.*
*We leren verder wat MVC en CRUD is en wat heeft dat te maken heeft met een framework.*
Op het examen, kerntaak 2 moet je een webapplicatie bouwen.
Je moet zelf weten hoe je dat doet. De meeste studenten kiezen voor PHP. Waarom? Het is relatief eenvoudig en de meeste web applicaties zijn ontwikkeld met PHP ([bron](https://w3techs.com/)).
Veel websites lijken op elkaar en doen vaak dezelfde dingen. Ze maken een verbinding naar de database, laten gegevens zien, je kunt aanloggen, je kunt soms gegevens veranderen en ga zo maar door.
Om niet telkens al deze 'standaard' zaken van 'scratch' af aan te moeten bouwen zijn er zogenaamde frameworks ontwikkeld. Elk framework is eigenlijk veen verzamelingen bouwblokken die je telkens op nieuw kunt gebruiken voor jouw website. Alle frameworks zijn net een beetje anders, maar er zijn ook veel overeenkomsten.
Wat zijn belangrijke zaken als je voor een framework kiest:
1. Wordt het framework actief onderhouden; bestaat het al wat langer? Je wilt niet in iets gaan investeren dat volgend jaar misschien niet meer bestaat.
2. Hoe moeilijk is het om een framework te leren; wat is de complexiteit?
3. Hoe snel kun je iets ontwikkelen met het framework?
4. Hoe flexibel is een framework; kun je er echt alles mee maken?
Bij punt 3 en 4 is het vaak het een of het ander. Of je kunt heel snel iets bouwen en je bent niet zo flexibel, of je kunt er eigenlijk alles mee ontwikkelen maar het kost veel tijd om dat te doen.
Bijvoorbeeld: PHP is super flexibel je kunt er echt alle mee ontwikkelen, het Laravel framework is ook redelijk flexibel, het Yii framework is iets minder flexibel en als je naar bijvoorbeeld WordPress kijkt (wat je ook als een soort framework zou kunnen zien), dan is dat het minst flexibel. Aan de andere kant kun je met WordPress heel snel een site maken, je bent alleen een beetje beperkt in de functionaliteiten.
#### Waarom Yii?
Laravel is het meest gebruikte PHP-framework. Yii staat in de meeste lijstjes ongeveer op plaats 7. Dat komt, omdat je weliswaar "snel even wat kan bouwen", maar je kunt het vrij lastig alles precies zo maken als jij het wilt. Het is minder flexibel, maar biedt wel veel structuur. Als je straks je examen maakt dan kun je waarschijnlijk ongeveer 70%-80% van je code maken met Yii, daarvoor hoef je heel weinig te programmeren en heb je tijd om je te storten op de overige 20%-30%. De examens die jullie gaan doen lenen zich goed om met Yii te maken. Je bent namelijk redelijk vrij in het ontwerp en kunt dus de 'Yii-manier' aanhouden.
Maar wat dan als ik later verder wil met (bijvoorbeeld) Laravel? Dat kan en Yii en Laravel hebben dezelfde opzet, MVC. Je zult in Laravel dus veel dingen terugvinden die je in Yii hebt geleerd.
#### MVC?
MVC, wat is dat? MVC staat voor Model, View en Control. Deze drie-deling wordt gemaakt in je code, zodat je eenvoudiger code kunt terugvinden.
Model
Hierin staat waar de verbinding tussen jouw code en de database beschreven
View
Dit is de front-end en is vooral HTML/CSS (bootstrap) met heir een daar een 'vleugje' PHP
Control
Dit is waar je bepaald wat er gebeurt, als je op een knop drukt ergens dan wordt de code uit de bijbehorende control uitgevoerd.
In een plaatje ziet dat er als volgt uit. De gebruiker doet wat en stuurt daarmee een verzoek (request) naar de juiste controller. De controller 'overlegt' met het model als er iets met data moet gebeuren en het resultaat wordt via de view aan de gebruiker getoond.
[](https://www.roc.ovh/uploads/images/gallery/2020-07/image-1594413597727.png)
In de komende lessen komen deze begrippen terug. Als het nu allemaal ngo wat onduidelijk is, geen probleem we gaan er mee aan de slag en zullen snel een gevoel krijgen wat MVC precies is en hoe het werkt.
#### CRUD?
Nog even....waar staat CRUD ook alweer voor? CRUD staat voor **C**reate, **R**ead, **U**pdate en **D**eleten. In een CRUD applicatie kun je dus gegevens aanmaken (create), lezen (read), bewerken (update) en verwijderen (delete).
In het examen (Kerntaak 2) moet je minimaal een CRUD kunnen maken.
Yii heeft een CRUD generator en je kan zonder te coderen een standaard CRUD applicatie maken. Super handig dus voor het examen. In de volgende les gaan we hier gelijk mee aan de slag.
### Opdrachten
##### Opdracht 1
Leg uit wat een ontwikkel framework is. Je mag hierbij gebruik maken van internet, maar beschrijf wel in je eigen woorden wat jij denkt dat een framework is.
Bespreek met elkaar waarom jij een framework zou willen leren?
Welke PHP frameworks ken je?
##### Opdracht 2
Als jij een framework kiest , wat is dan belangrijk voor jou?
Zet de volgende punten op volgorde van belangrijkheid (van meest belangrijk naar minder).
- Veel over te vinden (tutorials e.d.).
- Veel plugins voor beschikbaar.
- Wordt actief onderhouden, veel updates dus.
- Is makkelijk te leren, kun je makkelijk je exmaen mee halen.
- Kun je snel iets mee maken/ontwikkelen.
- Heeft heel veel mogelijkheden.
- Genereert automatisch code, die je dan kan aanpassen.
- Heeft veel ‘straight out of the box’, sorteren, selecteren, login, menu, etc.
- Is hip/modern/cool.
\--
# 1, De eerste web app
*In deze les gaan we alles klaarmaken en installeren voor het werken met Yii. Aan het eind van de les heb je werkende Yii CRUD-applicatie.*
Een CRUD-applicatie is een applicatie waarmee je records kunt aanmaken (Create), records kunt lezen (Read), records kunt aanpassen (Update) en records kunt verwijderen (Delete).
We gaan drie stappen doen om een werkende web app te maken:
1. installeren van alle software
2. maken van een eenvoudige database
3. generen van code
In drie stappen hebben we straks een *werkende* web app in PHP gemaakt.
Voordat je met deze les begint weet je hoe je met [phpMyAdmin](http://localhost/phpmyadmin/) (of ander tool) een database kunt maken en hoe je een .sql file kan importeren. Ook heb je XAMPP geïnstalleerd.
### Installatie
##### XAMPP
Je hebt [XAMPP](https://www.apachefriends.org/index.html) geïnstalleerd. Voor Yii hebben dit nodig, omdat we een database gaan gebruiken.
Heb je nog geen XAMPP of werkt die niet meer dan kun je [hier](https://www.roc.ovh/books/databases-voor-ict-beheer/page/xampp-installeren) lezen hoe je XAMPP kan installeren.
##### Composer
Zorg er voor dat je [composer](https://getcomposer.org/) hebt geïnstalleerd. Composer is de installer van de WEB tools.
Als we een framework als Yii of Laravel gaan gebruiken dan installeren we eigenlijk een hele grote doos met allemaal bouwblokken. Deze blokken moeten allemaal samen werken en zijn vaak afhankelijk van elkaar. De blokken worden door verschillende mensen ontwikkeld en op één of andere manier moet er voor worden gezorgd dat de juisten blokken zijn geïnstalleerd. Hiervoor dient Composer. Composer is als het ware de installer van PHP tools, deze worden vaak libraries of packages genoemd. Librabries zijn dan de blokken functionaliteit die je kunt gebruiken om een programma te maken.
[https://getcomposer.org/](https://getcomposer.org/)
Tip: Zorg dat XAMPP al in geïnstalleerd voordat je composer installeert; composer heeft namelijk de locatie van php.exe nodig.
In deze korte video wordt getoond hoe je Composer kunt installeren:
##### Create new yii Project
We maken het Yii project **world** aan.
Je hoeft niet zelf een map/folder aan te maken. Dit doet composer voor jou. Zorg ervoor dat je in de terminal in de parent-folder bent.
Vul de volgende code in de terminal:
```
composer create-project --prefer-dist yiisoft/yii2-app-basic world
```
Let op dat het nieuwe Yii project wordt gemaakt in de folder waarin je de cmd box opent. Stel je wilt je jouw nieuwe project op je Desktop maken dan open je een cmd box en je tikt het commando `cd Desktop` in. Voer dan het composer commando uit (zoals hierboven aangegeven) en het nieuwe Yii project zal op je Desktop worden gemaakt.
##### Start Development Server
yii heeft een ingebouwde php server als je die opstart dan draait jouw website op [http://localhost:8080/](http://localhost:8080/)
Let wel dat je XAMPP ook blijft draaien voor je database.
In VCS open je jouw Yii project en daarna open je een nieuwe terminal.
[](https://www.roc.ovh/uploads/images/gallery/2021-04/image-1618344180761.png)
In de terminal type je dan het commando in:
```
php yii serve
```
De Yii webserver draait nu. Ga naar je browser en controleer of op je via localhost:8080 jouw nieuwe Yii project ziet.
Wil je cmd box gebruiken of lukt dit niet. Kijk dan naar de [instructiefilm](https://youtu.be/5idkjTWIL7g).
##### Web.php
We moeten nu nog het een en ander configureren in Yii. We willen dat Yii zoveel mogelijk voor ons regelt. Om te beginnen mag Yii de routing regelen (dit wordt uitgelegd in de [volgende les](https://www.roc.ovh/books/yii/page/2-routing)).
Open **config/web.php** - en zet het gedeelte dat urlmanager heet, uit commentaar (uncomment prettyURL). Het moet er als voglt uitzien (ongeveer op regel 50 van config/web.php).
```
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
```
Dit is een instelling die de [routing](https://www.roc.ovh/books/yii/page/2-routing) (waarover later meer) eenvoudiger maakt.
##### Database
Let er op dat je **database goed is gedefinieerd** en dat je ook de relaties heb vastgelegd. Dat kun je doen met [phpMyAdmin](http://localhost/phpmyadmin/). De ingebouwde[ Yii CRUD-generator](http://localhost:8080/gii/crud) werkt alleen goed als de database en de relaties goed zijn vastgelegd.
Voor onze eerste Yii web-app gaan we gebruik maken van de world database. In [deze les](http://www.roc.ovh/books/databases-voor-ict-beheer/page/1-wat-is-een-database#bkmrk-world) staat beschreven hoe je deze database kunt installeren. In deze les staat de [SQL-file world.sql](https://www.roc.ovh/attachments/53) waarmee je de database World kan maken (klik op de link of kijk aan de linkerkant van deze pagina).
We gaan Yii vertellen welke database er moet worden gebruikt.
We openen de file **config/db.php** en zetten daar het volgende in:
```
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=world',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
];
```
Let op dat je geen localhost gebruikt om naar je database te verwijzen. Gebruik 127.0.0.1.
### Easy Debugging (optioneel)
Om straks eenvoudig te kunnen debuggen maken we een paar aanpassingen. Voor nu mag je dit ook even overslaan, we kunnen dit later ook nog doen.
Als je dit uitvoert dan kun je later in de code de volgende twee functies gebruiken:
`d($objectnaam)` bekijk $object de code loopt gewoon door.
`dd($objectnaam)` bekijk $object de uitvoering van de code stopt.
Hoe krijg je dit? Eenvoudig twee stappen.
Stap 1, New file config/functions.php
```PHP
';
echo 'File: '.$caller['file'].'';
echo '';
yii\helpers\VarDumper::dump($var, 10, true);
echo '';
}
/**
* Debug function with die() after
* dd($var);
*/
function dd($var)
{
$caller = debug_backtrace(1)[0];
d($var,$caller);
die();
}
```
Stap 2, Edit config/web.php - voeg regel 3 en 4 toe.
```
Klik links op 'Model Generator' en type de naam van de databasetabel **country** in:
[](https://www.roc.ovh/uploads/images/gallery/2020-07/image-1594285274135.png)
De naam van het model wordt automatisch aangemaakt **Country**. Let op dat de 'Model Class Name' met een **hoofdletter** begint; kijk goed naar het voorbeeld. De naam van een class (oop) wordt altijd met een hoofdletter geschreven.
Druk onderaan op de pagina op *preview*, Yii laat nu zien welke file hij gaan aanmaken voor je. Druk op **generate** om de file te maken.
De file **model/country** is nu aangemaakt, we gaan later meer in op de inhoud van deze file. Wat voor nu belangrijk is om te onthouden is dat de model/country.php file de verbinding is tussen de tabel country en Yii. Elke keer als Yii informatie uit de country tabel nodig heeft dan gebruikt Yii de model/country.php file
Omdat er vanuit de country tabel wordt verwezen naar de andere twee tabellen, **City** en **Countrylanguage** maak je nog twee modellen van deze twee tabellen.
In je model directory (folder) heb je nu dus de volgende files staan:
```
City.php
ContactForm.php
Country.php
Countrylanguage.php
LoginForm.php
User.php
```
##### 2. CRUD compleet maken met controllers en views
Ga terug naar de component builder, [open ](http://localhost:8080/gii)[http://localhost:8080/gii/model](http://localhost:8080/gii/model)
Klik links op 'CRUD Generator' en type het volgende in:
[](https://www.roc.ovh/uploads/images/gallery/2021-04/image-1618227641051.png)
Let goed op de hoofdletters, deze zijn belangrijk. Het View path wordt leeg gelaten, daar kan Yii zelf iets voor kiezen.
Druk op preview, je ziet 8 files die klaar staan om te worden aangemaakt.
[](https://www.roc.ovh/uploads/images/gallery/2021-04/image-1618227971123.png)
Druk op **generate** om de files aan te maken.
##### Controller
In de directory controllers staat een file CountryController.php. Dit is de controller van de country CRUD. Al het denkwerk dat nodig is om de country CRUD aan te sturen zit in de CountryController.php file.
##### View
In de views/country directory staan de views. De index.php is de standaard view en deze file bevat de (voornamelijk HTML code) om de pagina weer te geven.
Weten we nog waar de controller en view ook alweer vandaan komen? Het Framework is gebouwd volgens de MVC-architectuur. In stap 1 hebben we het model gemaakt en in deze 2de stap hebben we de view en controller gemaakt.
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1612557541726.png)
(deze sheet is uit de vorige les)
De controller is waar alle verzoeken van de gebruiker naar toe gaan. De view is de presentatielaag met voornamelijk HTML, CSS, en JavaScript. En in het model wordt de verbinding met de database gemaakt.
### Klaar
Ga naar [http://localhost:8080/country](http://localhost:8080/country)
[](https://www.roc.ovh/uploads/images/gallery/2020-07/image-1594288457454.png)
Je hebt een CRUD van Country gemaakt, compleet met search en sort-functionaliteiten. Je hebt ook een mooie pagina selector waarmee je daar de verschillende pagina's kan navigeren. Je kunt country's lezen/tonen, aanpassen, verwijderen en aanpassen. Probeer het maar! Wees niet bang om de database 'kapot' te maken want je kunt in een paar tellen de database opnieuw importeren.
In de volgende lessen gaan we de automatisch gebouwde applicatie stap-voor-stap aanpassen.
Voor nu kan je trots zijn op je eerste (?) web CRUD applicatie.
#### Extra hulp met Filmpje
Niet gelukt? Kijk in dit filmpje nog een keer alle stappen door: [Instructie Yii - les1](https://youtu.be/6NRMaJgSmLw)
### Opdracht
Maak voor de tabellen:
- city
- countrylanguage
ook een CRUD met de Crud Generator
Controleer op [http://localhost:8080/city](http://localhost:8080/city) en [http://localhost:8080/country-language](http://localhost:8080/countrylanguage) of de CRUD werkt.
### Plus opdrachten
1. Ga in de code-editor naar de map **views** en probeer te vinden waar het overzicht Countries is gemaakt. Haal code weg zodat de kolom *Surface Area* niet meer wordt getoond.
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1612558210976.png)
2. Kun je de in dezelfde view de groene knop 'Create Country' verplaatsen en onderaan de pagina plaatsen?
Dus het moet er zo uit te komen zien:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1612558884647.png)
\--
# 2, Routing
*In deze les leer je wat routing is en hoe je binnen Yii de routing kunt instellen.*
### Wat is routing? (Algemeen)
Routing is de manier waarop de webserver en jouw programma weet welke pagina er moet worden getoond. Kijk maar eens goed naar de URL in je browser. Je kunt de URL opdelen in 5 stukjes:
[](https://www.roc.ovh/uploads/images/gallery/2020-07/image-1594292626981.png)
Onderdeel
Wat is het?
Uitleg
Scheme
protocol
hoe wordt de informatie verzonden (http, https, ftp, smb, file, ...)
domain name
domein
domein verwijst naar een server of een groep servers.
file path
path
verijst naar de file die de webserver moet 'uitvoeren'
parameters
variabelen
hiermee kun je informatie naar de webserver sturen.
anchor
verwijzing binnen de pagina
hiermee kun je naar een onderdeel van de pagina springen.
Voorbeeld: https://www.roc.ovh/link/302#bkmrk-nog-een-keer-in-sche
Het schema bepaald hoe de informatie wordt opgevraagd (bij een webserver is dit meestal http en https). De domain name is de naam van de server(s). Het file path verteld de server welke informatie er moet worden getoond. De parameters zijn variabele die mee kunnen worden gegeven bijvoorbeeld om waarden die een gebruiker heeft ingevoerd naar de webserver te sturen. Tot slotte is het anchor (weinig gebruikt) een verwijzing naar een stukje binnen een pagina.
Normaal gesproken komt het file path overeen met de locatie van de bestanden op de server. Het file path is het path vanaf de document root. Stel de document root staat op jouw laptop naar:
c:\\www
Je hebt XAMPP opgestart en je gaat naar:
[http://localhost/opgave1/uitslag/index.php](http://localhost/opgave1/uitslag/index.php)
Dan wordt de file
c:\\www\\opgave1\\uitslag\\index.php
door de webserver uitgevoerd. Het file path wordt dus achter de *document root* geplaatst
#### Hoe kom je van de URL in je browser naar de file op jouw laptop?
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1613336806883.png)
Met routing zorg je ervoor dat je ergens een vertaling wordt gemaakt tussen het URL en de file PHP die moet worden uitgevoerd.
Alles wat hierboven is beschreven is de *standaard* routing. Zo werkt het op jouw laptop als je plain PHP gebruikt (dat is PHP zonder framework).
Routing zorgt ervoor dat het path en eventueel de parameters de juiste code uitvoeren. Bij eenvoudige web applicaties is het path gewoon de locatie van de file op de harddisk, maar voor meer ingewikkelde programma's kan dat al snel onoverzichtelijk worden.
Met een framework werkt het daarom anders.
### Routing in Yii
Standaard hoef je niets te doen voor routing. Er zit al heel veel voorgebakken in Yii.
Stel je typt in je browser in
localhost:8080/country/index
Dit path bestaat uit twee delen; country en index.
country verwijst naar controllers/CountryController en
index verwijst naar de public function actionIndex in de class CountryController.
Het path bestaat in Yii uit twee delen, de verwijzing naar de controller en de verwijzing naar de functie/method.
De vertaling van path naar controller en function/method gaat als volgt:
1. het eerste deel van het path is de controller-naam, maar
1. de controller-naam begint altijd met een hoofdletter, en;
2. als er een streepje (-) in het path staat dan is dat een nieuw woord en in de controller begint dit nieuwe woord met een hoofdletter. Voorbeeld: dit-is-het-eerste-deel wordt DitIsHetEersteDeel
2. Het tweede deel van het path wordt opdezelfde manier vertaald maar er wordt ook nog eens het woord action voorgezet. Voorbeeld: dit-is-het-tweede-deel wordt actionDitIsHetTweedeDeel
##### Een paar voorbeelden:
path
file
public function
/kaart/overzicht
KaartController
actionOverzicht
/klas-lokaal/overzicht
klasLokaalController
actionOverzicht
/klas-lokaal/stoel-maat
klasLokaalController
actionStoelMaat
/klas-lokaal/index
klasLokaalController
actionIndex
/klas-lokaal
klasLokaalController
actionIndex
Zoals is te zien in de laatste regel, wordt de actionIndex uitgevoerd als het tweede deel van het path ontbreekt.
### Oefening
We gaan in onze World-applicatie oefenen met routing
(1) Zet in de CountryController in de CountryController class een nieuwe public function:
```
public function actionHello() {
echo "Hello World!";
exit;
}
```
**Opdracht:** Save de aangepaste CountryController en bedenk met welke url je nu deze nieuwe functie (method) moet aanroepen.
Controleer dat, zodat je in jouw browser het volgende ziet:
[](https://www.roc.ovh/uploads/images/gallery/2020-07/image-1594296881002.png)
(2) Maak een nieuwe file **controllers/ExampleController.php** en zet daar het volgende in.
```PHP
` dit is kort voor`` . Het toont jouw pagina die in de variabele $content staat:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1614021559589.png)
### Nav Widget in main.php
In de main.php in de folder lay-outs staat de standaard Yii pagina structuur. Het menu is hier ook een onderdeel van.
In de main.php staat een stuk PHP-code die gebruik maakt van een Yii widget. Een Yii widget is eigenlijk een plug-in zoals we die ook bij WordPress kennen.
De code voor de menu bar heeft de volgende structuur:
```PHP
Yii::$app->name, // de naam van het menu
'brandUrl' => Yii::$app->homeUrl, // de home page waar je naar toe gaat als je op de naam klikt
'options' => [
'class' => 'navbar navbar-expand-md navbar-dark bg-dark fixed-top',
],
]);
echo Nav::widget([
// hier worden de menu's en menu items bepaald
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => [
[ 'label' => 'Country',
'items' => [
['label' => 'Overzicht', 'url' => ['/country/index', ''] ],
['label' => 'Voeg toe', 'url' => ['/country/index', ''] ],
['label' => 'Europa', 'url' => ['/country/index', ''] ],
],
],
],
]);
NavBar::end();
?>
```
In Yii worden parameters voor Widget via assiociative arrays mee gegeven. Deze hebben de structuur:
```PHP
[ 'key1' => 'waarde1', 'key2' => 'waarde2' ]
```
de waarde kan dan ook weer een assiociative array zijn:
```PHP
[ 'key1' => 'waarde1', 'key2' => [ 'andere_key1'=> 'andere_waarde1', ........ ] ]
```
### Opgaven
1. Pas het menu aan en plaats de code zoals hierboven beschreven:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1613993167595.png)
2. Om een country toe te voegen moet in de controller *CountryController* de method/function *actionCreate*() worden uitgevoerd.
Bedenk hoe je de routing naar deze pagina opzet en pas het menu aan '*voeg toe*' zodat deze is gekoppeld aan *actionCreate*() van de *CountryController*.
3. In elk menu-item staat de route, bijvoorbeeld 'country/index' en daarna staat een ''. Deze laatste lege string zijn de parameters. Als we alle landen uit Europa willen filteren dan kunnen we de volgende URL gebruiken:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1613993783698.png)
Het gedeelte na de ? is de parameter. In Yii zet je een paramter als volgt in een assiociatieve array (element): 'countrySearch\[Continent\]'=>'Europe'
Het hele menu-item ziet er dus als volgt uit:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1615820099350.png)Pas je menu aan en test uit of alle drie de menu-items goed werken.
4.
5. Maak nu een extra menu-item en noem dat Asia. Dit menu-item laat alle landen van Asia zien.
6. Maak nu een menu-item voor alle werelddelen: North America, South America, Asia, Europe, Africa, Antarctica en Oceania.
7. Maak een extra menu city met als items 'Overzicht' en 'Voeg toe'.
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1614009669414.png)
\--
# 4, Gridview Widget (view)
*Dit In deze les leer je de basis aanpassingen in de Gridview maken.*
*Je leert hoe je kolommen wel of niet **zichtbaar** kan maken, hoe je de kolom **headers** kan aanpassen, hoe je de kolom **breedte** kan aanpassen, hoe je de **inhoud** van de kolom zelf kan aanpassen en als laatste leren hoe we een **link** kunnen maken van een kolom.*
### Country overzicht aanpassen
Onze CRUD-generator (Gii) heeft voor ons een country overzicht gemaakt. Als je de CountryController.php opent dan zie je dat function (method) actionIndex de view index aanroept. Open deze index file. Deze staat in views/country.
### Gridview Widget
Je ziet dat er op regel 23 een zogenaamde widget wordt aangeroepen.
Een Widget is een plug-in waarmee je functionaliteit aan Yii toevoegt. De Gridview Widget is misschien wel de meest uitgebreide widget en het zorgt ervoor dat we een mooi overzicht van onze data krijgen.
#### 1. Kolommen aanpassen
In de parameters van deze widget zie je dat de kolommen *Code*, *Name*, *Continent*, *Region* en *SurfaceArea* worden afgedrukt. Je ziet ook dat bepaalde kolommen niet worden afgedrukt deze staan in commentaar.
##### Opdracht 1
Verander de lay-out in het country overzicht en laat de volgende kolommen in deze volgorde zien:
*Code*, *Name*, *Population*, *SurfaceArea* en *Capital*.
*Population* laat inwoneraantal zien en *SurfaceArea* laat oppervlakte zien.
#### 2. Kopjes aanpassen
Stel we willen het kopje boven de kolom veranderen, dan kan dan als volgt. Vervang bijvoorbeeld 'SurfaceArea' in de GridView door het volgende array.
```
[ 'label' => 'Oppervlakte',
'attribute' => 'SurfaceArea',
],
```
Je ziet dat we de surface area nu hebben vervangen door een assiociative array. Dus waar in de code het woord 'SurfaceArea' staat plaats je het assiociative array zoals hierboven is aangegeven.
Dit verteld de GridView snippet dat het label Oppervlakte moet zijn (dit wordt boven aan de pagina gezet) en dat de waarde in de kolom moet worden gevuld met 'SurfaceArea'.
##### Opdracht 2
Pas nu de kolom *Population* aan; en zet in de kolom header 'Inwoners'.
#### 3. Kolom breedte aanpassen
We gaan de kolombreedte aanpassen. Vervang het blok van net door het volgende:
```
[ 'label' => 'Oppervlakte',
'attribute' => 'SurfaceArea',
'contentOptions' => ['style' => 'width:30px; white-space: normal;'],
],
```
##### Opdracht 3
Pas de breedte van de kolom *Inwoners* (*Population*) ook aan; zet de breedte op 30 pixels.
#### 4. Waarde van kolom aanpassen
Stel we willen km2 achter de oppervlakte plaatsen, dan kunnen we de waarde van de kolom als volgt aanpassen:
```PHP
[
'label' => 'Oppervlakte',
'attribute' => 'SurfaceArea',
'format' => 'raw',
'value' => function($data) {
return sprintf("%8d k㎡", $data->SurfaceArea);
}
]
```
Regel 4 t/m 7 in deze code verandert de waarde van de kolom.
##### Opdracht 4
Test uit wat de code doet, haal 'format'=> 'raw' weg en kijk wat er gebeurt.
Waarom is deze regel nodig?
Vervang regel 6 door
```
return 'hallo';
```
en kijk wat er gebeurt.
#### 5. Link maken van een kolom
In de Capital kolom zien we geen plaatsnaam, maar een nummer. Dit is het ID van een plaats in de city tabel.
Dus de *Capital* kolom uit *country* is de foreign key die wijst naar de primary key *ID* in *city.*
In de city view kun je een plaats naam zoeken door bijvoorbeeld de volgende URL te gebruiken:
[http://localhost:8080/city/index?CitySearch\[ID\]=179](http://localhost:8080/city/index?CitySearch%5BID%5D=179)
179 is het ID van Brussels, de hoofdstad van België.
We gaan nu de value van de kolom Capital vervangen door de link.
Laten we om te beginnen de kolom *Capital* een beetje gaan aanpassen:
##### Opdracht 5
Vervang de kolomnaam van de kolom Capital door 'Hoofdstad'.
Verander de breedte van deze kolom naar 30px.
Vervang de value van de kolom in
```
'value' => function($data) { return "/city/index?CitySearch[ID]=179"; }
```
(alle kolommen krijgen dus dezelfde waarde).
Je ziet nu:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1614025244735.png)
Dat is nog geen link. Dat komt omdat we met <a href="">...</a> een link moeten maken. Dat kan maar dat is lastig omdat we met " in " quotes zitten. Dus dubbele quotes in dubbele quotes. Dat kan, maar het is een gepriegel.
Met de Yii module Html kunnen we dit eenvoudiger doen.
Zet eerst boven aan in de code:
```
use yii\helpers\Html;
```
En we vervangen nu de regel die de waarde returned in:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1614026085274.png)
We zijn er bijna, we moeten nu alleen de 179 nog variabel maken.
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1614026443516.png)
#### Opdracht 6
Maak je code werkend met bovenstaande code.
Als je nu op het nummer klikt ga je naar de hoofdstad van het betreffende land.
Verander nu de tekst van de link zodat je in de kolom Hoofdstad, in 'naar hoofdstad'.
Als je er op klikt dan ga je dus naar de index view van de hoofdstad.
Verander ook de breedte van de kolom naar 120px zodat de kolom netjes past.
De kolom ziet er dus als volgt uit:
[](https://www.roc.ovh/uploads/images/gallery/2021-02/image-1614026822965.png)
#### Opdracht 7
(a) Zet de kolommen in de volgende volgorde:
Code - Name - Hoofdstad - Population - Oppervlakte
(b) Verander de kolomnamen als volgt:
Code - Naam - Hoofdstad - Inwoners - Oppervlakte
(c) Zorg dat de naam van het land vet gedrukt wordt (bold).
(d) Haal vervolgens de volgnummers (1,2,3,4....) weg en verplaats de edit kolom (de laatste) naar voren.
Het hele overzicht ziet er uit zoals te zien is op het volgende plaatje:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1617127616569.png)
Dit is het eindresultaat.
### Plus opdracht \*\*
De bevolkingsdichtheid zegt iets over de hoeveelheid inwoners in een land. Natuurlijk heeft Amerika meer inwoners dan Nederland, maar het land is ook vele groter. Om te vergelijken hoe dichtbevolkt een land is, kun je uitrekenen hoeveel mensen er gemiddeld per km2 wonen.
bevolkingsdichtheid = aantal inwoners / oppervlakte.
Stel een land heeft een oppervlakte van 100 km2 en je er wonen 200 mensen. Dan heb je in dit land dus gemiddeld 2 inwoners per km2, want:
2 = 200 / 100
Maak nu een nieuwe kolom in het *country* overzicht en bereken daarin de bevolkingsdichtheid.
\--
# 5, Menu - Controller - View
*We gaan een eigen overzicht maken. We beginnen met het aanmaken van een menu, dan maken we een controller, en van de controller gaan we naar de view. We leren data op te halen met de controller en deze te tonen in onze eigen view.*
*Het ophalen van data doen we met een eenvoudige query die we in de Controller plaatsen. Vanuit de Controller gaan we via het Model naar de database. De volgorde wordt:*
Gebruiker -> (kiest) menu -> controller -> model -> database -> (resultaat terug naar) controller -> view -> gebruiker.
*In deze les maken we dus het hele 'rondje'. Dit is een standaard 'rondje' dat in elke applicatie vaak terug zal komen.*
### Menu - Controller - View
Om te beginnen maken we een nieuwe method (=functie) in de **controllers/CountryControlle**r class.
Deze controller noemen we actionOverzicht. Volgens de routing regels wordt de route wordt dus /country/overzicht.
##### Opdracht 1
Maak een menu item *overzicht* onder country dat naar */country/overzicht* gaat.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1614620329168.png)
Probeer het menu uit. Wat zie je en kun je verklaren wat je ziet?
Juist.... je krijgt een foutmelding want de routering verwijst naar de method/function actionOverzicht in de controller CountryController en die bestaat niet!
We gaan dus een stukje code toevoegen aan onze CountryController.
```PHP
use yii\data\Pagination;
..
..
public function actionOverzicht()
{
// dit is de query, dit is te vergelijken met select * from Country
$countries=Country::find()->all();
// de view wordt aangeroepen en het object $countries en $pagination wordt meegegeven.
return $this->render('overzicht', [
'countries' => $countries,
]);
}
```
##### Opdracht 2
Maak de function *actionOverzicht* in de *CountryController* zoals hierboven is aangegeven.
Test opnieuw wat er gebeurt als je het menu *overzicht* selecteert
 What? Weer een fout? Waarom nu?
Juist het menu gaat naar de actionOverzicht en de actionOverzicht voert een query uit en roept de view overzicht op. En die view bestaat (nog) niet.
We gaan dus in de folder views/country een nieuwe file overzicht.php aanmaken en plaatsen daar de volgende code in.
```PHP
Name;
echo " - ";
echo $country->Code;
echo " - ";
echo number_format($country->Population, 0, ',', ' ');
echo " ";
}
?>
```
##### Opdracht 3
Maak de view *overzicht* zoals hierboven is aangegeven.
Het overzicht is bijna niet geformatteerd.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1614627165703.png)
Weet je nog hoe een HTML table er uit ziet?
```HTML
..
..
..
..
..
..
```
Hierboven staat een skelet van een table met twee rijen en drie kolommen.
Vind je dit lastig? [Kijk dan de video.](https://youtu.be/D00WkHqw2qk)
##### Opdracht 4
Verander de /view/country/overzicht nu zo dat het netjes in een table wordt gezet. De output komt er als volgt uit te zien:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1614627534845.png)
De kolommen staan nu dus netjes onder elkaar.
Je hebt nu zelf een view opgebouwd zonder gebruik te maken van de Gridview widget. Het kost meer tijd en moeite om zelf een overzicht zonder Gridview widget te maken, maar je hebt wel veel meer controle over hoe jouw overzicht er uit komt te zien.
### Sorteren en selecteren
Via de Yii Gridview widget hebben we geleerd dat we eenvoudig kunnen sorteren en selecteren. De Yii Gridview heeft ook beperkingen. Je kunt bijvoorbeeld niet alle landen zoeken met *meer dan* X inwoners. Soms wil je ook dat de gebruiker zelf niet kan selecteren. Hij krijgt dan niet alle regels uit de tabel te zien, maar bijvoorbeeld alleen de regels met de datum van vandaag.
We gaan het sorteren en selecteren via de controller coderen.
Kijk nog eens naar de *CountryController* bij de *actionOverzicht*, daar staat:
`$countries=Country::find()->all();`
Dit statement kijkt naar het object *Country* dat in het model is gemaakt en zoekt dan naar alle regels uit dit object. Dit object wordt in het model gekoppeld aan de tabel *country*.
Yii vertaald dit naar de query
`SELECT * FROM country`
We kunnen nog veel meer, kijk maar eens naar het volgende uitgebreide voorbeeld:
`$countries = country::find()->where(['Continent' => 'Europe'])->orderBy(['Name' => SORT_ASC])->all();`
Hier worden alle *countries* geselecteerd met *Continent*=*Europe*, gesorteerd op *Name.*
Dit is een soort Yii query; een query in Yii-formaat.
Het SQL-statement zou er zo uit zien:
`SELECT * FROM country WHERE Continent = 'Europe' ORDER BY Name ASC`
Op deze manier kun je dus via de code in de controller een selectie maken en de sortering aanpassen. In de volgende opdracht komt dit terug.
##### Opdracht 5
- - Maar een nieuw menu-item en noem dit *Overzicht Europe*.
- Maak een nieuwe function *actionOverzichtEurope,* zet deze in de juiste controller en koppel deze aan het menu-item.
(let op de vertaling naar de routering; in de routering staat nooit een hoofdletter en woorden worden gescheiden door een streepje "-" , [zie les 2 over routing](https://www.roc.ovh/link/302#bkmrk-een-paar-voorbeelden)).
- Laat in dit overzicht alle landen van Europa zien. Gebruik hiervoor het stukje code dat hierboven staat ($countries = country::find()->where.........).
- Druk de volgende kolommen af:
*Name* en *Surface Area*
- - Zet de twee kolommen netjes onder elkaar
- Formateer de Surface Aera netjes met spatie tussen de duizendtallen en lijn ze recht uit.
- Maak een header die **bold** is.
- Sorteer het overzicht op Surface Area van grootste land naar kleinste.
Het overzicht komt er dus zo uit te zien:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1614629726011.png)
Je hebt geleerd dat je een overzicht kan maken via een (Yii-)query. Met de query kan je de selectie en sortering aanpassingen. De query wordt geplaatst in de *controller* en maakt gebruik van het model. In dit voorbeeld het model van *country*.
Dit komt terug in het examen, daarom nog een opgave over dit onderwerp.
##### Opdracht 6
Pas het overzicht van Opdracht 5 aan zodat je alleen alle kleine Europese landen ziet.
Een land is klein als `SurfaceArea <100000`
Pas hiervoor de controller aan.
Je hebt dus te maken met **twee** zoekcriteria.
Zoek zelf op internet uit hoe je in een 'Yii-query' twee zoekcriteria kan combineren met *andWhere().*
\--
# 6, Relaties 1:1 en 1:N
*In deze les gaan we bekijken hoe je relaties legt tussen tabellen en hoe je informatie uit andere tabellen kan afdrukken in jouw view.*
Een relatie in de view wordt altijd gelegd tussen één regel (row/record) van één tabel naar één of meer rijen in een andere tabel.
Omdat de relatie vanuit één regel wordt gelegd, is er dus altijd sprake van een 1:1 of 1:N relatie.
We gaan beide relaties apart bespreken en uittesten met voorbeelden.
Als uitgangspunt nemen onze eigen view die we in de vorigen les hebben gemaakt. We gaan een kolom toevoegen waarin de hoofdstad van el land wordt getoond.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1615887892142.png)
### 1:1 relatie
Bekijk de *World* database. In de *country* tabel staat de kolom *Capital*, dit is een foreign key die verwijst naar de primary key *ID* in de *city* table.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1615888192933.png)
Vanuit de country table kun je via de foreign key Capital verwijzen naar de Name in de gekoppelde tabel city.
```PHP
$country->hoofdstad->Name;
```
Met dit statement verwijs je vanuit de *country* tabel, via de relatie *hoofdstad* naar de N*ame* (naam) van de hoofdstad.
Nu moet de relatie hoofdstad alleen nog worden geprogrammeerd. Dit doen we in de model file van Country.
```PHP
// models/Country.php
public function getHoofdstad()
{
return $this->hasOne(City::className(), ['ID' => 'Capital']);
}
```
De functie *getHoofdstad* vertel jij Yii hoe de relatie tussen de tabel *Country* en *City* in elkaar zit.
Een 1:1 relatie wordt dus op de volgende manier gemaakt:``
```PHP
public function get()
{
return $this->(::className(),
['' => '']);
}
```
In een query zou de relatie er als volgt uit zien:
```SQL
SELECT *
FROM Country
LEFT JOIN City
ON Country.Capital = City.ID
```
De relatie is gemaakt in het Model van Country en is dan ook alleen vanuit Country Beschikbaar. Je kunt in een view van Country dan gegevens uit de relatie afdrukken door:
`$country->relatie_naam['kolom naam']`
##### Opdracht 1
**Lees** de uitleg hierboven goed door en plaats de kolom hoofdstad in het overzicht.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1615887892142.png)
Maak hiervoor twee aanpassingen:
1. 1. maak de relatie in het model van *Country*, en
2. pas de view *overzicht* aan door daar de kolom *Hoofdstad* aan toe te voegen.
We gaan de Hoofdstad clickable maken. Als je naar [http://localhost:8080/city](http://localhost:8080/city) gaat dan zie je het overzicht van steden. Klik op een oogje op een van de steden. Let op de URL. Je ziet [http://localhost:8080/city/view?id=<NR>](http://localhost:8080/city/view?id=) als url en <NR> is het ID van de stad.
Dus als je bijvoorbeeld klikt op [http://localhost:8080/city/view?id=5](http://localhost:8080/city/view?id=5) dan zie je informatie over Amsterdam.
##### Opdracht 2
Maak elke hoofdstad in het overzicht datje bij opdracht 1 hebt gemaakt *clickable. Als je op de link klikt dan* open je het overzicht van de stad, bijvoorbeeld [http://localhost:8080/city/view?id=5](http://localhost:8080/city/view?id=5).
Tip: je kunt Html:a() gebruiken om een link te maken. Dit is in de [vorige les uitgelegd](https://www.roc.ovh/link/303#bkmrk-zet-eerst-boven-aan-).
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1615896595590.png)
### 1:N relatie
In de *World* database staat een tabel *countrylanguage*. In deze tabel staat per land welke talen er worden gesproken. Per taal wordt ook aangegeven welk percentage van de bevolking deze taal spreekt. De relatie tussen country en *countrylanguage* is 1:N. Namelijk in een land worden **1 of meer** talen gesproken.
We willen een overzicht maken dat er als volgt uitgaat zien:
[](https://www.roc.ovh/uploads/images/gallery/2020-07/image-1594550267859.png)
In dit voorbeeld zien we dat in Indonesië 8 talen worden gesproken. We gaan ons overzicht aanpassen, zodat we per land alle talen die er worden gesproken netjes in de tabel worden weergegeven zoals hierboven in het voorbeeld is te zien.
Hoe werkt dit?
Bij de 1:1 relatie hierboven konden we via `$country->hoofdstad['Name']` de naam van de hoofdstad uit de gelinkte tabel opvragen. Als dit niet duidelijk is, lees dan het stuk over 1:1 relatie hierboven nog een keer goed door!
Bij een 1:N relatie werkt het hetzelfde als bij de 1:1 relatie. Dus in het model (*models/Country.php*) s de relatie beschreven:
```PHP
public function getCountrylanguages()
{
return $this->hasMany(Countrylanguage::className(), ['CountryCode' => 'Code']);
}
```
Controleer of je het model hebt aangemaakt van *Countrylanguage* tabel.
Let even op de hoofd en kleine letters!
tabel naam in database
Countrylanguage
model naam
CountryLanguage
relatienaam in Country.php
Countrylanguages
We kunnen nu vanuit de view (*views/country/overzicht.php*) via `$country->countryLanguages` de taal opvragen.
Als je de Gridview widget gebruikt dan noem je het veld (in de Widget) `country.countryLanguages`
Er is alleen één belangrijk verschil, omdat we geen 1:1 relatie hebben, maar een 1:N, krijgen we geen variabele terug maar een array. We moeten het dus met een loop door het array heen lopen.
Dit gaan we demonstreren met behulp van de debug functie die we in [les 1 (optioneel)](https://www.roc.ovh/link/296#bkmrk-%C2%A0-1) hadden toegevoegd. als je dit nog niet hebt gedaan dan moet je dat nu doen.
#### Debugging
Ga nu naar je view en voeg bovenaan in de loop waarmee je het overzicht afdrukt, de regel dd($countries) toe. *dd* staat voor dump & die. Dus *dd()* laat de variabele zien en stopt met het uitvoeren van het programma.
```PHP
";
....
foreach ($countries as $country) {
...
// hier staat al code voor eerste kolommen
...
// voeg hier deze kolom toe
echo "
";
d($country->countrylanguages);
echo "
";
...
}
...
```
Als we even de border van de tabel aanzetten (regel 3) dan is het iets makkelijker om de output te lezen.
Als je goed kijkt dan zie je in de rechter kolom een array van objecten. In deze Yii-objecten staat telkens een 'Language'.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616504143444.png)
Om de taal te af te drukken moeten we eerst het element array aanwijzen:
```
$country->countrylanguages[0]
$country->countrylanguages[1]
$country->countrylanguages[2]
$country->countrylanguages[3]
```
En van elk element moeten we de 'Language' hebben. Dat kun je in de dump (plaatje hierboven) goed zien.
```
$country->countrylanguages[0]->Language
$country->countrylanguages[1]->Language
$country->countrylanguages[2]->Language
$country->countrylanguages[3]->Language
```
Je weet natuurlijk niet hoeveel talen er in elk land worden gesproken. De lengte van het array is in dit voorbeeld 4, maar het kunnen er natuurlijk meer of minder zijn.
##### Opdracht 3
**Lees** de uitleg hierboven goed door. Druk in de laatst kolom één taal af.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616504705123.png)
Nu hebben we één taal per land, maar in de meeste landen wordt meer dan één taal gesproken. We gaan nu met een loop door het array $country->countrylanguages heen. Gebruik hiervoor de volgende loop.
```PHP
foreach( $country->countrylanguages as $taal) {
// vul zelf de jusite variable in om de taal af te drukken
echo .....;
echo " ";
}
```
##### Opdracht 4
Gebruik de loop zoals hierboven is aangegeven en maak het volgende overzicht.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616505080100.png)
Zorg ervoor (met CSS) dat de tabel er netjes uitgelijnd uit ziet zoals hierboven in het voorbeeld.
Je hebt nu een 1:N (één op meer) relatie gemaakt. In volgende lessen gaan we hier opnieuw mee aan de slag.
##### Opdracht 5
In de Countrylanguages tabel staat naast de taal ook het percentage. Dit is het percentage van de bevolking dat deze taal spreekt. Zet dit percentage tussen haakjes achter elke taal. Voorbeeld:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616505413868.png)
Jammer dat de percentage niet gesorteerd zijn!
Pas de relatie aan in het Country model
```PHP
public function getCountrylanguages()
{
return $this->hasMany(CountryLanguage::className(), ['CountryCode' => 'Code'])
->orderBy(['Countrylanguage.Percentage' => SORT_ASC]);
}
```
Regel 4 is erbij gekomen. let op de ; !
Als je nu het overzicht opnieuw toont dan zie je dat de talen nu oplopend (van laag naar hoog) zijn gesorteerd.
##### Opdracht 6
Sorteer de talen op percentage aflopend van hoog naar laag. Op die manier komt de meest gesproken van een land bovenaan.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616506111435.png)
Tip: gebruik Google om te zoeken hoe je de relatie in het model verandert zodat je aflopend kunt sorteren.
Als je in de database de relaties (via SQL) goed definieert dan worden de relaties in Yii door de model generator automatisch gemaakt. Het aanmaken van relaties in de databases valt buiten deze lessen en kan lastig zijn. Het is dus belangrijk dat je snapt hoe de relaties tussen tabellen in Yii worden gemaakt.
---
# 7, en nu koffie!
In deze les gaan we alles wat we tot nu toe hebben geleerd herhalen. We bouwen een nieuwe applicatie.
In de volgende les gaan we nieuwe dingen leren met deze applicatie.
### Wat gaan we maken?
We gaan een applicatie maken waarin medewerkers van een coffee-to-go een bestelling kunnen opnemen. De medewerker neemt een bestelling op, vraagt de naam van de klant. De bestelling krijgt een status *besteld.*
De bestelling wordt klaar gemaakt en de barista (koffiemaker) zet de status van de bestelling op *klaar.* De medewerker ziet dat zijn bestelling klaar is, roept de naam van de klant en rekent af. De status wordt op *geleverd* gezet.
### Opdracht 1
##### Opdracht 1
Maak de *coffee* database met de drie tabellen, menu, medewerker en bestelling. Maak voor elke tabel een CRUD.
Volg de stappen hieronder om dit uit te voeren.
In stap 1 maak je een nieuwe database
In stap 2-6 maak je een nieuw Yii project aan. De uitgebreide instructie met voorbeelden kan je vinden in les 1.
In stap 7-12 maken we de tabellen en de CRUD pagina's.
**Voer stap 1 tot en met 13 uit.**
Stap 1, maak een database *coffee.*
Stap 2, maak een nieuw Yii project *coffee.* Gebruik de onderstaande regel voor in de Terminal.
Let op dat je `` vervangt voor de naam van dit project
```
composer create-project --prefer-dist yiisoft/yii2-app-basic
```
Stap 3, pas de database configuratie file in de Yii aan en laat deze verwijzen naar de *coffee* database.
Stap 4, pas de web.php in de Yii config aan en zet smart routing aan (uncomment het gedeelte bij 'urlManager').
Stap 5, maak de file functions.php met daarin de functies dd() en d(). Dit is beschreven in les 1.
Stap 6, roep functions.php aan vanuit de web.php configuratie file. Ook dit staat in les 1 beschreven.
Stap 7, maak een tabel medewerker.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616594908052.png)
Stap 8, Genereer het model en de CRUD voor *medewerkers* en zet de volgende namen in de database.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616594707813.png)
Stap 9, maak een tabel menu.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616595011664.png)
Stap 10, Genereer het model en de CRUD voor *menu* en zet de volgende namen en prijzen in de database.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616594739223.png)
Stap 11, Maak een tabel bestelling
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616595477669.png)
Stap 12, Genereer het model en de CRUD voor *bestelling. (er hoeft geen data in de database gezet te worden voor Bestelling)*
We hebben nu een tweede standaard Yii applicatie en we gaan nu aanpassingen maken in het invoerformulier 'Create Bestelling'.
Als we nu een nieuwe bestelling maken dan zien we het volgende scherm:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616595571596.png)
Stap 13*, timestamp* halen we weg, want die wordt automatisch ingevoerd (default). Die hoeven we dus niet in te voeren. Open de *\_form.php* in de view van bestelling en haal de *timestamp* regel er uit.
(als *id* er ook nog in staat dan kun je deze ook verwijderen uit het formulier)
### Opdracht 2
#### ERD (Database Model)
(optioneel alleen als je nog examen KT1 moet doen).
##### Opdracht 2
Maak de *coffee* database met de drie tabellen, menu, medewerker en bestelling een ERD met behulp van Lucichart.
We zijn nu klaar en gaan in de volgende les onze eigen drop down menu's maken.
\--
# 8, Form en drop down
*We gaan onze koffie applicatie uitbreiden.*
*Om het invoeren van gegevens eenvoudiger te maken gaan we drop down menu's toevoegen.*
*We gaan naar twee soorten drop-downs kijken; die met vaste waarden en die met dynamische waarden (uit de database).*
*Bij het invoeren van een bestelling gaan we allereerst de status via een drop down invoeren.*
*Daarna gaan we waarde voor de medewerker ook uit een drop down halen. Deze waarde moet uit de database komen.*
### Drop down in Bestelling
We gaan kijken naar de bestelling tabel en CRUD.
Als we de status in de database als een enum hebben aangemaakt dan weet Yii dat de status uit beperkt aantal waarden kan hebben en als het goed is maakt Yii dan vanzelf een een drop down in het form.
Klopt dat heb jij een drop down?
Indien niet, dan kun je de code aanpassen in het form aanpassen.
In de view *\_form.php* van Bestellingen moet de volgende regel staan:
```PHP
= $form->field($model, 'status')->dropDownList([ 'besteld' => 'Besteld', 'klaar' => 'Klaar', 'betaald' => 'Betaald', '' => '', ], ['prompt' => '']) ?>
```
Deze regel laat een drop down menu in het formulier zien. Kijk eens goed naar de parameter van dropDownList.
```
[ 'besteld' => 'Besteld', 'klaar' => 'Klaar', 'betaald' => 'Betaald', '' => '', ], ['prompt' => '']
```
De eerste parameter is een associative array waarin elk element bestaat uit een key en een value.
De key is de waarde die het element uit het form krijgt (de value) en deze waarde wordt door Yii in de database gezet. De key komt dus overeen met de waarde in de database. De value van het associatieve array is wat de gebruiker op het scherm ziet.
Deze waarde kan je dus veranderen. Je kunt dus bijvoorbeeld 'betaald' veranderen in 'afgerekend'. Het enige dat dan gebeurt is dat je iets ander op het scherm ziet.
In dit voorbeeld is de key en de value gelijk (de waarde op het scherm is hetzelfde als de waarde in de database).
Dus samengevat, de key is de waarde in de database en de value is wat de gebruiker op het scherm ziet.
Stel we willen in het form van bestelling de medewerker veranderen. Dan moeten we dus de *foreign key* die naar medewerker verwijst veranderen. Het juiste id van de medewerker moet in de tabel bestelling worden ingevuld.
De waarde wordt dus het id, maar dat is niet wat je de gebruiker wilt laten zien.
Dus als we voor de medewerkers een drop down willen maken dan hebben we een assiociative array nodig dat er zo uit ziet:
```
[ '1'=> 'Ayoub', '2'=> 'Brahim','3'=> 'Carla','4'=> 'Diego','5'=> 'Eisa' ]
```
De keys zijn de id's die als foreign keys in de bestelling tabel staan en de namen zijn de namen van de medewerkers.
### Opdracht 8a
Maak nu een statische drop down met de waarden zoals in het voorbeeld (Ayoub, Brahim, Carla, ....).
De waarden worden dus (nog) niet uit de database gehaald.
##### Inleveren
1. Schermafdruk yii-08a-jouw-naam met het form waarin je de drop down (opengeklapt) laat zien. Maak een schermafdruk van je gehele browser.
### Opdracht 8b, Dynamische drop down
In opdracht 8a hebben we een drop down van medewerkers gemaakt, maar we willen de lijst van medewerkers natuurlijk uit de database halen.
*In deze opdracht leg ik stap-voor-stap uit wat je moet doen omdat oor elkaar te krijgen. Lees alles aandachtig door en sla geen stappen over!*
Data uit de database halen doen we in de controller.
Open de BestellingController. Vanuit deze code wordt de create view aangeroepen en vanuit de create view wordt de \_form.php aangeroepen. Waarom dit in twee stappen gaat leggen we later uit.
We veranderen de code in Bestelling controller:
```PHP
use app\models\Medewerker;
..
..
public function actionCreate()
{
$model = new Bestelling();
$medewerkers = Medewerker::find()->all();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
'medewerkers' => $medewerkers
]);
}
```
De eerste regel `use app\models\Medewerker;` zetten we bovenaan in de BestellingController. Hiermee vertellen we Yii dat vanuit de *BestellingController* gebruik willen gaan maken van het model *Medewerker*.
In de function *actionCreate* die wordt aangeroepen als we een nieuwe bestelling willen maken, voegen we een object toe waarin alle medewerkers zitten. In regel 9 halen we alle medewerkers op en in regel 17 sturen we het resultaat naar de view create.php (van *bestelling*).
We kunnen de medewerkers ook ophalen via een sql-query. Je mag regel 9 ook vervangen in de volgende twee regels:
```PHP
// dit is hetzelfde als
// $medewerkers = Medewerker::find()->all();
$sql="select * from medewerker";
$medewerkers = Yii::$app->db->createCommand($sql)->queryAll();
```
In de view create.php van bestelling passen we het laatste code aan
```PHP
= $this->render('_form', [
'model' => $model,
'medewerkers' => $medewerkers
]) ?>
```
Hiermee geven we het object medewerkers weer door aan de view *\_form* van bestelling.
In het view \_form zetten we nu bovenaan in het PHP-gedeelte.
```PHP
dd($medewerkers);
```
Dit is de debugfunctie en hiermee controleren we of we inderdaad alle medewerkers naar de view hebben gestuurd.
We hebben nu als het goed is een lijst van medewerkers in de \_form maar we moeten het ombouwen naar een assiociative array.
Pas hiervoor de code aan in de view \_form van bestelling.
```PHP
...
...
...
```
Deze code laat het eerst stukje van de view\_form zien.
Met de functie ArrayHelper::map zetten we het object $medewerkers om in een assiociative array. Met dd() laten we dat zien. Probeer maar! Als het goed is, zie je het volgende:
```PHP
[
1 => 'Ayoub'
2 => 'Brahim'
3 => 'Carla'
4 => 'Diego'
5 => 'Eisa'
]
```
En dit is precies wat we nodig hebben om de Drop Down te maken.
Pas de regel in de view \_form van bestelling waarin de user het id van de medewerker moet intypen aan. Verander deze regel in:
```PHP
= $form->field($model, 'medewerker_id')->dropDownList($medewerkerList, ['prompt' => ''])->label('Medwerker') ?>
```
Als het goed is heb je hiermee een werkend menu gekregen.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616605065315.png)
Gelukt? Wordt de lisjt van medewerkers in de drop down uit de database gehaald?
### Inleveren
1. schermafdruk yii-08b-jouw-naam met het form waarin je de drop down van de medewerkers (opengeklapt) laat zien. Maak een schermafdruk van je gehele browser.
### Opdracht 8c
Maak nu een drop down voor de bestelling zodat de medewerker
uit een lijstje van koffiesoorten kan kiezen bij het opnemen van
de bestelling.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616605448841.png)
Gebruik hiervoor het stappenplan dat hieronder is beschreven.
#### Het stappenplan voor een drop down
Schrijf eerst het volgende op:
In welk model komt de drop down? Dit noemen we de target.
(in opdracht 2 hierboven is dat *Bestelling*)
Waar komt de informatie voor de Drop Down uit? Dit noemen we de source.
(in opdracht 2 hierboven is dat *Menu*)
#### Voer nu de stappen 1-6 uit
1. Zet in de target controller welke source model we willen gebruiken.
```
// in controller van target
use app\models\;
```
2. Haal in de target controller in de actionCreate() de informatie uit de source op.
```
// sourceName bedenk jij zelf en daarin staat de informatie die in de drop down moet komen.
$sourceName = source::find()->all();
```
3. Geef vanuit de target controller in de actionCreate() de informatie door aan de view.
```
return $this->render('create', [
'sourceName' => $sourceName,
....
]);
```
4. Open de view create in de target (view) en geef de informatie door aan \_form view.
```
= $this->render('_form', [
'sourceName' => $sourceName,
...
]);
```
5. Open de view \_form in de target (view) en zet de informatie om in een assiociative array
```
// in dit voorbeeld worden id en naam gebruikt:
// id is het veld dat moet worden opgeslagen
// naam is het veld dat in de drop te zien is
$sourceNameList = ArrayHelper::map($sourceName,'id','naam');
```
6. Pas het invoerveld aan in de \_form van de target (view).
```
// veld_in_de_db is het veld van de target dat in dit invoerveld wordt weggeschreven.
= $form->field($model, 'veld_in_de_db')->dropDownList($$sourceNameList, ['prompt' => '']) ?>
```
Als je alles correct gedaan hebt dan moet je nog 1 regel aanpassen in de code om de functionaliteit te gebruiken. Yii controleert automatisch of alle databasekolommen zijn ingevuld in het formulier. Dit controleren wordt *validatie* genoemd. Deze regels staan in het model. Omdat je geen Bestelling ID opgeeft bij het maken van een bestelling moet je deze requirement verwijderen op regel 33 van model Bestelling.
```PHP
return [
[ ['naam', 'medewerker_id', 'menu_id', 'status'], 'required'],
...
...
]
```
### Inleveren
1. schermafdruk yii-08c-jouw-naam met het form waarin je de drop down van de producten (opengeklapt) laat zien. Maak een schermafdruk van je gehele browser.
2. de *BestellingController.php* en zet jouw naam bij de aanpassingen die je hebt gedaan.
### Opdracht 8d
De insert en update lijken op elkaar en gebruiken hetzelfde form (\_form.php).
We hebben nu de insert aangepast, maar de update nog niet. Controleer maar! We moeten nu de update dus ook nog aanpassen.
#### aanpassen update view
Weet je nog dat de -update view niet rechtstreeks door de actionCreate van de BestellingController wordt aangeroepen?
Hoe zit dat nu?
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616610519616.png)
De *actionCreate* en *actionUpdate vanuit* de controller gaan bieden naar hun 'eigen' view maar via deze eigen view komen beide op hetzelfde form uit. Dat komt omdat een *update* en *create* hetzelfde form gebruiken.
Als we nu dus een update uitvoeren van de bestelling (pennetje vanuit de gridview) dan krijgen we een foutmelding. Dat komt omdat de form verwacht dat er gegevens voor de drop down worden meegestuurd.
Om dit te fixen kopiëren we de code in de controller die we in de *actionCreate* hebben gemaakt dus naar de *actionUpdate*.
Deze twee functies zijn bijna hetzelfde. Bij de create wordt alleen een nieuw object gemaakt en bij de update wordt een bestaand object ingeladen.
Nu moeten we de objecten nog doorgeven van de *update* view naar de *\_form* view. Net zoals we dat ook deden bij de *create.*
Zorg ervoor dat de update weer werkt en dat de objecten op de juiste manier worden doorgegeven. Lees hiervoor de uitleg die hierboven staat.
Pas de actionUpdate in de BestellingController aan.
Pas de update view van de BestellingController aan
Zorg dat de update van een Besteliing goed werkt..
### Inleveren
1. de *BestellingController.php* en zet jouw naam bij de aanpassingen die je hebt gedaan.
###
### Opdracht 8e
#### De final touch
Laten we nog wat labels aanpassen. Dit zijn de teksten die boven de invoervelden in het form staan.
Pas de labels in het form aan zodat er Medewerker, Klantnaam, Bestelling en Status Bestelling komt te staan:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616611684520.png)
Zoek zelf uit hoe dit moet. Tip gebruik de zoektermen:
**How to change label text of the ActiveField?**
### Inleveren
1. schermafdruk yii-08e-jouw-naam met het bestellingen form waarin je de aangepaste labels laat zien. Maak een schermafdruk van je gehele browser.
\--
# 9, Drop down in de Grid View
*In deze les gaan we bepaalde dingen herhalen en op een ander manier gebruiken. We leren hoe we drop downs in een Gridview plaatsen en we leren ook hoe we een relatie kunnen gebruiken in de gridview.*
In de gridview van de *Bestellingen* pas de kolom **status** aan:
```PHP
[
'attribute'=>'status',
'filter'=>array('besteld'=>'is besteld', 'klaar'=>'is klaar', 'betaald'=>'is betaald'),
],
```
In de database is de waarde van deze kolom *besteld*, *klaar* of *betaald*. Om duidelijk het verschil tussen de waarde van de kolom in de database en de getoonde waarde te laten zien zijn de getoonde waardes 'is besteld', 'is klaar' en 'ís betaald'.
Let op dat
```
array('besteld'=>'is besteld', 'klaar'=>'is klaar', 'betaald'=>'is betaald')
```
hetzelfde is als
```
['besteld'=>'is besteld', 'klaar'=>'is klaar', 'betaald'=>'is betaald']
```
Als we nu een drop down willen bij de medewerkers dan moeten we dit hetzelfde aanpakken als we in de vorige les hebben gedaan:
Bovenaan in de view zetten we:
```PHP
$medewerkerList=['1'=>'test1','2'=>'test2','3'=>'test3'];
```
Test dit uit. Als je test1 selecteert dan selecteer je dus de medewerkers met id 1.
Vanuit de controller maken we een object dat alle medewerkers bevat. Dit object geven we door aan de grid view (index). Daar maken we van het object een list en de list plaatsen we in de kolom als value van de key 'filter'.
Dus we veranderen de kolom medewerker:
```PHP
[
'attribute' => 'medewerker_id',
'filter' => $medewerkerList,
],
```
##### Opdracht 1
Zorg er nu voor dat je vanuit de controller de medewerkers opvraagt en deze verstuurd naar de index view.
Gebruik de
`ArrayHelper::map()`
functie om je object om te zetten in een list.
En gebruik de list dan in de gridview.
In de kolom medewerker zien we nu de id's van de medewerker. Als we de naam willen afdrukken moeten we de relatie maken. Dit hebben we eerder gedaan, zet in het model van Bestelling de volgende code:
```PHP
public function getMedewerkers()
{
return $this->hasOne(Medewerker::className(), ['id' => 'medewerker_id']);
}
```
Plaats nu in de gridview in de index view van de bestelling:
```PHP
[
'attribute' => 'medewerker_id',
'label' => 'Medewerker',
'filter' => $medewerkerList,
'value' => 'medewerkers.naam'
],
```
Hiermee zetten we de waarde van deze kolom op *naam* van de relatie *medewerkers*.
##### Opdracht 2
Pas tenslotte het label aan en zorg ervoor dat de kolom waarin de medewerker wordt getoond in de gridview (van de index view van bestelling) er als volgt uit ziet:
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616622153704.png)
Als er een naam wordt geselecteerd dan worden alle bestellingen die door deze medewerker zijn uitgevoerd geselecteerd.
Hiermee zetten we de waarde van deze kolom op *naam* van de relatie *medewerkers*.
##### Opdracht 3
In deze opdracht gaan we alle stappen die we hebben uitgevoerd om de kolom *Medewerker* aan te passen nog een keer uitvoeren maar nu voor de kolom *menu\_id*.
Pas de *menu\_id* kolom aan in het bestellingenoverzicht (*index* view van *Bestelling*).
Zorg ervoor dat je met een drop down alle koffie soorten (*menu*) kunt selecteren. Je kunt dan dus alle bestellingen 'Americano' opzoeken.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616622602808.png)
Zorg ervoor dat je de juiste relatie legt tussen de *Bestelling* en *Menu*.
Pas dan de grid view aan zodat je in de bestelling kolom geen id's meer ziet, maar dat je de naam van de bestellingen ziet.
[](https://www.roc.ovh/uploads/images/gallery/2021-03/image-1616622580235.png)
Let ook op het label. Dit is veranderd van *menu\_id* naar *Bestelling*.
**Succes!**
\--
# 10. View en details aanpassen
Om alle details netjes te krijgen dien je nog de view.php aan te passen zodat de labels correct staan.
##### Opdracht 1
Pas de gegevens van de tabel in de **view.php** zodanig aan dat het resultaat er ongeveer zo uit ziet als onderstaande afbeelding:
Let op! Er is een relatie tussen Bestelling en Medewerker. Wil je van de properties van medewerker gebruik maken doe dan dit: $model->menu->naam
**Tip: er is ook een relatie tussen Bestelling en Menu**
#### Opdracht 2
Boven elke pagina kun je **breadcrumbs** zien die aangeven waar een gebruiker zich bevindt. Als je de opdrachten gemaakt hebt volgens de instructies dan zie je dat er *Bestellings* staat. Dit is natuurlijk niet correct. Kun je dit aanpassen naar *Bestellingen.*
**Tip: dit dien je te doen op meerdere views.**
# 11. Login
*Yii heeft al een (beperkte) ingebouwde login. In deze les wordt besproken hoe je dit systeem kan gebruiken.*
### Role based security
In *role based security* heeft elke gebruiker een naam en wachtwoord en heeft elke gebruiker ook een rol (role in het Engels). De role bepaald dan wat de gebruiker kan. Je kunt de rol 'admin' hebben die bijvoorbeeld alles kan en mag. Daarnaast kun je de rol 'user' hebben die bijvoorbeeld alleen bepaalde overzichten kan maken. Een andere rol zou bijvoorbeeld 'docent' kunnen zijn en de docent kan dan bijvoorbeeld cijfers aanpassen. De rol leerling kan dan bijvoorbeeld alleen de cijfers raadplegen.
### Model
De file in model 'User.php' bevat de data waarin de users staan. De users staan dus niet in de database. Dat kan wel maar dat kost iets meer tijd en voor het ontwikkelen is het lekker 'makkelijk' om de gebruikers even lokaal aan te maken.
Standaard staat dit in de *User.php* file
```PHP
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
'role' => 'admin',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
'role' => 'user'
],
];
```
Regel 8 en 16 (de 'role') zijn toegevoegd aan de standaard inhoud van de file. In dit voorbeeld zijn er dus twee rollen.
Dan dien je nog een attribuut/property toe te voegen aan de User Model. Door deze als volgt aan te maken:
Voeg `public $role` toe bovenaan in de class User
```PHP
class User extends \yii\base\BaseObject implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
public $role; //Deze dien je nog toe te voegen aan de User.php
```
Dit is alles en hiermee kan kan je aanloggen in het Yii systeem.
### Functionaliteiten afschermen
In elke controller staat bovenin een function behaviors(). Deze functie regelt de toegang tot de functies. Bijvoorbeeld:
```PHP
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
// when logged in, any user but yo need to be logged in!
[ 'actions' => ['student','create', 'update-status'],
'allow' => true,
'roles' => ['@'],
],
// when logged in and role = user
[ 'actions' => [ 'rolspeler', 'update', 'call-student' ],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return (Yii::$app->user->identity->role == 'user');
}
],
// when logged in and role = admin
[ 'actions' => [],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return (Yii::$app->user->identity->role == 'admin');
}
],
],
],
];
}
```
##### Toelichting
Het eerste gedeelte is standaard en daarin wordt bepaald dat een delete alleen mag worden aangeroepen via een POST (en dus niet via een GET). Dit is niet van belang voor onze role based security.
```PHP
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
```
Het gedeelte daaronder is wel van belang. We zien drie blokjes (elk blokje begint met 'actions').
In het eerste blokje wordt bepaald dat als je bent aangelogd dat je dan de functie *student*, *create* en *update-status* mag gebruiken.
```PHP
// when logged in, any user but yo need to be logged in!
[ 'actions' => ['student','create', 'update-status'],
'allow' => true,
'roles' => ['@'],
],
```
De regel` 'roles'=> ['@']` betekent iedereen die is ingelogd.
Je kunt ook `'roles'=>['?']` gebruiken en dat betekent iedereen die niet is aangelogd (*guest* user).
Meer uitleg kan je vinden op: [https://www.yiiframework.com/doc/guide/2.0/en/security-authorization](https://www.yiiframework.com/doc/guide/2.0/en/security-authorization)
Het tweede blokje bepaald dat als je bent aangelogd met de rol *user*, je de functie *rolspeler*, *update* en *call-student* mag gebruiken.
```PHP
// when logged in and role = user
[ 'actions' => [ 'rolspeler', 'update', 'call-student' ],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return (Yii::$app->user->identity->role == 'user');
}
],
```
Het derde blokje bepaald dat je alle acties (dus alle functies) kan gebruiken als he de rol *admin* hebt.
```PHP
// when logged in and role = admin
[ 'actions' => [],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return (Yii::$app->user->identity->role == 'admin');
}
],
```
### Opgave 1
Maak allereerst een menu voor jouw *coffee* app.
[](https://www.roc.ovh/uploads/images/gallery/2021-05/image-1621708382447.png)
Kijk in[ les 3](https://www.roc.ovh/books/yii/page/3-menu "Yii - Les 3, Menu") als je niet meer weet hoe je een menu moet maken.
### Opgave 2
Maak nu een drie logins: één admin en twee medewerkers Adam en jane.
Gebruik de volgende gegevens.
id
username
password
authKey
accesToken
role
100
admin
admin123
admin-key
admin-token
admin
200
Adam
geheim
adam-key
adam-token
user
201
Jane
wachtwoord
jane-key
jane-token
user
Pas de *User.php* in *models* aan. Kijk naar het voorbeeld dat in deze les is beschreven.
Je kunt de template die hieronder staat gebruiken.
```PHP
private static $users = [
'100' => [
'id' => '100',
'username' => '',
'password' => '',
'authKey' => '',
'accessToken' => '',
'role' => '',
],
'200' => [
'id' => '200',
'username' => '',
'password' => '',
'authKey' => '',
'accessToken' => '',
'role' => ''
],
'201' => [
'id' => '201',
'username' => '',
'password' => '',
'authKey' => '',
'accessToken' => '',
'role' => ''
],
];
```
### Opgave 3
Wie mag wat? Pas de rechten aan aan de hand van het volgende schema.
Create
Read (index)
Update
Delete
Medewerkers
admin
medewerker/admin2)
admin
admin
Menus
admin
iedereen1)
admin
admin
Bestelling
medewerker
iedereen1)
medewerker/admin2)
medewerker/admin2)
1)*Iedereen* betekent admin, medwerker of iemand die *niet* is aangelogd.
2)*medewerker/admin*, kan ook worden gezien als iemand die is aangelogd.
Bovenstaande tabel kun je ook zo vertalen:
Een **admin** kan
Medewerker
Read (index)
Create
Update
Delete
Menus
Read (index)
Create
Update
Delete
Bestelling
Read (index)
Create
Update
Delete
Een **medewerker/user** kan
Medewerker
Read (index)
Menus
Read (index)
Bestelling
Read (index)
Create
Update
Delete
Een **niet-ingelogde gebruiker/guest** kan
Medewerker
Menus
Read (index)
Bestelling
Read (index)
We gaan de toegang regelen voor de *create*, *index*, *update* en *delete* van de *medewerker*.
Ga naar de file *MedewerkerController.php* in de *controllers* en voeg de volgende code toe:
```PHP
class MedewerkerController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
// when logged in as admin
[ 'actions' => ['create', 'update', 'delete'],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return (Yii::$app->user->identity->role == 'admin' );
}
],
// when logged in, any user but you need to be logged in!
[ 'actions' => ['index'],
'allow' => true,
'roles' => ['@'],
],
],
],
];
}
....
....
```
Maak nu zelf de toegangscontrole voor de *MenuController.php* en de *BestellingController* af.
### More info
In
[https://www.roc.ovh/books/yii/page/login-via-db](https://www.roc.ovh/books/yii/page/login-via-db)
staat kort beschreven hoe je de gebruikers in de database kan vastleggen. Voor het examen is dit niet noodzakelijk.
\--
# 12. Issues
Deze opdracht maakt gebruik van een bestaand project waarbij sommige zaken ontbreken of kapot zijn. Aan jou de taak om ze op te lossen
Maak gebruik van het project op Github: [Garage](https://github.com/MeesterDaaf/yii-garage-issues)
1. Maak een Fork van de repository
[](http://roc.ovh/uploads/images/gallery/2021-06/Screenshot-2021-06-15-165045.png)
1. Clone (vanuit je eigen Github) het project naar je eigen computer
2. In de root folder van het project staat een bestand: `garage.sql`
3. Maak een database aan: `garage`
4. Importeer het garage.sql met phpmyadmin``
5. Open het project in VS Code
6. Run de volgende code: `composer update` (hiermee update je de benodigde pakketen voor dit project)
7. Start de server op met `php yii serve```
8. `Los de onderstaande issue op`: zorg ervoor dat je na elke oplossing een `commit maakt`
9. Als je klaar bent `push` je je werk naar Github``
##### Issues
1. Part pagina is niet zichtbaar
2. Bij maken Car is het mogelijk om klanten te selecteren maar we zien alleen voornamen, achternamen zou al veel beter zijn
3. In de appointment index staat onder Customer een getal. Hier moet een achternaam komen.
4. Bij maken van een reparatie worden de onderdelen (Part) niet goed weergegeven in de dropdown.
5. Als je een Appointment, Car of Reparatie wilt updaten dan ontstaat er een error.
6. Inloggen doet het niet vanwege een bug.
7. Alle pagina's zijn zichtbaar zonder inloggen: klant wil dit
8.
Index
Create
Update
Delete
Appointment
Alle medewerkers
Alle medewerkers
Admin/Manager
Admin
Car
Alle medewerkers
Alle medewerkers
Admin/Manager
Admin
Repair
Alle medewerkers
Alle medewerkers
Admin/Manager
Admin
Customer
Alle medewerkers
Alle medewerkers
Admin/Manager
Admin
Parts
Iedereen
Alle medewerkers
Admin/Manager
Admin
# 13. PDF genereren (optioneel)
Je kunt data exporteren naar bijvoorbeeld een excel bestand of PDF. Dit kan ook met YII maar daarvoor heb je wel een extentie nodig die dit voor je regelt. Hoe dat in zijn werk gaat dat zie je in dit hoofdstuk.
1\. Installeer de volgende extentie: **yii2-export** door de volgende command in de terminal van je project te zetten:
`composer require kartik-v/yii2-export "*"`
2\. Zorg ervoor dat de extentie in je project geactiveerd is. Open `web.php`
Voeg de onderstaande code toe achter 'components'
```PHP
'components' => [
],
'modules' => [
'gridview' => ['class' => 'kartik\grid\Module']
],
```
3\. Kies een Controller uit waar je de PDF-extentie wilt gebruiken. Stel bijvoorbeeld dat je een overzicht wilt printen van alle Projecten of alle Auto's. Je kunt in principe van alle *index* overzichten een pdf (of excel) maken.
In het voorbeeld hieronder maken we gebruik van een *AppointmentController*
Bovenin de controller zet je de volgende regel neer
`usekartik\export\ExportMenu;`
4\. We verbouwen de boel een beetje zodat de logica klopt. In de view index.php wordt de gridview aangemaakt. Dit gaan we aanpassen
Van dit:
Naar dit: Hiermee worden de kolommen van de tabel niet aangemaakt in de view index.php maar in de controller zelf.
```PHP
= \kartik\grid\GridView::widget(
[
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => $gridColumns,
],
);
// Renders a export dropdown menu
echo $menu;
?>
```
5\. Omdat we een overzicht willen hebben van alle Afspraken, dus de index, gaan we naar de method *actionIndex()* van de desbetreffende controller (in dit voorbeeld de AppointmentController.
```PHP
// AppointmentController.php
$gridColumns = [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'appointment_id',
'label' => 'Appointment',
'value' => 'appointment.name'
],
[
'attribute' => 'part_id',
'label' => 'Part',
'value' => 'part.name'
],
['class' => 'yii\grid\ActionColumn'],
];
$menu = ExportMenu::widget([
'dataProvider' => $dataProvider,
'columns' => $gridColumns
]);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'gridColumns' => $gridColumns,
'menu' => $menu,
]);
```
# FAQ
#### Hoe maak ik een link met Yii?
```PHP
use yii\helpers\Html;
...
Html::a('Naam van de link', ['/controller/method','id'=>'1','param2'=>'waarde'],['title'=> 'Edit',]);
```
Dit resulteert in de link met de naam 'Naam van de link' die verwijst naar link /controller/method?id=1¶m2=waarde
Verder die je de tekst 'Edit' als je een met de muis over de link gaat (mouse over).
#### Hoe maak ik een button in Yii?
```PHP
use yii\helpers\Html;
...
= Html::a('Cancel', ['index'], ['class'=>'btn btn-primary', 'title'=> 'Mouse over Text',]) ?>
= Html::a('Ok', ['create'], ['class' => 'btn btn-success', 'title'=> 'Mouse over Text',]) ?>
```
Bootstrap button styles: [https://getbootstrap.com/docs/4.0/components/buttons/](https://getbootstrap.com/docs/4.0/components/buttons/)
#### Hoe verander ik de standaard home page in Yii?
Twee mogelijkheden:
1. Standaard staat de home page in de site view index, views/site/index.php. Pas deze file aan.
2. De controller SiteController.php wordt standaard uitgevoerd. Je kan hier dus een verwijzing naar andere home pagina maken. Zie voorbeeld hieronder.
```PHP
public function actionIndex()
{
return $this->redirect(['/maaltijd/index']);
}
```
De home page is nu /maaltijd/index.
#### Hoe kan ik vanuit Yii naar de vorige pagina?
```PHP
use yii\helpers\Html;
...
= Html::a( 'Cancel', Yii::$app->request->referrer , ['class'=>'btn btn-primary']); ?>
```
#### Hoe kan ik selecteren en sorteren?
```PHP
$countries = Country::find()->where(['Continent' => 'Europe'])
->andWhere('SurfaceArea>1000000')->orderBy(['Name' => SORT_ASC])->all();
```
Hierbij selecteer je alle countries waarbij Continent = 'Europe' and waar SurfaceArea>1000000, gesorteerd op Name (oplopend, dus a...z).
#### Hoe kan ik in Yii invoercontrole instellen?
Dit bepaal je in je model, bijvoorbeeld:
```PHP
public function rules()
{
return [
[['population', 'average_age'], 'integer'],
[['children_count'], 'integer', 'min' => 0, 'max' => 5],
[['first_name', 'last_name'], 'string', 'max' => 35],
[['from_date', 'to_date'], 'date'],
[['opmerking', 'extra_opmerking'], 'default', 'value' => null],
[['email'], 'email'],
];
}
```
Meer info:
[https://www.yiiframework.com/doc/guide/2.0/en/tutorial-core-validators](https://www.yiiframework.com/doc/guide/2.0/en/tutorial-core-validators)
en
[https://www.yiiframework.com/doc/guide/2.0/en/input-validation](https://www.yiiframework.com/doc/guide/2.0/en/input-validation)
# Trouble Shooting Yii Installatie
Eerste hulp bij installatie issues.
Yii is eigenlijk alleen afhankelijk van PHP. Als Yii dus niet werkt dan moet er worden gecontroleerd of de goede versie van XAMPP is geïnstalleerd en of deze versie ook daadwerkelijk wordt gebruikt.
#### Stap 1, nieuwst XAMPP
Controleer XAMPP, alles is getest met de onderstaande versie, zorg dat je deze versie of nieuwer heb geïnstalleerd en dat oude versie zijn verwijderd.
[](https://www.roc.ovh/uploads/images/gallery/2020-09/image-1600615612510.png)
#### Stap2, welke php wordt gebruikt?
Om dit te controleren maken we een nieuwe file *test.php* en zetten deze in de web directory van het Yii project. In opgave 1 van de lessen, heet het project *world* dus we plaatsen de file *test.php* in de directory *world/web*.
Meestal is het path dus voluit *c:\\XAMPP\\htdocs\\world\\web,* maar dit kan per installatie verschillen.
In de file *test.php* komt het volgende te staan:
```
```
Start nu je yii server op (*php yii serve*).
In de browser ga je naar [http://localhost:8080/test.php](http://localhost:8080/test.php)
Je ziet nu alle instellingen van de PHP server.
[](https://www.roc.ovh/uploads/images/gallery/2020-09/image-1600616185913.png)
De geel gemarkeerde dingen zijn belangrijk. De eerste laat zien dat PDO is geïnstalleerd:
```
"--with-pdo-oci=c:\php-snap-build\deps_aux\oracle\x64\instantclient_12_1\sdk,shared"
```
De tweede laat zien welke PHP wordt gebruikt.
```
Loaded Configuration File C:\xampp\php\php.ini
```
Ziet dit er anders uit dan heb je mogelijk een andere PHP versie nog geïnstalleerd of die heb je geïnstalleerd gehad. Haal deze weg of de-installeer deze.
#### Stap 3, path
Ga naat je *cmd box* en type *path*.
Zoek in het de output van dit commando naar:
```
C:\xampp\php
```
Lastig zoeken? Kopieer de hele output naar *notepad* en gebruik de zoekfunctie van *notepad* en zoek naar *php*. Contoleer ook of er niet twee maal een path naar php bestaat (php komt als het goed is precies één keer voor).
Klopt het path niet dan kan je dat als volgt aanpassen.
1. ga naar *control panel*
2. zoek (rechtsbovenin) naar *environment*
[](https://www.roc.ovh/uploads/images/gallery/2020-09/image-1600616724024.png)
3. Klik op "Edit the system environment variables"
4. Klik op knop "Environment Variables"
[](https://www.roc.ovh/uploads/images/gallery/2020-09/image-1600617058469.png)
5. Je hebt nu twee schermen (boven en onder). Zoek waar je *path* staat en pas het aan.
6. Had je geen *path*? Maak dan een nieuwe entry in de system variables (onderste gedeelte van het scherm).
Je moet nu herstarten of uitloggen/opnieuw aanloggen.
Controleer dan opnieuw in een cmd box met het commande *path* het *path* goed staat.
\--
### XAMPP opstarten of afsluiten geeft foutmelding
Bij het afsluiten van XAMPP krijg je een foutmelding die zegt dat het bestand xampp-control.ini niet kan worden overschreven.
Je kunt dit verhelpen door de inhoud van deze file eerst te kopiëren, dan de file weg te gooien en daarna een nieuwe xampp-control.ini aan te maken. Zet daarin de originele inhoud, die je hebt gekopieerd terug.
### De CRUD en Model page werkt niet
Je gaar naar [http://localhost:8080/gii](http://localhost:8080/gii) en er gebeurt niets.
Heb je de *urlManager* in web.php goed geconfigureerd (zie uitleg in les1)?
### Gii werkt niet
Als je gii oproept dan zie je de Yii home page.
Check config/web.php is op regel 47 is dit stukje uncommented?
\--
I put this in the page content for our homepage rather than in the custom HTML header where you'd only want:
# Bijlagen, Notes en Voorbeelden
Voorbeelden stukjes code
# Unsorted Notes
### Voor- nadelen Laravel v. Yii
Laravel
YII
MVC
✓
✓
Model
Eloquent
Active Record
View/templating
Blade
PHP met 'Yii Snippets'
Routing
Expliciet
Impliciet / Expliciet
Migrations
✓
✓ (meer als optie)
Model creations
command line
GUI, reverse engineered form DB
Controller Creation
command line
GUI, create full CRUD
View creation
?
GUI, create full CRUD
Documentation
\*\*\*
\*\*
Active development
✓
✓
Add Ons / Libraries
\*\*\*
\*\*
Install Base (volgens Google)
484,970
58,800
Grootste voordeel is de GUI waarmee je reverse engineered een CRUD maakt.
### Install Datepicker
(in project root)
change in file composer.dev "minimum-stability": "dev",
```
composer clear-cache
composer require kartik-v/yii2-widget-datepicker
```
[https://github.com/kartik-v/yii2-widget-datepicker](https://github.com/kartik-v/yii2-widget-datepicker)
##### Create (temporary swap on Ubuntu)
```
free -m
total used free shared buffers cached
Mem: 2048 357 1690 0 0 237
-/+ buffers/cache: 119 1928
Swap: 0 0 0
```
```
/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
/sbin/mkswap /var/swap.1
/sbin/swapon /var/swap.1
```
[https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors](https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors)
### Install Bootstrap 4
```
composer require --prefer-dist yiisoft/yii2-bootstrap4
```
### Redirect
```PHP
return $this->redirect(['view', 'id' => $model->id]);
```
### Post form on dropdown change
```PHP