Scroll
1.5. Klassen verbinden voor werken met database en templates
We hebben de structuur van ons framework gemaakt, nu is het tijd om na te denken over gegevensopslag: nieuws, producten, enz.
Het object dat met de database werkt, moet in staat zijn om:
- Databaseverbindingen te beheren
- Een lichte abstractie van de database te bieden
- Query’s te cachen
- Algemene databasebewerkingen te vereenvoudigen
Registry/objects/db.class.php
aan:
<?php /** * Databasebeheer * Biedt een lichte abstractie van de database */ class database { /** * Meerdere verbindingen met de database toestaan * Wordt zelden gebruikt, maar kan nuttig zijn */ private $connections = array(); /** * Geeft de actieve verbinding aan * setActiveConnection($id) wijzigt de actieve verbinding */ private $activeConnection = 0; /** * Query’s die al zijn uitgevoerd en gecachet */ private $queryCache = array(); /** * Gegevens die zijn opgehaald en gecachet */ private $dataCache = array(); /** * Laatste uitgevoerde query */ private $last; /** * Constructor */ public function __construct() { } /** * Nieuwe databaseverbinding maken * @param String hostnaam van de database * @param String gebruikersnaam * @param String wachtwoord * @param String databasenaam * @return int ID van de nieuwe verbinding */ public function newConnection( $host, $user, $password, $database ) { $this->connections[] = new mysqli( $host, $user, $password, $database ); $connection_id = count( $this->connections )-1; if( mysqli_connect_errno() ) { trigger_error('Fout bij verbinden met host. '.$this->connections[$connection_id]->error, E_USER_ERROR); } return $connection_id; } /** * Actieve verbinding sluiten */ public function closeConnection() { $this->connections[$this->activeConnection]->close(); } /** * Actieve verbinding wijzigen */ public function setActiveConnection( int $new ) { $this->activeConnection = $new; } /** * Query in cache opslaan */ public function cacheQuery( $queryStr ) { if( !$result = $this->connections[$this->activeConnection]->query( $queryStr ) ) { trigger_error('Fout bij uitvoeren en cachen van query: '.$this->connections[$this->activeConnection]->error, E_USER_ERROR); return -1; } else { $this->queryCache[] = $result; return count($this->queryCache)-1; } } /** * Aantal rijen in cache ophalen */ public function numRowsFromCache( $cache_id ) { return $this->queryCache[$cache_id]->num_rows; } /** * Rijen ophalen uit cache */ public function resultsFromCache( $cache_id ) { return $this->queryCache[$cache_id]->fetch_array(MYSQLI_ASSOC); } /** * Gegevens opslaan in cache */ public function cacheData( $data ) { $this->dataCache[] = $data; return count( $this->dataCache )-1; } /** * Gegevens uit cache ophalen */ public function dataFromCache( $cache_id ) { return $this->dataCache[$cache_id]; } /** * Records verwijderen uit tabel */ public function deleteRecords( $table, $condition, $limit ) { $limit = ( $limit == '' ) ? '' : ' LIMIT ' . $limit; $delete = "DELETE FROM {$table} WHERE {$condition} {$limit}"; $this->executeQuery( $delete ); } /** * Records bijwerken */ public function updateRecords( $table, $changes, $condition ) { $update = "UPDATE " . $table . " SET "; foreach( $changes as $field => $value ) { $update .= "`" . $field . "`='{$value}',"; } $update = substr($update, 0, -1); if( $condition != '' ) { $update .= "WHERE " . $condition; } $this->executeQuery( $update ); return true; } /** * Record invoegen */ public function insertRecords( $table, $data ) { $fields = ""; $values = ""; foreach ($data as $f => $v) { $fields .= "`$f`,"; $values .= ( is_numeric( $v ) && ( intval( $v ) == $v ) ) ? $v."," : "'$v',"; } $fields = substr($fields, 0, -1); $values = substr($values, 0, -1); $insert = "INSERT INTO $table ({$fields}) VALUES({$values})"; $this->executeQuery( $insert ); return true; } /** * Query uitvoeren */ public function executeQuery( $queryStr ) { if( !$result = $this->connections[$this->activeConnection]->query( $queryStr ) ) { trigger_error('Fout bij uitvoeren van query: '.$this->connections[$this->activeConnection]->error, E_USER_ERROR); } else { $this->last = $result; } } /** * Rijen ophalen van laatste query */ public function getRows() { return $this->last->fetch_array(MYSQLI_ASSOC); } /** * Aantal beïnvloede rijen */ public function affectedRows() { return $this->connections[$this->activeConnection]->affected_rows; } /** * Gegevens beveiligen */ public function sanitizeData( $data ) { return $this->connections[$this->activeConnection]->real_escape_string( $data ); } /** * Destructor, sluit alle verbindingen */ public function __deconstruct() { foreach( $this->connections as $connection ) { $connection->close(); } } } ?>Voordat we de databaseverbinding testen, bekijken we eerst wat onze klasse doet. We kunnen eenvoudige bewerkingen uitvoeren via methoden van de klasse:
// Invoegen $registry->getObject('db')->insertRecords( 'products', array('name'=>'Mok' ) ); // Bijwerken $registry->getObject('db')->updateRecords( 'products', array('name'=>'Rode mok' ), 'ID=2' ); // Verwijderen $registry->getObject('db')->deleteRecords( 'products', "name='Rode mok'", 5 );Onze klasse ondersteunt ook caching. Vervolgens voegen we een object toe voor templatebeheer:
Registry/objects/template.class.php
.
(Volledige code zoals hierboven in het origineel.)
Daarna voegen we de Page
-klasse toe in Registry/objects/page.class.php
, die de structuur en inhoud van de webpagina’s beheert.
Wanneer de klassen voor database en templates klaar zijn, verbinden we ze via de methode storeCoreObjects()
in Registry/registry.class.php
:
public function storeCoreObjects() { $this->storeObject('database', 'db' ); $this->storeObject('template', 'template' ); }Daarna vullen we de database met wat voorbeeldgegevens, maken we een tabel
users
met de velden id
, name
, email
, en maken we het sjabloon Views/Templates/main.tpl.php
aan om gebruikers weer te geven.
Vervolgens verbinden we alles in index.php
, stellen we de databaseverbinding in, laden we het sjabloon en tonen we de lijst met gebruikers vanuit de database via onze template-engine.
Als alles goed is gegaan, zal op de startpagina de lijst met gebruikers correct worden weergegeven.