Gisteren kreeg ik een vraag op IRC hoe je de naam van een categorie kan selecteren van een nieuwsbericht. Het probleem is dus, hoe leg ik een relatie tussen verschillende models en hoe vraag ik de gegevens ervan op? Laten we veronderstellen dat we een tabel news hebben en een tabel categories. De structuur ziet er als volgende uit.
CREATE TABLE `categories` (
`id` int(11) NOT NULL auto_increment,
`naam` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `news` (
`id` tinyint(4) NOT NULL auto_increment,
`titel` varchar(255) NOT NULL,
`categorie` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `categorie` (`categorie`)
);
ALTER TABLE `news` ADD CONSTRAINT `nieuws_ibfk_1` FOREIGN KEY (`categories`) REFERENCES `categories` (`id`);
Dit is de structuur van je tabel. In PHP ziet ons model er als volgt uit.
class News extends Zend_Db_Table {
protected $_name = ‘news’;
}
class Categories extends Zend_Db_Table {
protected $_name = ‘categories’;
}
Dit ziet er in orde uit maar wat als ik nu een artikel wil weergeven en daaronder de naam van zijn categorie wil plaatsen. Je kan natuurlijk de twee modellen oproepen en dan twee fetch instructies doen, zoals hieronder staat.
public function indexAction()
{
$nieuws = new News();
$categorie = new Categories();
$artikel = $nieuws->fetchRow(“id=1”);
$categorie = $artikel->fetchRow(“id=” . $artikel->categorie);
}
Je hebt nu wel de correcte informatie maar je relatie tussen je models zit niet goed. Als ik nu alle nieuwsberichten wil van één categorie, kan me dit behoorlijk wat werk geven. Ook zijn er verschillende soorten relaties. Daarom leg een relatie tussen je models. Hoe beginnen we eraan? In het ene model moet de relatie komen en de andere model moet weten welk model er van hem afhangt. De model News heeft een kolom catgorie die wijst naar Categorie en kolom id. Dus de waarde van News.categorie is een referentie/verwijst naar Categorie.id, dus we defineren de relatie in onze model News. Dit betekent ook dat onze model News afhankelijk is van de model Categories. Onze models code ziet er als volgt uit (mijn excuses voor het gebrek aan tabs, quotes verwijdert die).
class News extends Zend_Db_Table {
protected $_name = ‘news’;
protected $_referenceMap = array(
‘Categorie’ => array(
‘columns’ => ‘categorie’,
‘refTableClass’ => ‘Categories’,
‘refTableColumn’ => ‘id’
)
);
}
class Categories extends Zend_Db_Table {
protected $_name = ‘categories’;
protected $_dependentTables = array(‘News’);
}
In de referenceMap komt een relatie identifier en die wijst naar de relatie tussen de kolommen. De relatie spreekt voor zich. In de dependentTables zet je een array met de model(s) die afhankelijk zijn.
Je kan nu je indexAction je code als volgt schrijven.
public function indexAction()
{
$nieuws = new News();
$artikel = $nieuws->fetchRow(“id=1”);
$categorie = $artikel->findParentRow(‘Categorie’);
}
Niet moeilijk te implementeren en vooral handig als je Zend Framework gebruikt! Meer informatie over relations.