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?
Gewoon zoals je altijd een parameter van buiten een functie in een functie brengt:
<?php
$class1 = new Class1();
$class2 = new Class2();
$class2->functie2($class1);
?>
Bedankt voor je reactie! Dependency injection is zoals ik het nu heb. Maar ik vond het nogal een 'vreemde' manier van werken. Ik moet dan telkens bij alle classes die b.v. de database class moeten kunnen bereiken een $db var toevoegen een de __constructor van die class.
Is dit dan echt de enige goede manier? En waarom is singleton slecht?
De 'enige goede' durf ik niet te zeggen, het is een van de meest recentste patternen in PHP wereld en wordt langzamerhand door alle grote libraries gebruikt.
Met een Service Container voorkom je problemen met het telkens moeten toevoegen van de $db parameter. Kijkt bijv. maar eens naar dit simpele voorbeeld:
<?php
$container = new Pimple();
Raoul, setters is ook een vorm van Injection. Je hebt 3 vormen: Constructor injection, Property injection en setter injection. Property injection wordt zelden gebruikt en als een klasse iets per se nodig heeft gebruik je constructor en anders setter.
Bedankt allemaal! Ik snap de code van Wouter J niet zo goed. Het lijkt me nogal veel code. Bij singleton kan ik dan misschien maar 1 instance per request doen. Dat is ook net wat ik wil. Stel ik heb een database class. Dan wil ik toch ook maar 1 instance van die database aanmaken en niet met 5 verschillende database connecties gaan rondlopen?
Wouter gaf puur een voorbeeld. Wat wil je nu precies doen eigenlijk?
Ik denk wel dat DI voor een simpele applicatie en een beginner als jouw een beetje uitgebreid is... dus daarom toon ik even mijn getter en setter voorbeeldje:
<?php
class EersteClass
{
}
class TweedeClass
{
private $_eersteClass;
public function setEersteClass(EersteClass $eerst)
{
$this->_eersteClass = $eerst;
}
public function getEersteClass()
{
return $this->_eersteClass;
}
public function voorbeeldje()
{
$class = $this->getEersteClass();
// doe iets met $class
}
}
$eersteClass = new EersteClass();
$tweedeClass = new TweedeClass();
$tweedeClass->setEersteClass($eersteClass);
?>
Als je van plan bent om meerdere classen te hebben die ook EersteClass gebruiken kan je misschien ook werken met Aware classen?
<?php
abstract class EersteClassAware
{
private $_eersteClass;
public function setEersteClass(EersteClass $eerst)
{
$this->_eersteClass = $eerst;
}
public function getEersteClass()
{
return $this->_eersteClass;
}
}
class EersteClass {}
class TweedeClass extends EersteClassAware {}
class DerdeClass extends EersteClassAware {}
$eersteClass = new EersteClass();
$tweede = new TweedeClass();
$derde = new DerdeClass();
$tweede->setEersteClass($eersteClass);
$derde->setEersteClass($eersteClass);
?>
Bedankt Raoul! Maar ik snap niet waarom je in bovenstaande code dan ook een class EersteClass aanmaakt. En dan moet ik dus telkens (zoals ik het nu al heb) de al reeds aangemaakte object meegeven.
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);
Het probleem is nu dat ik het $db object ook in een andere class (user) wil gebruiken.
class user {
__constructor() {
$this->db = $db; // Hoe verkrijg ik hier de reeds aangemaakte $db object?
}
}
Wat ik nu heb is als volgt:
class user {
__constructor($db) {
$this->db = $db; // Hoe verkrijg ik hier de reeds aangemaakte $db object?
}
}
$db = new mysql($host, $user, $pass, $database);
$user = new user($db);
Ik wil nu juist net niet die $db meesturen naar de constructor van de user class. Dit lijkt mij nogal vreemd om te doen. Net omdat ik dan bij iedere class waar ik die database nodig heb dat moet bijvoegen.
Wat je hierboven doet is gewoon normale OO en is gewoon correct, hoe vreemd je dat ook vind.
Je code is wel niet echt net...
Hieronder verbeterd:
<?php
class User
{
public $db = null;
public $id = null;
public function __construct($db, $id)
{
$this->db = $db;
$this->id = $id;
}
public function getUsername()
{
$user = $this->db->query('...');
return $user->fetch()['username'];
}
}
$db = new Db(...);
$user = new User(1, $db);
echo $user->getUsername();
?>
[size=xsmall]Toevoeging op 24/12/2012 15:05:21:[/size]