Ik ben bezig met het ontwikkelen van een eigen MVC. Via htaccess stuur ik alles door naar mijn index. Mijn index bepaalt vervolgens welke controller moet worden aangeroepen. Stel mijn url is /nieuws/nieuwsitem. In dit geval moet de NewsitemController worden aangeroepen om het nieuwsitem te tonen. Stel mijn URL is /over-ons. Dan moet de ContentController worden aangeroepen en een contentpagina getoond worden. Maar nu mijn vraag.. Hoe weet index welke controller moet worden aangeroepen?
<?php
// controllers/newsitem.php
class NewsitemController extends Controller
{
private _model;
public function __construct()
{
$this->_model = new NewsitemModel();
}
public function getLatest()
{
return $this->_model->getLatest();
}
}
// models/newsitem.php
class NewsitemModel extends Model
{
public function getLatest()
{
$select = "SELECT * FROM newsitems ORDER BY id DESC";
$query = $this->_database->query($select);
if($query->rowCount() > 0)
{
return $query->fetchAll();
}
}
}
$controller = new NewsitemController();
$newsitems = $controller->getLatest();
?>
@Ozzie,
Klopt, had ik al gezien. Heb mijn post al aangepast :)
Hoe zit dit dan verder met de route?
Stel mijn url is /nieuws, dan wil ik een overzicht tonen van alle nieuwsitems. Stel mijn url is /nieuws/dit-is-mijn-eerste-nieuwsitem, dan wil ik het specifieke nieuwsitem tonen. En zo verder...
Ja, precies: je kunt nu honderden of duizenden applicaties tegelijk verbouwen door alleen die ene controller te herschrijven.
Als je meerdere nieuwsitems hebt, wat niet onwaarschijnlijk klinkt, kun je er beter nog een controller naast zetten. De methode getLatest() heeft binnen één nieuwsitem zelf immers geen betekenis. Er is geen laatste nieuwsitem binnen één nieuwsitem.
Wel kunnen ze eventueel hetzelfde model delen: dáárin dient de methode getLatest() een duidelijk doel, net zoals bijvoorbeeld getPrevious() en getNext() om te bladeren.
Google anders maar eens op het data mapper pattern en het factory method pattern. Een factory is een oplossing voor wat je nu met getLatest() doet: je wilt niet zomaar een nieuwsitem, maar specifiek het laatste nieuwsitem. Dat is in alle opzichten identiek aan andere nieuwsitems, met één verschil: het is het item met de laatste publicatiedatum en -tijd.
Dat is weer een heel andere discussie. Ik heb je alleen even geholpen met het model-verhaal ;)
Een route koppel je aan een action (actie). Uit de route moet je afleiden om welke actie het gaat. Dus /nieuws koppel je bijvoorbeeld aan een showNewsAction() en /nieuws/item/1/mijn-eerste-nieuws-item koppel je aan showItemAction waarbij in dit geval 1 het ID van het item in de database is.
Toevoeging op 24/11/2014 13:38:24:
@Ward:
>> Er is geen laatste nieuwsitem binnen één nieuwsitem.
Ik snap wat je bedoelt. Wellicht is het dan handiger om de controller niet NewsItemController te noemen, maar simpelweg NewsController, met als actions bijvoorbeeld show($amount), showItem($id) en showRecent($amount).
Valt me nog even op nu dat Roy dit doet:
$newsitems = $controller->getLatest();
Eigenlijk is een MVC patroon bedoeld om direct dingen te tonen (de V staat voor View). In dat geval zou het dus logischer zijn om te kiezen voor:
$controller->showRecent();
De controller zorgt dan ook dat de recente items daadwerkelijk worden getoond in de browser.
'http://mydomain.com/news/' // alle nieuwsitems moeten getoond worden (in een lijst met titels)
'http://mydomain.com/news/latest' // de laatste 20 nieuwsitems moeten getoond worden (in een lijst met titels)
'http://mydomain.com/news/show/12' // laat één nieuwsbericht zien met id=12
en je hebt een NewsController:
<?php
class NewsController
{
public function indexAction() {}
public function latestAction() {}
public function showAction($id) {}
}
?>
Dan moet de Dispatcher (Of hoe je dat geval ook wilt noemen) er voor zorgen dat bij de eerste route in mijn lijstje de indexAction methode wordt aangeroepen en dat bij de tweede route in mijn lijstje de latestAction methode wordt aangeroepen. Bij de derde wordt het extra interessant want daar zit een variabele waarde in.
Die 12 kan immers net zo goed een ander getal zijn. Leuke uitdaging :p
Je zult dus ergens een lijst, array, xml of whatever moeten opslaan waarin aangegeven staat welke controller aangeroepen moet worden bij welke route er opgevraagd wordt.
Als je het slim wilt doen dan zorg je ook dat je heel makkelijk linkjes (denk aan <a href="..." >blabla</a> kunt maken in je view.
DUS:
<?php
$routes = array(
'latest_news' => new $route('news/latest'),
// en nog véél meer routes ...
);
?>
en in de view:
Dat moet je dus gaan inbouwen. Vanuit de betreffende action ga je dan een view genereren. In je showNewsItemAction() komt dus aan het eind iets te staan als $this->render('newsitem.phtml').
Dat moet je dus gaan inbouwen. Vanuit de betreffende action ga je dan een view genereren. In je showNewsItemAction() komt dus aan het eind iets te staan als $this->render('newsitem.phtml').
Dan krijg ik dus zoiets?
En wat gebeurt er dan in render()?
<?php
class Controller
{
public function render($file)
{
}
}
class NewsitemController extends Controller
{
private _model;
public function __construct()
{
$this->_model = new NewsitemModel();
}
public function getLatest()
{
$newsitems = $this->_model->getLatest();
$this->render("nieuws.html");
}
}
// models/newsitem.php
class NewsitemModel extends Model
{
public function getLatest()
{
$select = "SELECT * FROM newsitems ORDER BY id DESC";
$query = $this->_database->query($select);
if($query->rowCount() > 0)
{
return $query->fetchAll();
}
}
}
$controller = new NewsitemController();
$controller->getLatest();
?>