dinsdag 15 juli 2008

Deel 9: Een groepsnaam wijzigen

Dit keer gaan we de groepen afwerken. Ik wil twee icoontjes bij elke groep plaatsen één voor wijzigen en één voor verwijderen van een groep.
Als voorbeeld gebruik ik de bake tool om een werkend voorbeeld te hebben van de CRUD (Create, Read, Update, Delete) functies.

Eerst maar eens een link per groep om deze te kunnen wijzigen en te verwijderen. Ik heb ervoor gekozen een icoontje voor de groepsnaam te plaatsen en zo de actie te triggeren. Daarvoor kunnen we de table functies gebruiken die deel zijn van de html helper.
Kies daarom leuk kleine plaatjes om als link naar de edit- en addactie te gaan dienen en plaats het in webroot/img.

Open views/groups/index.ctp.
Om een link van een plaatje te maken moeten een combinatie van html->link en html->img gebruiken:

$cells = array();
foreach($groups as $groupSet):
foreach($groupSet as $k => $group):
array_push($cells, array(
// edit link voor deze groep
$html->link(
$html->image('/img/edit.png', array('alt' => 'Edit groepnaam', 'border'=>'0')),
'/groups/edit/'.$group["id"],
array(), false, false
),
// delete link voor deze groep
$html->link(
$html->image('/img/delete.png', array('alt' => 'verwijder groep', 'border'=>'0')),
'/groups/delete/'.$group["id"],
array(), false, false
),
// doorklikken naar de links van deze groep
$html->link($group["naam"],array("controller"=>"Links", "action"=>"index/".$group["id"]."?groepsnaam=".urlencode($group["naam"])))
));
endforeach;
endforeach;
// tabelletje op het scherm zetten
echo "<table>";
echo $html->tableCells($cells);
echo "</table>";

Het gebruik van deze helpers zorgt ervoor dat altijd geldige html wordt gegenereerd. De tabel zorgt dat de icoontjes netjes naast de groepnamen komen te staan.
De helper $html->tableCells() maakt van een array een serie TR's en TD's:
$html->tableCells(array(array(1,2,3), array(4,5,6), array(7,8,9)));
genereert de volgende code:

<tr><td>1</td> <td>2</td> <td>3</td></tr>
<tr><td>4</td> <td>5</td> <td>6</td></tr>
<tr><td>7</td> <td>8</td> <td>9</td></tr>

Daar hoeft dus alleen nog een table omheen. De actie voor een nieuwe groep zullen we ook gelijk aanpassen, dat wordt verderop gebruikt:
link("Nieuwe groep", array("controller"=>"Groups", "action"=>"add"));?>
Vraag het scherm op via de webinterface om te zien hoe de groepen er nu uitzien.



Nu de view in orde is, hebben we de controller nodig.
Hernoem de huidige group_controller.php in controllers om te voorkomen dat ie overschreven wordt.
Open een DOS box en ga naar je programma directory. Daar type je
cake bake
om de utility te openen.
Kies Controller -> Group,
- interactive: n
- include basic class methods: y
- admin routing: n
- Look Okay?: y
- unit test files: n
In de controllers dir is nu een nieuwe groups_controller.php gemaakt met daarin een method voor add() edit() en delete() (en nog wel wat meer, maar dat hebben we niet nodig). Hernoem groups_controller.php naar groups_controller_baked.php, en herstel de vorige groups_controller.php in de originele staat.
Nu eerst een klein uitstapje. In de controller wordt gecontroleerd of de gebruiker ingelogd is. Na dat geconstateerd te hebben kunnen we eigenlijk gelijk de layout wijzigen naar "ingelogd". Open het oorspronkelijke groups_controller bestand. Kopieer
$this->layout = "loggedin";
uit de index() functie naar de __validateLoginStatus() functie, en wel als we zeker weten dat er is ingelogd:

function __validateLoginStatus(){
if($this->action != 'login' && $this->action != 'logout'){
if(!$this->Session->check('User')){
$this->Session->setFlash('Om deze pagina te bekijken moet je eerst inloggen');
$this->redirect('/users/login');
}
$this->layout = "loggedin";
}
}

In andere methods is dit nu dus niet meer nodig.
Nu de edit() en delete() functies en nu we toch bezig zijn gaan we de add() functie refactoren, naar voorbeeld van de bake actie.
Er is maar een kleine aanpassing nodig:

$user = $this->Session->read('User');
$this->set("user_id", $user['id']);

Dit komt in plaats van de koppeling van de user die bake heeft gemaakt. Verder kun je de methods add() edit() en delete() kopiëren. De functie nieuwe_groep() is niet meer nodig en mag opgeruimd worden. Rest ons nog om twee views toe te voegen, 1 voor edit en een voor add. Deze views zijn precies hetzelfde als de bestaande view nieuwe_groep.ctp. Hernoem dat bestand naar edit.ctp en maak er een kopie van die je add.ctp noemt. De code zelf hoeft niet aangepast te worden. Let op de forms die op je scherm komen, ze posten automatisch naar de juiste controller-action.

He group-gedeelte is nu af. (dwz, alles werkt). Het was sneller geweest direct de bake utility te gebruiken, maar nu heb ik veel meer geleerd. Het onderhouden van de links in groepen zal nu niet veel problemen meer opleveren. Ik heb nog even de favicon veranderd (in /webroot) hier is de code tot nu toe.

maandag 14 juli 2008

Deel 8: Nieuwe groep aanmaken

Om een nieuwe groep aan te maken moeten we weten voor welke user. Als dat meegestuurd wordt in de POST kan het Cake DBO de nieuwe entry opslaan.
Eerst maar eens een link om de aktie om een nieuwe groep aan te maken te starten:
open views/groups/index.ctp en voeg deze regel toe:

<?php echo $html->link("Nieuwe groep", array("controller"=>"Groups", "action"=>"nieuweGroep"));?>

We kunnen nu de te nemen stappen door CAKE laten melden in debus informatie.
Start de groepen pagina en klik de "Nieuwe groep" link. Cake meldt nu dat er een method nieuweGroep() wordt verwacht in de controller GroupsController. Het skelet van de functie wordt meegegeven. Neem dus deze functie op in groups_controller.php:

/**
* Een nieuwe groep creeren
* @return
*/
function nieuweGroep() {
$user = $this->Session->read('User');
$this->set("user_id", $user['id']);
$this->layout = "loggedin";
}

De userID zit in de sessie, en die hebben we nodig. Verder gebruiken we de layout loggedin om te zorgen dat het menu verschijnt, inclusief de uitleggen link.
Druk op F5 om te refreshen en nu blijkt dat we een view missen: \views\groups\nieuwe_groep.ctp
Maak het gevraagde bestand aan. Daar moet een invulformulier op komen.

<h3>Nieuwe groep</h3>
<div id="formwrapper">
<?php echo $form->create(); ?>
<?php echo $form->input("naam", array("label"=>"Groepnaam"));?>
<?php echo $form->input("users_id", array("type"=>"hidden", "value"=> $user_id)); ?>
<?php echo $form->end("Opslaan"); ?>
</div>

Ik gebruik weer de formwrapper DIV om de uitlijning van de velden te regelen.
Verder verschijnt het hidden veld met de userID die doorgegeven wordt door de controller. Als we naar de bron van de pagina kijken, blijkt het formulier te posten naar groups/add. De controller verwacht dus een add() method in de groups-controller.
We maken deze method aan in groups_controller.php met de volgende body:
 
/**
* opslaan van een nieuwe groep
* @return
*/
function add(){
if(!empty($this->data)){
if($this->Group->save($this->data)){
$this->Session->setFlash("Groep opgeslagen");
} else {
$this->Session->setFlash("Fout bij opslaan van groep");
}
}
$this->redirect("/groups/index");
}

Nu kun je een nieuwe groep aanmaken in de database.

vrijdag 4 juli 2008

Tussendeel: een stukje refactoren

Hoe meer ik lees over CakePHP hoe meer ik zie dat ik wat te veel heb overgeslagen. Nu dan maar even een kort stukje refactoring.

Om beter gebruik te maken van de form-helper en eindelijk een einde te maken aan die tables die een form zo groot maken, heb ik maar eens gekeken of ik een standaard manier kan vinden om het uitlijn effect van een table zo goed mogelijk na te bootsen in CSS. Een bijkomend voordeel is dat ik de form helper veel meer kan laten genereren en de code dus compacter wordt.
Na lezen over de form-helper in de docs (rtfm) heb ik het inlog formulier teruggebracht naar het volgende:
\views\users\login.ctp

<h2>Inloggen</h2>
<div id="formwrapper">
<?php echo $form->create('User', array('action' => 'login'));?>
<?php echo $form->input("username");?>
<?php echo $form->input("password");?>
<?php echo $form->end("Login"); ?>
</div>

Het meeste wat hierboven staat is vast duidelijk. De inputs leveren een label op + het input veld, zoals hieronder:
<div class="input text">
<label for="UserUsername">Username</label>
<input name="data[User][username]" type="text" value="" id="UserUsername" />
</div>

De $form->end() levert een </form> op én een submit-button.
Om dat netjes uitgelijnd te krijgen heb ik wat meer CSS nodig:

\webroot\css\stijlen.css

#formwrapper{
width: 350px;
border: 1px solid black;
text-align: right;
}
div > label{
float:left;
}
input[type=text]{
width: 15em;
}
input[type=password]{
width: 15em;
}

De truuk is als volgt: de wrapper, die de beschikbare breedte voor het form bepaalt, daarbinnen rechts uitlijnen voor de input-velden en een float:left voor de labels. Werkt in elk geval in msie 7. ff 3 en opera 9. De vaste breedte van de wrapper kan nog een probleem opleveren: we'll cross that bridge when we get to it...
Verder hoeft niets te worden gewijzigd: wat een mooie scheiding van presetatie en business logica! Van 30 naar 7 regels in 5 minuten...

dinsdag 1 juli 2008

Deel 7: Groepen links opvragen

De volgende stap is het ophalen van de link groepen van een user.
De groepen staan in de groups tabel. Er is een 1:n relatie met de users tabel of, in CakePHP termen:
een group belongs-to een user
Dit is gemodelleerd in een FK relatie van group naar user. In het model wordt dit direct aangegeven, wat als voordeel heeft dat bij een query naar de groupen ook de users gegevens worden opgehaald. Nadeel s de overhead.

Open een dos-box en cd naar je scolafavs dir. Type
cake bake
en kies het maken van een model.
Kies ervoor een model association aan te geven. Cake ziet dat het waarschijnlijk om de users tabel gaat.

---------------------------------------------------------------
Possible Models based on your current database:
1. Group
2. Link
3. User
Enter a number from the list above, type in the name of another model, or 'q' to exit
[q] > 1
Would you like to supply validation criteria for the fields in your model? (y/n)
[y] > n
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)? (y/n)
[y] > y
One moment while the associations are detected.
---------------------------------------------------------------
Please confirm the following associations:
---------------------------------------------------------------
Group belongsTo Users? (y/n)
[y] > y
Would you like to define some additional model associations? (y/n)
[n] > n

Open het gegenereerde bestand en voeg de volgende method toe:

/**
* Haal de groepen van een user op
* @return
* @param $data Object
*/
function getMyGroups($data){
$groups = $this->findAllByUsersId($data['user_id']);
if(!empty($groups)) {
return $groups;
}
return false;
}

Heel eenvoudig en portable. 1 method om de linkgroepen van een user op te halen. De findAllBy... method wordt door het CakePHP model verzorgd.

Nu de controller. Maak een bestand groups_controller.php in /controllers en neem de volgende index() method op:

/**
* Haal standaard de link groepen van een user op
* @return
*/
function index(){
$this->layout = "loggedin";
$data["user_id"] = $this->Session->read('User');
// haal de groepen van deze user op
$this->set("groups", $this->Group->getMyGroups($data));
}


De gebruiker moet ook nog naar de pagina kunnen navigeren. Daarom hebben we een aantal links nodig, die pas na inloggen getoond moeten worden. Daarvoor is de regel
$this->layout = "loggedin";
Deze regel zorgt ervoor dat we in plaats van de layout "default" nu de layout "loggedin" gaan tonen. Die moeten we dan wel hebben. Creëer het bestand loggedin.ctp onder /views/layouts. Ik heb er de volgende code in staan:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<?php echo $html->charset(); ?>
<title>ScolaFavs</title>
<?php
echo $html->css('stijlen');
echo $scripts_for_layout;
?>
</head>
<body>
<div id="container">
<div id='menu'>
<?php echo $html->link("Home", array('controller' => 'Users', 'index' => 'logout')); ?>
<?php echo $html->link("Mijn Groepen", array('controller' => 'Groups', 'action' => 'index')); ?>
<?php echo $html->link('Logout', array('controller' => 'Users', 'action' => 'logout')); ?>
</div>
<div id="content">
<?php
if ($session->check('Message.flash')):
$session->flash();
endif;
echo $content_for_layout;
?>
</div>
</div>
<?php echo $cakeDebug?>
</body>
</html>


Nu nog de view voor de linkgroepen. Maak een bestand index.ctp aan onder /views/groups en vul 'm bijvoorbeeld zo:

<h3>Mijn Groepen!</h3>
<?php
foreach($groups as $groupSet){
foreach($groupSet as $k => $group){
if($k == "Group"){
echo $html->link(">> " . $group["naam"],"/groups/getLinks/".$group["id"]) . "<br/>";
}
}
}
?>


En tenslotte breiden we de onbeveiligde homepage uit met een link naar de inlogpagina:
views/pages/home.ctp

<h3>Welkom bij ScolaFavs!</h3>
<br/>
klik hier om in te loggen
<br/>
<?php
echo $html->link("Inloggen", array("controller"=>"Users", "action"=>"login"));
?>
<br/>
Meer informatie over deze applicatie kun je hier lezen...

Als alles goed is gegaan kun je nu via de bekende URL de applicatie starten en, na inloggen, je groepen opvragen.

Een ding hebben we overgeslagen: de groups_controller is niet beveiligd. Beveiligen is echter een kwestie van vooraf bekijken of de sessie een user bevat. hoewel dit wel een beetje inbraakgevoelig is, houden we het hier even op.

Neem deze twee functies op in de groups_controller om de controller te beveiligen:

function beforeFilter() {
$this->__validateLoginStatus();
}

function __validateLoginStatus(){
if($this->action != 'login' && $this->action != 'logout'){
if(!$this->Session->check('User')){
$this->Session->setFlash('Om deze pagina te bekijken moet je eerst inloggen');
$this->redirect('/users/login');
}
}
}

We gebruiken dus de code in de users_controller als nog niet is ingelogd door een forward naar de users controller en daarvan de login actie. Als er wel is ingelogd doet de validatie-method verder niets.

maandag 23 juni 2008

Deel 6: gebruikers autoriseren

Apache werkt, php werkt, Cake werkt, database klaar, daar gaat ie dan.
- Maak een werkdirectory onder je devel directory, genaamd scolafavs
- Maak een virtual host aan in C:\devel\EasyPHP\apache\conf\extra\httpd-vhosts.conf en in c:\windows\system32\drivers\etc\hosts
- herstart apache
- ga in devel\scolafavs staan en type
cake bake
creëer hiermee je applicatie skeleton en database connectie script. Hierna moet je via http://scolafavs/ de maagdelijke applicatie op kunnen vragen, en wel met allemaal groene balken (geen foutmeldingen).

Erg mooi vind ik die pagina niet, maar wel heel functioneel. Laten we eens naar de opmaak kijken. In de directory views/layouts staat het bestand default.ctp. Een ctp bestand in een cake template, hier wordt bepaald hoe de pagina's (die van deze layout gebruik maken) eruit komen te zien. Je kunt de pagina openen in een wysiwyg editor zoals macromedia, sorry adobe dreamweaver, of gratis: microsoft visual webdeveloper express ed en zo zijn er nog wel een paar. Maak er een leuke layout van. Bij mij zien head en body er even zo uit:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<?php echo $html->charset(); ?>
<title>
ScolaFavs
</title>
<?php
echo $html->css('stijlen');
echo $scripts_for_layout;
?>
</head>
<body>
<div id="container">
<div id="content">
<?php
if ($session->check('Message.flash')):
$session->flash();
endif;
echo $content_for_layout;
?>
</div>
</div>
<?php echo $cakeDebug?>
</body>
</html>


Ik heb er een externe css voor gemaakt die geplaatst is in webroot\css. Laat de variabele $cakeDebug en Message.flash vooral staan, ze kunnen je helpen. In productie verhoog je het debuglevel, zodat foutmeldingen niet doorkomen naar de eindgebruiker. In $content_for_layout komt de content te staan die een view produceert.

De applicatie moet gebruikers herkennen, daarom hebben we een inlogsysteem nodig.
Als basis gebruik ik dit artikel uit de bakery, de CakePHP documentatie.
De users tabel gaat de users van de applicatie herbergen (duhhh). Ik moet nog steeds wennen aan wat nu precies in enkelvoud en wat in meervoud moet (en dat is wel zo handig om ook zo te doen!), daarom heb ik er een klein schemaatje van gemaakt:


Wat hebben we concreet nodig: er is een users tabel (meervoud) die wordt benaderd via een user model (enkelvoud) die wordt aangestuurd door een users_controller die weer naar de bezoeker gaat via views/users/index.ctp of login.ctp als nog niet is ingelogd (de dirname is meervoud). confused? Toch is het prettig als je dit gewoon zo doet dat cake zonder meer weet waar alles staat en hoe alles heet zodra je de users controller benadert.

Een users tabel hebben we al, daar moet dus een model omheen geplaatst worden om de toegang naar de database te regelen. We laten Cake zelf het model bakken.

Open nu het bestand models/user.php en pas het als volgt aan:
<?php 
class User extends AppModel {
var $name = 'User';

function validateLogin($data) {
$user = $this->find(array('un' => $data['username'],
'pw' => md5($data['password'])),
array('id', 'un'));
if(!empty($user)) {
return $user['User'];
}
return false;
}
}
?>

Een opmerking hierbij: Het is niet altijd duidelijk of een dergelijke functionaliteit nu in de controller of in het model moet worden geregeld. Ik voel wel voor deze oplossing omdat er alleen een databasequery plaatsvindt. De $data wordt doorgegeven door de controller die als enige iets met POST en GET requests te maken heeft. Het valideren van een login is volgens een andere leerschool echter iets voor in de controller.

Nu volgt dan de controller:
Dit keer zullen we hem zelf maken. Creëer een nieuw bestand in de controllers directory dat je users_controller.php noemt. Het bestand krijgt de volgende inhoud:
<?php
class UsersController extends AppController {
var $name = "Users";
var $helpers = array('Html', 'Form');

function index() {}

function beforeFilter() {
$this->__validateLoginStatus();
}

function login() {
if(!empty($this->data)) {
if(($user = $this->User->validateLogin($this->data['User'])) == true) {
$this->Session->write('User', $user);
$this->Session->setFlash('Je bent ingelogd.');
$this->redirect('index');
exit();
} else {
$this->Session->setFlash('De inloginformatie is niet correct.');
$this->redirect('login');
exit();
}
}
}

function logout(){
$this->Session->destroy('user');
$this->Session->setFlash('Je bent uitgelogd.');
$this->redirect('login');
}

function __validateLoginStatus(){
if($this->action != 'login' && $this->action != 'logout'){
if(!$this->Session->check('User')){
$this->Session->setFlash('Om deze pagina te bekijken moet je eerst inloggen');
$this->redirect('login');
}
}
}
}
?>

Een paar opmerkingen hierbij.
De method beforeFilter() wordt automatisch uitgevoerd als je een controllermethod aanroept, welke dan ook. Dit is dus een goede plaats om te zorgen dat de autorisatie plaatsvindt. De autorisatie zelf komt in een functie __validateLoginStatus die begint met __ om 'm 'private' te maken. Het valideren van de inloggegevens gebeurt door de zojuist gemaakte functie in het model aan te roepen. Uitloggen is een kwestie van de sessie opruimen. Andere pagina's die beveiligd zijn kunnen gebruikmaken van dezelfde check. Over het algemeen zullen alle controlleractions of beveiligd, of niet beveiligd zijn.

Rest nog de views, 1 voor het inlogscherm en 1 voor als het inloggen gelukt is:
Maak twee bestanden in views\users: index.ctp en login.ctp
Hierin staan dus geen <html> enzo, dat staat in layouts/default.ctp. Het volgende staat er wel in:


views\users\login.ctp
<div class="login">
<h2>Login</h2>
<?php echo $form->create('User', array('action' => 'login'));?>
<table>
<tr>
<td>
<?php
echo $form->input('username', array(
'label'=>'username:</td><td>'
));
?>
</td>
</tr>
<tr>
<td>
<?php
echo $form->input('password', array(
'label'=>'password:</td><td>'
));
?>
</td>
</tr>
<tr>
<td colspan='2' align='right'>
<?php echo $form->submit('-login-');?>
</td>
</tr>
</table>
<?php echo $form->end(); ?>
</div>

views\users\index.ctp

<?php echo $html->link('Logout', array('controller' => 'Users', 'action' => 'logout')); ?>
<br/><br/>
You've accessed the secret secure location!


Het loginschermpje wilde ik netjes opmaken, waardoor een beetje extra code nodig was tov het eerder genoemde artikel.

Tenslotte is natuurlijk ook wat databasevulling nodig (initiele gebruikersaccounts, een paar links en een paar groepen) die je hier kunt downloaden. Om de controller starten: http://scolafavs/users/
De controller zal de index starten, maar daarvoor de validatie uitvoeren. Omdat er nog niet is ingelogd wordt geforward naar de loginpagina. Nu kun je inloggen en de index wordt getoond.

De volledige code staat hier

vrijdag 13 juni 2008

Deel 5: de database voor ScolaFavs

Om verder te gaan heb ik een applicatie in mijn hoofd waarmee gebruikers links in groepen kunnen plaatsen en zo altijd het setje favorieten bij zich hebben. Verder (later) moet het mogelijk worden een pagina met link-groepen te kunnen delen onder users. Ik noem deze applicatie ScolaFavs.

Mysql Workbench
Ik heb voor het ontwerp van de database maar eens gekozen voor open source tool: MySql Workbench. Ik moet zeggen: een erg mooie tool. (let op: op dit moment alleen nog onder windows te krijgen, voor linux kun je DBDesigner 4 gebruiken (eveneens open source), die blijft beschikbaar totdat workbench ook voor linux het levenslicht ziet).
Na installeren en opstarten verschijnt het hoofdscherm met een lege database erin die mydb heet. Dat lijkt niet wat we willen dus rechtsklikken op het databasesymbool en kies edit schema.

Ik heb de database scolafavs genoemd. Nu we hier toch zijn kunnen we gelijk de charset van de database op utf8 zetten (utf8-genral-ci). Nu gaan we het ERD schema zelf tekenen. Dubbelklik op add diagram. Er wordt een nieuw scherm geopend om het schema op te tekenen. Klik nu op het icoontje dat eruit ziet als een tabelletje (Place a new table). De muiscursor verandert nu als je boven het werkplaat beweegt, in een handje met een tabelletje. Plaats de tabel nu door op het werkblad te klikken. Door op het vlakje met table1, de lege tabel, te dubbelklikken opent zich onderin het scherm een serie tabbladen waarmee de naam van de tabel kan worden ingevoerd en de velden in de tabel. Vul nog niet de relaties-velden (FK) in, dat gaat straks automatisch.
De tabellen zien er nu zo uit:

links(id, naam, url)
groups(id, naam)
users(id, naam, un, pw)

id is steeds int, PK en autonumber (checkbox AI) en dus ook not null (checkbox NN)
Let op: de tabelnamen zijn in meervoud, omdat CakePHP ze zo verwacht en dan weet hoe het model moet worden gemaakt.

Nu de FK relaties. Eerst gaan we controleren hoe de gegenereerde FK-velden zullen worden genoemd. Opnieuw, om optimaal van de active recordset van CakePHP gebruik te maken moeten de foreign keys van de vorm ..._id zijn (waarbij op de ... de tabelnaam verschijnt waarmee gelinkt wordt) in plaats van id_.... Tevens moet de primary key van de tabellen id heten.

Om zeker te weten dat dit naar wens gaat moet je de settings bekijken (tools > options).

Een user heeft n groepen en die bestaan weer uit n links.
Kies "place a new 1..n non-identifying relationschip" (icoontje 6e van onder, identifying is voor gedeeltelijke relatie in een n:m tabel). Kijk in de statusbalk (please select the table to receive the foreign key). Klik op de 'links' tabel, in de statusbalk verschijnt nu select the referenced table. Klik op de 'groups' tabel. De relatie wordt getekend. Zo kan de tweede relatie tussen 'groups' en 'users' ook getekend worden. Het model ziet er nu zo uit:

Om dit model om te zetten in een .sql bestand, kies File > export > forward engineer CREATE script. In de popup: Generate DROP TABLE en kies een outputnaam (bijv. D:\scolafavs.sql) > next > finish
Nu heb je een mysql-script (.sql) waarmee je de database kunt vullen. Je kunt hiervoor phpmyadmin gebruiken. Je hoeft niet eerst een database aanmaken, er wordt een gemaakt die scolafavs heet, als je tenminste de database zo genoemd hebt (bij edit schema, hierboven). We zijn klaar om terug te gaan naar CakePHP!

Het complete Mysql Workbench bestand is hier te downloaden, maar zelf maken is natuurlijk leuker!

dinsdag 10 juni 2008

Deel 4: Controller en View, je eerste applicatie

Na de M komen de C en de V

De controller: ga naar devel\projects\social\3_bouw en type cake bake
Kies nu c en volg de voorbeelden op het scherm.


De v gaat in een moeite door. Hierna heb je eencomplete applicatie, maar niet "productierijp".


De applicatie kan opgevraagd worden via een webbrowser: