Ik ben bezig met een website waarbij ik aardig gebruik maak van OOP. Daarbij heb ik nu het probleem dat ik een bepaalde class in een andere class moet gebruiken. Ik wil niet opnieuw een object aanmaken omdat ik dan weer een 'leeg' object heb. Ik wil namelijk een bestaand object (die aangemaakt is buiten de class) gebruiken in een class.
Voorbeeldje om het wat te verduidelijken
class class1 {
private $data;
function functie1($data) {
$this->date = $data;
}
}
$class1 = new class1;
class class2 {
function functie2($data) {
return $class1->functie1($data);
}
}
Ik weet nu al bijna zeker dat het op bovenstaande manier niet zal werken. Weet er toevallig iemand hoe je dit kan oplossen?
Bedankt alvast!
[size=xsmall]Toevoeging op 23/12/2012 22:33:36:[/size]
Ik heb net iets gevonden waarmee ik het zou kunnen proberen. Met de singleton patern. Iemand die weet of dat goed en veilig is?
Ik heb dus een database class aangemaakt. Dan maak ik bovenaan in mijn index file het database-object aan door volgende code uit te voeren:
$db = new mysql($host, $user, $pass, $database);
Hier begin je dus al verkeerd. In een echte OOP omgeving is er maar 1 object dat je in de global space (je index file) aanmaakt en dat is de controller of het application object (afhankelijk van welk pattern je gebruikt). De hele afhandeling van het request wordt vervolgens in dat object afgewerkt. Alle andere objecten die worden aangemaakt worden danook vanuit dat ene object geinitieerd.
Ja, zo heb ik het toch ook. Of begrijp ik je hier verkeert? Dit hele topic gaat er net over dat ik maar één object wil aanmaken voor bijvoorbeeld de database. Daarom stuur ik het $db object door naar bijvoorbeeld de user class zodat ik die kan hergebruiken i.p.v. een nieuwe aan te maken.
Ik denk dat je mijn opmerking niet begrijpt. He gaat er niet om hoeveel database objecten je aanmaakt, maar om waar je die aanmaakt. Zoals gezegd, in een echte OOP omgeving zal je dat niet in je index file doen. Daar maak je namelijk alleen het applicatie object aan, verder niets. Een db object maak je normaal gesproken binnen een factory of een service container aan.
Oke, bedankt! Ik begrijp het nu. Dus ik mag eigenlijk geen database object aanmaken zolang ik deze niet nodig heb. Dus dan moet ik telkens als ik de database nodig heb het volgende doen: $db = new mysql($host,$password..); Als ik dan klaar ben doe ik $db->closeConnection of zoiets? Bedankt alvast!
Ruben, nee dat zegt hij niet. Wat je nu hebt is ongetwijfeld iets als dit:
<?php
// index.php
$db = new Database(...);
// ... een hele boel lappen code
?>
Wat de juiste OO methode is:"
<?php
// kernel.php
/**
* De kern van je applicatie
*/
class Kernel
{
private $database;
/**
* Deze functie wordt aangeroepen en handelt een pagina request af.
*/
public function handle(...)
{
$db = $this->getDatabase();
// ... andere code die alles gaat afhandelen
}
protected function getDatabase()
{
if (null === $this->database) {
$this->setDatabase();
}
return $this->database;
}
protected function setDatabase()
{
$this->database = new Database(...);
}
}
?>
<?php
// bootstrap.php
require_once 'kernel.php';
?>
<?php
// index.php
require_once 'bootstrap.php';
$kernel = new Kernel();
$kernel->handle();
//! niet meer
?>
Ik denk dat ik het nu helemaal begrijp! Dus ik moet per class een nieuwe database connectie aanmaken? En hoort deze code niet omgedraaid: "$db = $this->getDatabase(); --> $this->getDatabase() = $db;"?
Ik snap het nog niet helemaal. Dus ik mag geen global $db aanmaken? Dus ik moet pas een object aanmaken in de classes zelf? Maar dan zit ik met het probleem dat ik na een tijdje meer dan 10 verschillende database objecten (database connecties) heb en dat bevorderd de performance van de website zeker niet.
Nee, nergens staat dat je elke keer een nieuw database object moet aanmaken. Waar het om gaat is dat je (1) niet buiten je classes om al objecten aanmaakt in je index file en (2) dat je het aanmaken van objecten gestructureerd doet. Als je bijvoorbeeld via een factory of service container werkt, kan je bij elke nieuwe aanvraag voor een database object een referentie geven naar een eerder aangemaakt object. De service container bijvoorbeeld houdt bij welke objecten hij heeft aangemaakt en als er een vraag komt naar een al aangemaakt object, dan maakt hij niet een nieuwe aan, maar geeft de eerder aangemaakte terug.
Dat is wat Wouter hier doet:
<?php
protected function getDatabase()
{
if (null === $this->database) {
$this->setDatabase();
}
return $this->database;
}
?>
Als $this->database null is (ergo, er bestaat nog geen database object) dan maakt hij er 1 aan en geeft die terug. Bestaat er wel al 1 dan geeft hij die direct terug.
Wat je nu in de rest van je classes moet doen, is altijd deze functie aanroepen in dit object en dus niet elke class zijn eigen database object laten aanmaken.
Heel erg bedankt iedereen! Ik moet dus een soort van configuration-class aanmaken waarmee ik andere classes aanmaak, heb ik het goed? Dus dan doe ik bijvoorbeeld:
Dit komt bovenin de index file:
<?php
$classes = new classes();
?>
Dit komt dan in een class:
<?php
class user() {
private $db;
function __contructor() {
$this->db = $classes->database($host, $user, $pass, $connection);
}
?>
Maar dan zit ik weer met de vraag, hoe kom ik in die user class aan de $classes class?
EDIT: Na het even beter bekeken te hebben is bovenstaande niet echt een antwoord op mijn vraag. Volgens mij moet ik dus gewoon alle regels waar ik een nieuw object aanmaak uit mijn index halen en dat in een class regelen. Dat is inderdaad iets waarvoor OO bekend staat. Maar dat is niet echt een antwoord op mijn vraag. Want dan moet de kernel class alsnog de $this->database meegeven aan de user class. Dus dat was niet echt mijn vraag
Ik wil weten of het mogelijk is om de user class aan de database class te laten komen zonder dat ik deze hoef mee te sturen en zonder een nieuw object hiervoor aan te maken indien deze al bestaat (buiten de user class aangemaakt).
Ik wil weten of het mogelijk is om de user class aan de database class te laten komen zonder dat ik deze hoef mee te sturen en zonder een nieuw object hiervoor aan te maken indien deze al bestaat (buiten de user class aangemaakt).
Nee, ze komen niet uit de lucht vallen. Je zal altijd op de een of andere manier een object (referentie) moeten doorgeven van het ene object naar het andere.
Wat mij betreft zijn er drie mogelijkheden:
- meegeven in de constructor als het een absolute noodzakelijkheid is (denk aan een database configuratie in een database object)
- meegeven via een setter
- opvragen via een getter
De enige ander manier is dat je met globals gaat werken, maar dat is natuurlijk vloeken in de kerk als je in een OOP omgeving bezig bent.
[quote="Ruben Portier op 26/12/2012 14:06:05"]
Ik wil weten of het mogelijk is om de user class aan de database class te laten komen zonder dat ik deze hoef mee te sturen en zonder een nieuw object hiervoor aan te maken indien deze al bestaat (buiten de user class aangemaakt).
Nee, ze komen niet uit de lucht vallen. Je zal altijd op de een of andere manier een object (referentie) moeten doorgeven van het ene object naar het andere.
Wat mij betreft zijn er drie mogelijkheden:
- meegeven in de constructor als het een absolute noodzakelijkheid is (denk aan een database configuratie in een database object)
- meegeven via een setter
- opvragen via een getter
De enige ander manier is dat je met globals gaat werken, maar dat is natuurlijk vloeken in de kerk als je in een OOP omgeving bezig bent.
[/quote]
Bedankt, maar zoals ik het hier nu ook even lees is het niet verstandig om via de contructor van een class alles in te stellen? Dus mijn databaseconfiguratie mag ik ook niet doorsturen aan de new mysql class? Dus ik moet eerst doen $db = new mysql(); en dan $db->set($host, $user...)?