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?
Wat je hierboven doet is gewoon normale OO en is gewoon correct, hoe vreemd je dat ook vind.
Je code is wel niet helemaal net, je zet geen 'public function' voor je methods.
Hieronder verbetert:
<?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]
Bedankt! Ik zal het dan op deze manier verder doen. Ik zet wel private en public voor mijn functies. Maar het voorbeeld was even 'snel' getypt hier. Geen exacte kopie van wat ik heb in mijn bestanden.
De meeste makkelijke oplossing is volgens mij op elke class waarin je een database connectie willen gebruiken te extenden met de database class.
Je krijgt dan dit:
<?php
include('path/to/db.class.php');
class User extends Db {
public function getUsername($id) {
$result = $this->query("SELECT * FROM users WHERE id = ".$id);
return $result->fetch();
}
}
$user = new User;
print_r($user->getUsername());
?>
De grotere frameworks doen het ook op deze manier omdat het gewoon snel en overzichtelijk werkt.
Bedankt, maar wat als je dan meerdere classes wil 'includen' in een andere class. Ik heb b.v. een class database, error en user. Ik wil in user de class database en error kunnen aanroepen. Kan dit wel met extend?
Neeneeneeneeneeeeee, niet doen Rick! Met Extenden maak je een IS_EEN relatie, je mag alleen extenden als je een klasse uitbreid. Bijv. Admin extends User, want Admin IS_EEN User of Cat extends Animal, want Cat IS_EEN Animal. Maar een User is geen vorm of uitbreiding van Database, User IS_GEEN Database maar User HEEFT_EEN database. Al is dat officieel niet goed en zul je een UserMapper hebben die een database HEEFT, maar goed dat laten we buiten beschouwing. Het hoofddoel is [color=red]dat je nog mag extenden om deze rede![/color]
En je mag mij een framework laten zien die dat op deze manier doet. Tevens zijn frameworks nooit gemaakt om 'snel' te werken, maar juist om 'goed en mooi volgens de standaarden' te werken. Als laatst is dit niet overzichtelijk, aangezien je op deze manier niet meerdere 'dependencies' kan hebben.
Voorbeeldje:
<?php
class Database {
static $instance;
public static function getInstance() {
if (null === self::$instance) {
self::$instance = new PDO(...);
}
return self::$instance;
}
}
class Model {
protected $db;
public function __construct() {
$this->db = Database::getInstance();
}
}
class User extends Model {
public function getUsername($id) {
// je kan hier $this->db aanroepen
}
}
?>
Ik vind het zelf ook redelijk vervelend om steeds een database object via de constructor mee te geven, en dan is dit een oplossing waarmee alles wat soepeler gaat. Ik ben benieuwd wat de rest van zoiets ^ vind
Not Moose, dat is het singleton pattern. In dit geval kun je dus maar 1 database connectie gebruiken in je hele request, je krijgt telkens dezelfde instance. Hierdoor maak je Test driven Development onmogelijk.
En denk nu eens over het gebruik van deze applicatie op een host zonder database? Dan moet je bijv. een FileDatabase klasse gaan gebruiken en mag je al je models aanpassen.
Tevens vind ik User geen model, UserModel of UserMapper daarintegen wel.
Ik denk niet dat OP de intensie heeft om tests te implementeren in zijn script. Ook denk ik niet dat hij een filedatabase gaat gebruiken in plaats van een sql database. Overigens ben je met PDO al redelijk goed bezig op dat opzicht.
Singleton is een oplossing, en het is/was populair voor een reden. Het is niet een verkeerde manier, het is een manier.
Ik denk dat jullie alles een beetje aan het overdenken zijn, zeker aangezien de vragen die de OP stelt. Als hij nooit singleton gaat gebruiken, zal hij ook nooit achter de sterke/zwakke punten komen :)
Ik ben een grote voorstander van OOP, maar ik vraag me af of dat in PHP vaak meer als een doel dan als een middel beschouwd wordt.
Om Wouters voorbeeld van een user aan te halen, wat ga je doen als je 6 verschillende type users hebt, ga je dan voor elke type user de user class extenden? Nee toch?