Beste

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);
?>

Tevens raad ik je aan eens te kijken naar Dependency Injection: http://www.phphulp.nl/php/tutorial/classes/dependency-injection/760/
[hr]
PS: Ik ben totaal geen voorstander van het Singleton pattern en dat is hier zeker niet voor nodig.
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?
Is dit dan echt de enige goede manier?

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();

$container['database.class'] = 'Wj\Storage\MySQLiDatabaseStorage';
$container['database.settings'] = array(
'user' => 'root',
'pass' => 'foobar',
'host' => 'localhost',
...
);
$container['database'] = function ($c) {
$settings = $c['database.settings'];

return new $c['database.class']($settings['host'], $settings['user'], ...);
};

$container['user.mapper.class'] = 'Wj\User\UserMapper';
$container['user.mapper'] = $container->share(function ($c) {
return $c['user.mapper.class']($c['database']);
});

// in gebruik
$user = $container['user.mapper']->findById(2);
$user1 = $container['user.mapper']->findByName('Henk');
?>

En waarom is singleton slecht?

Doordat je maar 1 instance per request kan hebben. Dat houdt elke vorm van Test Driven Development en elke vorm van uitbreiding tegen.
Je kunt natuurlijk ook met getters and setters werken.

->setClass1($class)
->getClass1()

Maar zoals Wouter zegt is DI een betere methode.
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.
Ah zo, weer iets bijgeleerd :))
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?

Is singleton daarvoor toch geen goed idee?
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]

Lees anders even deze OOP tutorial: http://phptuts.nl/view/45/ ?

Reageren