Goedendag allemaal,
Ik had een vraagje met betrekking tot het inladen van data vanuit bijvoorbeeld een (my)SQL database of een xml-bestand in een object.
Stel ik heb een pagina waarin ik gegevens over een gebruiker weergeef en ik heb een obect Gebruiker (instantie van de class Gebruiker). De data die ik bijvoorbeeld uit een database zou halen zijn naam en geboortedatum. Waar laden jullie dan de gegevens? In de weergave pagina en vervolgens alles in heb object plaatsen? Of een variabele meegeven in de constructor waarmee ik de data in de database kan vinden, en in het object laden?
Ik hoop dat de vraag een beetje duidelijk is en dat jullie me hiermee kunnen helpen.
P.S. Overigens heeft dit vooral betrekking op PHP, hoewel ik er van uit ga dat het ook bij andere talen soortgelijk werkt.
- Data in een class zetten/laden
-
29-03-2010, 13:36 #1
- Berichten
- 15
- Lid sinds
- 16 Jaar
Data in een class zetten/laden
-
In de schijnwerper
Goedkope 10 Gbps Virtual Private Server (VPS) in Nederland (Met PURE NVMe opslag!)Hosting[BELANGRIJK] Festinger Vault - Download 25.000 thema's en pluginsPromotieOntvang tot 20% kickbackfee op je Google Ads klanten, waar wacht je nog op?Promotie(SEO) Tekstschrijver nodig voor winstgevende teksten?Freelance / Werk -
29-03-2010, 13:40 #2
- Berichten
- 257
- Lid sinds
- 15 Jaar
Het lijkt me dat je deze gegevens typisch vanuit de class zelf laadt. Dus bijvoorbeeld via een parameter in de constructor of een losse functie.
De class heeft als verantwoordelijkheid te zorgen voor de data, dus ophalen, aanpassen, wegschrijven etc. Dus dat wil je niet aan één of andere losse pagina overlaten.
-
29-03-2010, 17:00 #3
- Berichten
- 330
- Lid sinds
- 18 Jaar
Het lijkt mij verstandig om bewerkingen niet uit te voeren in de constructor. Een constructor kan je beter gebruiken om bijvoorbeeld bij een member class een id van een lid op te slaan, waarop alle daaropvolgende bewerkingen worden uitgevoegd (zoals updaten, selecteren, etc.).
Je kan gebruik maken van de zogenaamde setters en getters. Setters gebruik je dus om bepaalde waarde te "setten" (door te voeren (dus updaten, etc.)) en getters gebruik je om informatie op te vragen (lijkt mij logisch).
Dus bijvoorbeeld:
PHP Code:class member {
protected $lidid;
public function __construct($lidid) {
$this->lidid = $lidid;
}
public function getUserinfo() {
// Hier haal je de informatie van de gebruiker op aan de hand van $this->lidid
return $arraymetinformatie;
}
public function setUserinfo() {
// Hier voeg je bijvoorbeeld informatie toe aan de database aan de hand van $this->lidid
}
}
$memberobject = new member(5);
$memberinfo = $memberobject->getUserinfo();
print_r($memberinfo);
Laatst aangepast door Arjen Rademaker : 29-03-2010 om 17:07
-
29-03-2010, 17:30 #4
- Berichten
- 15
- Lid sinds
- 16 Jaar
Het lijkt mij verstandig om bewerkingen niet uit te voeren in de constructor. Een constructor kan je beter gebruiken om bijvoorbeeld bij een member class een id van een lid op te slaan, waarop alle daaropvolgende bewerkingen worden uitgevoegd (zoals updaten, selecteren, etc.).
-
29-03-2010, 18:42 #5
- Berichten
- 330
- Lid sinds
- 18 Jaar
Dat klinkt logisch inderdaad. Mijn twijfels ontstonden doordat ik dacht dat door het in de class te zetten, de reusability daalde doordat het specifiek op mysql/xml gericht zou zijn. Maar of ik het nu buiten of binnen de class data laadt maakt wat dat betreft niet uit.
Zoals ik heb geleerd 'maakt' de constructor de class. Ik zou juist zeggen dat data die al bekend is (in de database staat) en een eigenschap van een object is, al bij de constructor gemaakt moet worden. Bedoelde je dat getUserInfo() in de constructor moet worden aangeroepen?
Maar er zijn meer wegen die naar Rome leiden, dus het is niet per definitie de juiste methode.
-
30-03-2010, 15:02 #6
- Berichten
- 257
- Lid sinds
- 15 Jaar
Dat klinkt logisch inderdaad. Mijn twijfels ontstonden doordat ik dacht dat door het in de class te zetten, de reusability daalde doordat het specifiek op mysql/xml gericht zou zijn. Maar of ik het nu buiten of binnen de class data laadt maakt wat dat betreft niet uit.
Overigens vind ik getters en setters wel goed. Ik zou er echter persoonlijk voor kiezen de interne variabelen al te vullen met data via de constructor. Afhankelijk misschien van hoeveel queries het je kost; anders zou je inderdaad via een getter kunnen controleren of de variabele al is gezet, zo niet dan pas de query uitvoeren en de variabele vullen en teruggeven. Als je dan veel variabelen hebt en er worden veel setters aangeroepen moet je ook veel queries uitvoeren. Dat kun je natuurlijk ook weer optimaliseren, ik denk dat je dat wel begrijpt.
-
30-03-2010, 15:49 #7
- Berichten
- 82
- Lid sinds
- 18 Jaar
Zoals hierboven genoemd kun je hiervoor inderdaad een Database Abstraction Layer gebruiken. Je zou eigenlijk je datasource willen abstraheren van je applicatie. Zo maakt het niet uit wat je kiest als opslag, of het nou XML of mysql is.
-
31-03-2010, 10:21 #8
- Berichten
- 15
- Lid sinds
- 16 Jaar
Ik heb even gekeken naar AdoDB en PEAR MDB2. Momenteel wil ik mijn aandacht daar nog niet op richten maar zal het zeker in het achterhoofd houden. Uiteindelijk is het natuurlijk nog wel de beperking dat de databases wel worden meegenomen maar xml niet (ik zie het in ieder geval niet). En uiteraard krijg je dan de vraag hoe je omgaat met het feit dat je zou kunnen willen switchen van Abstraction Layer. Misschien denk ik er gewoon al te veel over na en moet ik me er niet zo druk om maken.
Hoe ik het van plan ben nu aan te pakken:
In de constructor van een class 'laadt' ik waar mogelijk de data met een functie loadData(). Daarnaast maak ik ook een functie saveData() die eventuele wijzigingen weer opslaat in de database.
De getters en setters gebruik ik om vanuit andere classes of scripts data aan te passen. En in het geval van setters roep ik wanneer er iets wijzigt saveData() aan.
Op deze manier weet ik precies waar ik de mysqli-verbindingen tot stand breng (in de classes die data uit de database gebruiken) waardoor het eventueel aanpassen makkelijker wordt.
Nu nog een praktisch vraagje. Ik was van plan om in een bestand config.inc.php de database gegevens (host, username, password en databasenaam) te zetten zodat ik het op één plek kan aanpassen.
Nu heb ik twee problemen:
1. Hoe zorg ik ervoor dat het juiste bestand ge-include wordt wanneer ik het bestand waarin ik require_once aanroep ook ge-include is. De class staat namelijk in een map "classes" terwijl ik het script waarin ik de class include in de homedirectory staat. Ook config.inc.php staat in de home directory. probleem is dus dat wanneer ik het volgende zet in de class:
PHP Code:require_once("../config.inc.php");
2.
Wanneer ik de variabelen uit config.inc.php tijdelijk in hetzelfde bestand als de class zet, worden de variabelen (wellicht logisch) niet gebruikt door de class. Ik heb geen idee hoe ik dit zou moeten oplossen behalve de strings letterlijk in de mysqli-connectie te plaatsen. Dit wil ik dus juist niet omdat ik het centraal wil kunnen aanpassen. Iemand suggesties hoe dit op te lossen?
-
31-03-2010, 10:50 #9
- Berichten
- 330
- Lid sinds
- 18 Jaar
1. Kijk hier eens: http://gathering.tweakers.net/forum/...ssages/1402157 (staat je antwoord gegarandeerd tussen als je in ieder geval beter leest dan de topicstarter van dat topic ;) ).
2. Je kan gebruik maken van een database class met static functions, waarmee je in een andere class de functies kan aanroepen aan de hand van classnaam::functienaam();. De class die je aanroept zal dus een database class kunnen zijn die buiten de andere classes is aangemaakt.
Wat ook handig is, is een autoloader die automatisch de juiste class bestanden include aan de hand van de classnaam die je aanroept in een bestand (dit scheelt je een hoop includes (require_once) en je zal nooit overbodige bestanden includen). Kijk hier maar eens: http://php.net/manual/en/language.oop5.autoload.phpLaatst aangepast door Arjen Rademaker : 31-03-2010 om 14:49
-
01-04-2010, 15:47 #10
- Berichten
- 257
- Lid sinds
- 15 Jaar
Ik heb ooit eens een tip gelezen over de includes:
Lees eens http://www.odi.ch/prog/design/php/guide.php daar staat het volgens mij uitgelegd wat ik bedoel onder 'Making your application location independent'.
Let op: dit werkt vaak niet voor cronjobs! Cronjobs vereisen vaak absolute paden vanaf de echte root directory.
-
02-04-2010, 00:37 #11
- Berichten
- 155
- Lid sinds
- 18 Jaar
je kunt natuurlijk een ontzettend moeilijk verhaal gaan maken maar handiger is om te kijken wat je daadwerkelijk nodig hebt.
mysql vs xml is een groot verschil maar laten we het 'database abstraction' gedeelte even weg dan kun je met straightforward php code en logisch nadenken een heel eind komen:
je wilt een gebruiker-object hebben zodat je logischerwijs later kunt zeggen:
PHP Code:$gebruiker = new Gebruiker();
$gebruiker->Load($id);
echo $gebruiker->naam;
in de gebruiker-class zelf kun je er voor kiezen om het opvragen van je data nog verder te abstraheren maar soms (mijn mening: meestal eigenlijk) ga je dan voorbij hetgeen je nodig hebt, simpelweg de data.
ik zou in dit geval de gebruiker dus gewoon als volgt implementeren:
PHP Code:class Gebruiker
{
private $data = null;
function __construct()
{
$this->data = array();
}
function Load($id)
{
// je kunt hier nog error handling aan toe voegen etc, jouw feestje
$sql = "SELECT * FROM gebruiker WHERE gebruiker_id = $id";
$res = mysql_query($sql);
if (mysql_num_rows($res) == 0)
return false;
$this->data = mysql_fetch_assoc($res);
return true;
}
function Save()
{
if (! isset($this->data['gebruiker_id']) )
{
$sql = "INSERT INTO gebruiker VALUES(blahblahblah)";
mysql_query($sql);
return true;
}
else
{
$sql = "UPDATE gebruiker SET blablabla WHERE gebruiker_id = " . $this->data['gebruiker_id'];
mysql_query($sql);
return true;
}
}
function __set($key,$value)
{
$this->data[$key] = $value;
}
function __get($key)
{
return (isset($this->data[$key]) ? $this->data[$key] : null;
}
}
stel dat je 100 verschillende objecten hebt, dan wil je dit natuurlijk niet alle 100x uit moeten werken:
PHP Code:class BaseObject
{
private $data = null;
private $table = null;
private $idfield = null;
function __construct()
{
$this->data = array();
}
function Load($id = null)
{
if ( empty( $id ) )
$id = ( isset($this->data[$this->idfield]) ) ? $this->data[$this->idfield] : null;
if ( empty( $id ) || $this->table === null || $this->idfield === null )
return false;
$sql = "SELECT * FROM {$this->table} WHERE {$this->idfield} = $id";
$res = mysql_query($sql);
if (mysql_num_rows($res) == 0)
return false;
$this->data = mysql_fetch_assoc($res);
return true;
}
function Save($id = null)
{
if ( $this->table === null || $this->idfield === null )
return false;
if ( empty( $id ) )
$id = ( isset($this->data[$this->idfield]) ) ? $this->data[$this->idfield] : null;
if ( empty( $id ) )
{
$fields = implode(',',array_keys($this->data));
$values = "'" . implode("','",array_values($this->data)) . "'";
$sql = "INSERT INTO {$this->table} ($fields) VALUES($values)";
mysql_query($sql);
return true;
}
else
{
$fields = array();
foreach($this->data as $key => $value)
$fields[] = "$key = '$value'";
$fields = implode(',',$fields);
$sql = "UPDATE {$this->table} SET $fields WHERE {$this->idfield} = $id";
mysql_query($sql);
return true;
}
}
function Delete($id = null)
{
if ( $this->table === null || $this->idfield === null )
return false;
if ( empty( $id ) )
$id = ( isset($this->data[$this->idfield]) ) ? $this->data[$this->idfield] : null;
if ( empty( $id ) )
return false;
$sql = "DELETE FROM {$this->table} WHERE {$this->idfield} = $id";
mysql_query($sql;
return true;
}
function __set($key,$value)
{
$this->data[$key] = $value;
}
function __get($key)
{
return (isset($this->data[$key]) ? $this->data[$key] : null;
}
}
class Gebruiker extends BaseObject
{
function __construct()
{
parent::BaseObject();
$this->table = 'gebruiker';
$this->idfield = 'gebruiker_id';
}
}
class Auto extends BaseObject
{
function __construct()
{
parent::BaseObject();
$this->table = 'auto';
$this->idfield = 'auto_id';
}
}
PHP Code:$gebruiker = new Gebruiker();
$gebruiker->load(1);
echo $gebruiker->naam;
$auto = new Auto();
$auto->load(1);
echo $auto->type;
// of
$auto = new Auto();
$auto->auto_id = 1;
$auto->delete();
// of
$auto = new Auto();
$auto->delete(1);
mocht je je data layer willen abstraheren, dan kun je dat nu centraal doen in de baseobject.
Het boven genoemde werkt in ieder geval gewoon simpel, is snel en erg makkelijk aan te passen.
reden voor mij om de data niet in de constructor te laden is simpel: een constructor moet niet bepalen wat je actie gaat zijn. (load, save, delete)
ben je ECHT extreem lui:
PHP Code:function CreateDBClass($classname,$table,$idfield)
{
eval("
class $classname extends BaseObject
{
function __construct()
{
parent::BaseObject();
$this->table = $table;
$this->idfield = $idfield;
}
}");
}
CreateDBClass('Fiets','fiets','fiets_id');
$fiets = new Fiets();
$fiets->load(1);
CreateDBClass('TafelClass','tafel','tafel_id');
$tafel = new TafelClass();
$tafel->load(3);
Nogmaals, werkt het niet, dat kan... quickreply is niet echt een volwaardige php edittor ;)
Plaats een
- + Advertentie
- + Onderwerp
Marktplaats
Webmasterforum
- Websites algemeen
- Sitechecks
- Marketing
- Domeinen algemeen
- Waardebepaling
- CMS
- Wordpress
- Joomla
- Magento
- Google algemeen
- SEO
- Analytics
- Adsense
- Adwords
- HTML / XHTML
- CSS
- Programmeren
- PHP
- Javascript
- JQuery
- MySQL
- Ondernemen algemeen
- Belastingen
- Juridisch
- Grafisch ontwerp
- Hosting Algemeen
- Hardware Info
- Offtopic