ik heb hier even een klein begin gemaakt voor een blog systeem maar nu loop ik telkens tegen hezelfde probleem. Hoe kan ik mijn database hieraan toevoegen? Ik zou het graag met pdo doen omdat je daar het meeste met kan maar dan moet ik eerst de pdo class ergens vandaan halen. Ik heb al gekeken op php.net maar de start lukt me niet echt goed..
<?php
class Blog
{
# Lees één specifiek blogbericht adhv een id
leesBlog($id)
{
}
# Geef een lijst van blog berichten
lijstBlog()
{
}
}
class Reactie
{
# Voeg een reactie toe
maakReactie($auteur, $datum, $email, $ip, $bericht)
{
}
# Lees reacties voor een speciefiek blog bericht
leesReactie($id)
{
Die geef je mee aan een constructor en die sla je op in een propertie:
<?php
class Blog
{
protected $_db; // Ik gebruik alitjd _ voor de var als het niet een eigenschap van het object is
protected $id;
protected $title;
protected $content;
protected $reaction_ids;
// Met PDO voor $db zorgen we dat $db een instance moet zijn van PDO
public function __construct( PDO $db )
{
$this->_db = $db;
}
public function setID( $id )
{
$this->id = (int) $id;
$sQuery = "SELECT title, content, author_id FROM posts WHERE id = ".$this->id;
$stmt = $this->_db->prepare($sQuery);
$stmt->execute();
$result = current($stmt->fetchAll());
$this->title = $result['title'];
$this->content = $result['content'];
$this->author = new Author($result['author_id']); // Author is een eigen classe die user extends
}
public function getTitle()
{
return $this->title;
}
public function getContent()
{
return $this->content;
}
public function getAuthor()
{
return $this->author;
}
public function getReactionIDs()
{
if( empty($this->reaction_ids) )
{
$sQuery = "SELECT id FROM reactions WHERE post_id = ".$this->id;
$stmt = $this->_db->prepare($sQuery);
$stmt->execute;
$this->reaction_ids = Array();
while( $row = $stmt->fetch(PDO::FETCH_ASSOC) )
{
$this->reaction_ids[] = $row['id'];
}
}
return $this->reaction_ids;
}
}
?>
Zoiets denk ik, er kunnen fouten in zitten en ik ben nog niet heel lang bezig met OO dus er zitten misschien wat kromme denkwijzes in.
Sta stil bij het feit of je uberhaupt wel een database object wilt hebben in een bepaalde class.
De genoemde classes zouden - in mijn ogen - alleen methods moeten hebben welke:
1. records kan registreren
2. contoles / validaties kan uitvoeren
3. eventuele output kan verifieren / beveiligen
4. eventuele specifieke berekeningen
2 en 3 zijn dan vaak instances van andere classes, anders heb je x keer de zelfde method functionaliteit in verschillende classes en dat is uiteraard niet de bedoeling
In dit soort gevallen, wanneer je je db connectie via pdo doet, kan je ook eventueel een $db object als global zetten.
Objecten worden toch "by reference" doorgegeven; er is niet echt nood om dat object (of dus de handle, of de pointer (hoe heet zoiets in php?)) overal als property te kopiëren.
In dit soort gevallen, wanneer je je db connectie via pdo doet, kan je ook eventueel een $db object als global zetten.
Objecten worden toch "by reference" doorgegeven; er is niet echt nood om dat object (of dus de handle, of de pointer (hoe heet zoiets in php?)) overal als property te kopiëren.
Dit zou ik niet doen. Ik zou er een singleton class omheen bouwen. Of misschien zelfs een registry om globale objecten te beheren.
Als we Blog even BlogPost noemen:
<?php
class BlogPostMapper
{
protected $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function getById($id)
{
$sql = 'SELECT * FROM X WHERE id = ?';
$stmt = $this->db->prepare($sql);
$data = $stmt->execute(array($id))->fetch();
return $this->populate($data);
}
protected function populate(array $data)
{
$blogPost = new BlogPost();
$blogPost->setId($data['id']);
$blogPost->setContent($data['content']);
return $blogPost;
}
public function save(BlogPost $post)
{
$sql = 'UPDATE X SET content = :content WHERE id = :id';
$stmt = $db->prepare($sql);
return $post;
}
}
?>
Iets als dit stelt je in staat mooi je opslag van je daadwerkelijke object te scheiden. Enkele delen van de mapper kan je hergebruiken voor andere modellen.
Niet is global, niet static.
Mooi toch? ;)
De mapper sla je dan op in een registry of service container.
Ook kan je het op aanvraag aanmaken met een opgeslagen PDO instance.
[size=xsmall]Toevoeging op 03/01/2012 18:25:06:[/size]
Gebruik:
<?php
$pdo = new PDO();
$mapper = new BlogPostMapper();
$blog = new Blog();
$blog->setContent('test');
$mapper->insert($blog);
$id = $blog->getId();
@pim, mooi systeempje. :) Telkens denk ik dat ik de object geörienteerde gedachtegang onder de knie heb maar nee.. toch niet dus. Ik zal me er nog eens verder in verdiepen.
Ah daar komt dan weer het verlossende antwoord van Pim!
Moet er op regel 34, 35 en 45 niet : voor de key?
En is die populate method niet een beetje zinloos? Gebruik je zoiets nou in het echt of is het alleen om even de mooiheid van een datamapper te laten zien?
[Offtopicmode]
Kun je misschien eens al dit soort begrippen (zoals datamapper en factory) eens opschrijven. Want ik kom er heel veel tegen in jou berichten, maar telkens vergeet ik ze weer. En wil ze toch gaan leren.
Die populatie method is best handig, omdat je zo korte get*() methodes kan maken.
Bijv:
<?php
public function getByAuthor($author)
{
$sql = 'SELECT * FROM X WHERE author= ?';
$stmt = $this->db->prepare($sql);
$data = $stmt->execute(array($author))->fetch();
return $this->populate($data);
}
?>
Als ik dezelfde code twee keer gebruik, probeer ik een manier te verzinnen om de code te hergebruiken. Zo is het maken van aanpassingen veel makkelijker.
Ik het misschien wel zo doen:
<?php
public function getById($id)
{
$sql = 'SELECT * FROM X WHERE id = ?';
$data = $this->fetchBySql($sql, $id);
return $this->populate($data);
}
protected function fetchBySql($sql, $identifier)
{
$stmt = $this->db->prepare($sql);
$data = $stmt->execute(array($identifier))->fetch();
if($data === false)
throw new LogicException();
return $data;
}
?>
Zo kan je in drie eenvoudige regels een selector maken.
Ja misschien is het leuk als tutorial zo'n begrippenlijst te maken, maar ik heb er net al eentje gepost en heb er nu even niet veel zin in.