[php]probleem aanroepen classes vanuit andere classes

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • link0007
  • Registratie: Augustus 2006
  • Niet online
Hallo,

Ik ben nu bezig mijn site opnieuw op te bouwen, en ga daarvoor gebruik maken van OOP. Ik heb in mijn design plannen 6 classes staan die functies bevatten voor verschillende delen van de site.
Nu ik klaar ben met de tekeningen en programma structuur diagrammen, ben ik begonnen met het programmeren van de eerste paar testjes. Maar vrijwel direct liep ik tegen design problemen aan.

Ik heb in mijn voorbeeld 2 classes:
- scenes
- database

In de test staat deze code:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
    include 'mysqli_extended.php';
    include 'database.php';
    include 'scene.php';

        $odatabase = new database;
    $oscene= new scene;
        $db = new mysqli_extended;

    $list = $oscene->details(1);
    foreach ($list as $value)
    {
        echo $value."<br />";
    }
?>


Dan heb ik in database.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
class database
{
        public function column_list($type)
    {
        if ($type == 'scene')
        {
            return "
                scene_id,scene_alive,scene_ip,scene_filename,scene_size,
                scene_title,scene_author,scene_description,scene_password,
                scene_datetime,scene_rating,scene_nr_downloads,scene_nr_views,
                scene_nr_comments,scene_nr_ratings,scene_response_to,scene_last_edit,
                scene_last_edit_by 
                ";
        }
    }
    public function fetch_details($type,$id)
    {
        if ($type='scene')
        {
            $query = $db->prepare("SELECT ".$this->column_list('scene')." FROM box_scenes WHERE scene_id = ?");
            $query->bind_param('i', $id);
            $query->execute(); 
            $query->store_result();
            $line = $query->fetch_assoc();
        }
        $query->close();
          echo "fetch flawless.";
    return $line;
    }
}
?>


En in scene.php het volgende:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class scene
{
    public function details($scene_id)
    {
          echo "start of function details() <br />";
        $scene_array = $odatabase->fetch_details('scene',$scene_id);
                 echo "database linked in function details() <br />";
        if ($scene_array['scene_alive'] == true)
        {
            return $scene_array;
        }
        else
        {
            return false;
        }
    }
}
?>



Sorry als het een beetje op een code-dump lijkt, maar ik heb het idee dat het allemaal al zo minimaal mogelijk is nu.
Anyway, dit werkt niet, en logisch ook.


Maar wat is nu de beste manier om in elke class en elke functie toegang te geven tot de verschillende classes?

Globals moet ik ontwijken heb ik gehoord. Maar ik snap die singletons niet helemaal. Ik heb het geprobeerd maar daar kwamen ook nog steeds errors van. En daarnaast moest ik het in iedere functie opnieuw doen? Ik wil gewoon een keer in de constructor alle classes binnen slepen, maar niet meerdere objecten van dezelfde class hebben.

Ik wil bijvoorbeeld niet dadelijk 7x een db object openen.

Kan iemand me uitleggen hoe ik hier alles op orde krijg?

offtopic:
Ik weet niet zeker of dit taal-afhankelijk is, maar ik meen ooit eens gelezen te hebben dat PHP niet volledig OOP is.

IF IF = THEN THEN THEN = ELSE ELSE ELSE = IF;


Acties:
  • 0 Henk 'm!

  • link0007
  • Registratie: Augustus 2006
  • Niet online
Laat maar, heb het probleem opgelost door rond te klooien met dubbele dubbele punten. Maar kan iemand me zeggen of de volgende oplossing goed is?

programma:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
    include 'mysqli_extended.php';
    include 'database.php';
    include 'scene.php';

    $scene =& scene::getInstance();
    $database =& database::getInstance();
    $list = $scene->details(1);
    foreach ($list as $value)
    {
        echo $value."<br />";
    }
?>



scene.php:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
class scene
{
    // object instance
    private static $instance;
    private static $database;

    public static function getInstance() 
    {
        if (!scene::$instance instanceof self) 
        {
            scene::$instance = new self();
            scene::$database =& database::getInstance();
        }
        return scene::$instance;
    }
    public function details($scene_id)
    {
        echo "start of function details() <br />";
        $scene_array = scene::$database->fetch_details('scene',$scene_id);
        echo "database linked in function details() <br />";
        if ($scene_array['scene_alive'] == true)
        {
            return $scene_array;
        }
        else
        {
            return false;
        }
    }
}
?>


database.php:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
class database
{
    // object instance
    private static $instance;
    private static $db;

    public static function getInstance() 
    {
        if (!database::$instance instanceof self) 
        {
            database::$instance = new self();
            database::$db = new mysqli_Extended('localhost','deb10784_phunbox','desk270jet','deb10784_phunbox'); 
        }
        return database::$instance;
    }
    public function column_list($type)
    {
        if ($type == 'scene')
        {
            return "
                scene_id,scene_alive,scene_ip,scene_filename,scene_size,
                scene_title,scene_author,scene_description,scene_password,
                scene_datetime,scene_rating,scene_nr_downloads,scene_nr_views,
                scene_nr_comments,scene_nr_ratings,scene_response_to,scene_last_edit,
                scene_last_edit_by 
                ";
        }
    }
    public function fetch_details($type,$id)
    {
        if ($type='scene')
        {
            $query = database::$db->prepare("SELECT ".database::$instance->column_list('scene')." FROM pbox_scenes WHERE scene_id = ?");
            $query->bind_param('i', $id);
            $query->execute(); 
            $query->store_result();
            $line = $query->fetch_assoc();
            return $line;
        }
        $query->close();
        echo "fetch flawless.";
        return $line;
    }
}
?>



Het lijkt mij best proper, maar ik hoor het graag als het beter kan! Ben van plan deze zomer eens goed in PHP te duiken :)

IF IF = THEN THEN THEN = ELSE ELSE ELSE = IF;


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Database.php, regel 19, moet dubbele = zijn ;)

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

Verwijderd

Waarom maak je $database een static property van scene? Waarom vind ik maar één keer $this in je hele source code? Dat lijkt me niet echt een goed teken. Het geheel is gewoon slecht ontworpen. Dat blijkt alleen al uit het feit dat je drie classes zonder parameters instantieert.

De scene class zou sowieso ofwel een constructor moeten hebben waaraan je $database meegeeft, of een losse functie waarmee je $database doorgeeft. Die scene class moet dan voor instanties die database class in een property opslaan. En dan dus géén static property, maar bijvoorbeeld $this->database.

En gebruik hoofdletters voor je klassenamen. Waarom doe je dat niet? Is dat een gevalletje "ik vind dat niet zo mooi staan"?

Als je echt object geörienteerd wilt leren programmeren doe je er beter aan bijvoorbeeld Visual C# 2008 Express Edition te installeren en daarmee aan de gang te gaan. Daarmee heb je meteen een heel aantal basisclasses waar je veel beter mee leert programmeren dan met zelfgebakken classes vanaf scratch.

Volgens mij is dit weer typisch een voorbeeld van eigenlijk nog niet toe zijn aan het bouwen van applicaties. Je mist simpelweg de basics, maar wilt al wel meteen iets compleet werkends maken.

Acties:
  • 0 Henk 'm!

  • link0007
  • Registratie: Augustus 2006
  • Niet online
#cheatah: Wat bedoel je met
Dat blijkt alleen al uit het feit dat je drie classes zonder parameters instantieert.
? Als ik geen parameters nodig heb dan heb ik die toch niet nodig? Er komt nog veel meer bij, dus een constructor komt er nog wel, met parameters. Maar eerst moet ik een basis hebben staan.

Inderdaad vind ik zaken zoals dit
code:
1
database::$db->prepare(....)

Vervelend, maar hoe zorg ik er dan voor dat het weer gewoon "$db" word, of "$this->$db"?

IF IF = THEN THEN THEN = ELSE ELSE ELSE = IF;


Acties:
  • 0 Henk 'm!

  • Borizz
  • Registratie: Maart 2005
  • Laatst online: 24-08 20:35
link0007 schreef op donderdag 24 juli 2008 @ 21:33:
#cheatah: Wat bedoel je met

[...]

? Als ik geen parameters nodig heb dan heb ik die toch niet nodig? Er komt nog veel meer bij, dus een constructor komt er nog wel, met parameters. Maar eerst moet ik een basis hebben staan.

Inderdaad vind ik zaken zoals dit
code:
1
database::$db->prepare(....)

Vervelend, maar hoe zorg ik er dan voor dat het weer gewoon "$db" word, of "$this->$db"?
PHP:
1
2
3
4
5
6
7
class Scene {
    protected $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }
}


Oftewel lees je even in in de programmeertaal die je gebruikt... Waarom zou je van al die classes maar 1 instance willen hebben trouwens? Volgens mij moet je je toch echt beter inlezen in OO design en programmeren.

If I can't fix it, it ain't broken.


Acties:
  • 0 Henk 'm!

  • Cascade
  • Registratie: Augustus 2006
  • Laatst online: 16-09 11:44
Wat je nu doet is nog procedureel programmeren, alleen dan met de procedures in classes gestopt en daarna om 'beperkingen' van die vorm heen werken (singletons gebruiken als een verkapte global maar dan binnen een class zelf). Dat maakt het geen OOP.

Het gebruiken van een singleton voor een database connectie vind ik dan nog geen slecht idee, als je als doel hebt om ook maar 1 open connectie naar je database toe te staan (maar doet die mysqli_extended class dat al niet?).

Als advies: je moet eens goed nadenken over wat jouw class scene allemaal moet doen en of die class database wel nodig is.

Je kan om te beginnen dit doen:
- ga na welke eigenschappen een 'scene' heeft, zet die als property in de class. Zoals het nu is, staan ze in een array die jouw functie fetch_details teruggeeft, heeft zo dus geen relatie met een specifiek Scene object...
- ga na hoe je die eigenschappen kan invullen als je een nieuwe instance van die class maakt. Ga je parameters via de constructor meegeven? Maak je functies daar voor? Heb je hier een functie nodig die het object vult vanuit de database?
Voorbeeld:
PHP:
1
public function fetchSceneFromDatabase( $db, $sceneId )

- welke bewerkingen kan je op een scene toepassen? Maak daar (relevante) functies voor in de class.
- kan je de scene ook weer opslaan in de database? Nog een functie van de class Scene.
- aanleren om fatsoenlijke foutafhandeling te gebruiken.

Ik zou in eerste instantie de array met velden voor een scene uit die class database halen en naar de class Scene zelf verhuizen. Als je meer onder de knie hebt van OOP en wat patterns daarvan kan je later altijd nog naar een volwaardige 'data abstraction layer' gaan (indien nodig).

Acties:
  • 0 Henk 'm!

  • link0007
  • Registratie: Augustus 2006
  • Niet online
Bedankt voor de opbouwende post :)

Het is inderdaad waar dat OOP voor mij enorm lastig lijkt nu.. Ben al jaren gewent aan pascal, en daar ging object oriented programmeren niet echt mee.

De applicatie die ik ga maken is in principe vergelijkbaar met iets als youtube. Dit is zoals de site nu is: http://www.phunbox.net/

De nieuwe site zal dan wel meer features hebben (gebruikers etc), maar kwa opbouw zal het er veel op lijken.

Daarom heb ik in mijn tekeningen deze classes bedacht:

- scene
- database
- backend
- user
- comment
- administration

Wat ik uiteindelijk wil, is dat ik de hele site opnieuw kan schrijven, op een manier die me beter instaat stelt dingen aan te passen, nieuwe dingen toe te voegen.. Een modulair ontwerp zeg maar.

Wat ik nu heb kwa functies in bijvoorbeeld scene is het volgende (komen nog wel meer bij.. maar deze zijn al geprogrammeerd):

new_scene($scene_file,$scene_title,$scene_author,$scene_description,$scene_password,$scene_response_to)
edit($scene_id,$scene_file,$scene_title,$scene_last_edit_by,$scene_description,$password)
details($scene_id)
delete($scene_id)
revive($scene_id)

Waar het OOP vooral naar voren komt is bijvoorbeeld bij de functie "new_scene":
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public function new_scene($scene_file,$scene_title,$scene_author,$scene_description,$scene_password,$scene_response_to)
    {
        $scene_id = scene::$database->new_id('scene');
        $scene_ip = scene::$backend->get_ip();
        if (scene::$backend->check_ban($scene_ip) == false)
        {
            $scene_filedetails = scene::$backend->file_upload($scene_id,$scene_file);
            scene::$database->add_scene
                        (
                            $scene_id,
                            $scene_ip,
                            $scene_filedetails['name'],
                            $scene_filedetails['size'],
                            $scene_title,
                            $scene_author,
                            $scene_description,
                            $scene_password,
                            $scene_response_to
                        );
        }
        return true;
    }


Hier vind ik het mooi dat ik snel bepaalde functies kan aanroepen, bijvoorbeeld om te kijken of de persoon die een scene wil uploaden niet gebant is.


In feite zal er dus nooit meer dan 1 object van elke class hoeven te bestaan in een script.


Heb ik hier echt wel nut van OOP? Of kan ik beter gewoon een stapel includes maken met functies erin?

IF IF = THEN THEN THEN = ELSE ELSE ELSE = IF;

Pagina: 1