Goede avond allen,

Ik ben om te leren OOP te programmeren met php een forum aan het maken.

Wat is nu de beste methode om je objecten te vullen met de data uit de database? Moet je een constructor (of aparte functie) maken met daarin de SQL om je hele object te van zijn data te voorzien door bijvoorbeeld een id mee te geven? Of is het de bedoeling dat je buiten het object een query uitvoert en d.m.v. je setters de data in je object pompt?

Na lang denken en wikken en wegen ben ik hier nog steeds uit.

Groeten,
Jens V
indien je sql in een class opneemt dan ben je dus afhankelijk van .... en dat is nu net niet de bedoeling.
Voorbeeldje van hoe het wel moet?

Ik ben gewend programma's te schrijven in C++ en Java, en dat allemaal OOP. Het voordeel daar is dat je objecten over het hele programma blijven bestaan, tenzij je de destruct. Hoe moet je dat oplossen in php?

Jens
De mooiste manier is een ORM. Dat kan op twee manieren (voor zover ik weet)
- Active record. Je Domain Object (User) extend een bepaalde klasse. Je vindt dit oa in Doctrine 1.
<?php
$user = User::find($id);
$user->setEmail('bla');

$group = Group::find($id);
$user->setGroup($group);

$user->save();
?>
Dit heeft het nadeel dat je Domain Objects afhankelijk worden van je Active Record mechanisme. Mooier is methode twee:
- Data mapper. Een andere klasse regelt de 'persistence' (opslag) van je objecten. Je vindt oa in Doctrine 2. De andere klasse heet daar de Entity Manager.
<?
$user = $em->find('User', $id);
$user->setEmail('bla');

$group = $em->find('Group', $id);
$user->setGroup($group);

$em->persist($user); // Stel het object in als 'persistent'
$em->flush(); // Doe alle wijzigingen in 1x
?>

Handmatig kan natuurlijk ook:
<?php
class ActiveRecord
{
protected static $db; // Kan ook als array

public static function setDb(PDO $db, $identifier = 'default');
public static function getDb($identifier = 'default');
}

class User extends ActiveRecord
{
public static find($id);

public function save();
}
?>
Maar dit kost veel werk en associaties zijn lastig beheersbaar.
@Pim, hier ben ik precies toch nog niet echt mee weg. Zo een Entity Manager, wat doet dat precies? Kan je eens een voorbeeldje geven?

Wat me ook nog steeds niet duidelijk is, is de algemene structuur van een opgeroepen pagina. Stel, ik roep de pagina op die gewoon het overzicht van forums ('categorien') laat zien. Hoe ziet dat er dan uit?

Ik heb als 'model' gewoon een paar klassen die Forum, Topic en Post voorstellen. Maar deze klassen hebben tot nu toe nog geen enkele functionaliteit. Ik neem aan dat iets zoals het volgende niet de bedoeling is?

<?php
$sql = "SELECT * FROM forums ORDER BY title ASC";
// uitvoeren
$forums = array();
foreach($result as $forum)
{
    $forums[] = new Forum(/* data in $forum hierin stoppen */);
}
// html bla bla bla
for($i = 0; $i < count($forums); $i++)
{
    $f = $forums[$i];
    // uitschrijven dmv $f->getTitle(); etc
}
?>


Dat lijkt mij eigenlijk gewoon dubbel werk...

Hoe dus wel? :)
Elders op dit forum heb ik al kenbaar gemaakt dat ik op zijn zachtst gezegd geen fan ben van Active Record. Zelf gebruik ik vaak het Data Mapper pattern. En ja, die schrijf ik allemaal handmatig.

De beste manier om objecten te vullen vanuit een query vindt ik dan ook:

<?php
PDOStatement::fetchAll(PDO::FETCH_CLASS, 'MyClass', array('argv'));
?>

Met __set() kan je dan nog eventueel gedrag beïnvloeden.
Wat ik, over het algemeen, vind wanneer men vraagt naar de zinnigheid van OOP en hoe men het moet aanpassen...

Bekijk het eens van de andere kant.
Vergeet even de class op zich en denk aan het gebruik er van, buiten de class.

Schrijf je logica en doe alsof de methodes van je class al precies doen wat je wil.
Als je dat hebt, vul dan je class in en zorg dat het doet wat je vraagt.

Een voorbeeld: een gastenboek:
Wat is dat? Een formulier, een lijst berichten en de mogelijkheid om een nieuw bericht te posten.
Voor mij zijn dat dus drie publieke methodes (+ een constructor uiteraard).
Je zou er zo-iets van kunnen maken:
<?php
require_once('guestbook.php');
$m_guestbook = new guestbook();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$m_guestbook->postMessage($_POST);
header('location ...');
}
else {
$guestbook = $m_guestbook->form() . $m_guestbook->messages();
echo '<html>...<body>... '. $guestbook .'</body></html>';
}
?>

Als je dit hebt, dan kan je beginnen nadenken over hoe je guestbook.php precies aanpakt.
@Kris,

In je voorbeeldje van je guestbook, waar haal je nu je gegevens uit je db? In je guestbook-klasse neem ik aan? En waar dan?
Ik vind dat het zinnig is om twee variabelen globaal te zetten:
Een $db object en een $user object.

$db is bv. een pdo object. Eventueel gewrapped in een eigen geschreven class.

Overal waar je een query moet uitvoeren, doe je bv. dit:

<?php
class guestbook {
...
public function messages() {
global $db;
...
$res = $db->query($sql);
}
}
?>

Zo'n $user object kan dan dingen bijhouden als ingelogd / ip / e-mail ... van de huidige client.

Mijn punt is vooral: je moet je algemene logica van je class niet omgooien omdat "men" zegt dat je beter geen query's laat uitvoeren binnen classes.
Oké, bedankt. Het een en ander is nu wel duidelijk, denk ik. Ik kan wel eens aan de slag.

Nog iets, jij hebt functies om een heel form of de rest uit te printen? Is dat wel zo goed?

En als ik dit nu met Smarty ofzo wil doen? Kan ik dan via een assign een heel object meegeven en dat object 'ondervragen' (data uithalen) in de tpl-files?

edit:
Dat van Smarty heb ik gevonden, assign_by_ref() :)
Sorry, ik weet veel te weinig van Smarty om hier verder iets zinnigs te zeggen.

Reageren