[Design Pattern] Elke class beschikbaar maken

Pagina: 1
Acties:
  • 170 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Ik heb een aantal classes:
* db
* user
* forum
* topics
* error
* output

Nou wil ik al deze classes beschikbaar maken aan elkaar. Dus class user kan gebruik maken van de database, en een error raisen e.d. Maar die classes mogen niet een nieuw object aanmaken, maar gebruik maken van de huidige class.

Op het moment doe ik dit op deze manier, maar dat is nogal lelijk ;)
$db = new database();
$db->set(&$db,&$user);

Nu heb ik even gekeken naar het Singleton pattern, maar of ik snap 'm niet, of het doet niet wat ik wil :)
Ik zal zelf te denken aan een class:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class classes
{
 function classes()
 {
 $this->array["db"] = new db();
 $this->array["user"]= new user();
 }

 function get($name)
 {
 return $this->array[$name];
 }

}

Waardoor ik via parent::get("db"); de database op kan vragen in een class. (toch?)
Maar dat betekend dat ik in de 'root' van het programma niet meer normaal classses aan kan roepen, maar dat alles via deze class moet gaan?

Dus, de vraag is, geef me wat tips :)

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Nee, je voorbeeld klopt niet.

Wat je namelijk vergeet, is wanneer je een class laat overerven van een parent-class "classes" er weer opnieuw een instantie gemaakt wordt van de class "classes" en daarin weer nieuwe instanties van de classes "db" en "user". Je kunt namelijk niet inheriten van een instantie van een class (een object) maar enkel van een class (de beschrijving van een object, abstractie. Als er in deze abstractie staat, dat er elke keer wanneer er een instantie aangemaakt wordt (in de constructor) weer nieuwe 'db' en 'user' aangemaakt moeten worden, betekent dat dus, dat er elke keer wanneer er een instantie van een derived class wordt aangemaakt, er ook weer opnieuw de constructor van de parent aangeroepen moet worden.

Je moet dus in de classes niet inheriten van de classes class, maar een property inbouwen die verwijst naar een enkele, statische instantie van de class 'classes'.

Vervolgens moet deze statische instantie gedefinieerd worden in een laag boven de classes zelf, gezien er 1 laag moet zijn die alle classes vertelt welke classes-instantie ze mogen/moeten gebruiken.

Kortom, zo'n classes-class is niets meer dan een wrappertje, die je net zo goed in een associative array kunt zetten ;)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • XTerm
  • Registratie: Juli 2001
  • Laatst online: 10-06 17:45
Hm, kan je niet gewoon in elke klasse pointerdeclareren voor de andere klassen en ze dan invullen als ze allemaal geladen zijn ?
code:
1
2
3
4
5
6
7
8
9
class y {
public:
  int c,d;
  x y;}*P;

class x {
public:
  int a,b;
  y x; }; *T

En dan na new T,P
code:
1
2
3
T->x=P->y;
of
P->y=T->x;

Acties:
  • 0 Henk 'm!

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
XTerm89D schreef op 07 augustus 2002 @ 09:51:
Hm, kan je niet gewoon in elke klasse pointerdeclareren voor de andere klassen en ze dan invullen als ze allemaal geladen zijn ?
Zo doe ik dat nu dus al..
Ik doe dus
$user->database=&$db;


ja het is PHP

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Je zou het natuurlijk ook in de constructor kunnen regelen.
bv.
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
47
48
49
50
51
52
class classes {

    function set ($newclass,$name){
        $this->array[$name]=$newclass;
    }

    function get($which) {
        if (isset($this->array[$which]) && is_object($this->array[$which])) {
            return $this->array[$which];
        }
        else {
            return false;
        }

    }
}


class a {
    var $container;
    function a($container){
        $container->set(&$this,get_class($this));
        $this->container=&$container;
    }

    function a_fun(){
        echo "A";
    }

    function callb() {
        $parent=$this->container->get("b");
        $parent->b_fun();
    }
}

class b {
    var $container;

    function b($container){
        $container->set(&$this,get_class($this));
        $this->container=&$container;
    }

    function b_fun(){
        echo "B";
    }
}

$container = new classes();
$blaat=new a(&$container);
new b(&$container);
$blaat->callb();

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Als je een pattern wilt, Singleton wordt hier vaak voor gebruikt.

Maar PHP en patterns...hmmm :P

Overigens is $db->set(&$db,&$user); geen goed PHP (meer).

Ik laat zelf constructors gewoon aliases doorgeven, dus:

class Users {
var $CDatabase;

function Users(&$CDatabase) {
$this->CDatabase = &$CDatabase;
}
}

Singleton werkt overigens alleen in die nieuwe PHP versie, omdat je nu nog niet kan dereferences op functie resultaten. Dus je kan niet doen Log::Instance()->foo(), hij loopt stuk op dat pijltje dan. Ook heb je nog geen statics dus dat scheelt weer.

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Misschien is dit een interresante link.

http://www.zend.com/zend/trick/tricks-app-patt-php.php

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Naar mijn idee is PHP helemaal niet geschikt voor zulke zaken door een groot gemis: het niet goed kunnen onderscheiden van classes.

Want wat heb je nou in die array staan: een lading classes die toch niets met elkaar te maken hebben die alleen te herkennen zijn aan een string. Echter, maak jij een typfout dan kan alles de db opeens niet meer vinden en krijgt ie opeens een user terug en gaat ie daar db functions op callen. Want hoe weet jij nou als ik een add( $user, "db" ); doe dat het goed gaat?

Beter zou zijn als het mogelijk was om een beschrijving te hebben van hoe een db class eruit moet zien (interface) en dan de getDb( ); aan te roepen. Add db zou dan ook alleen maar classes moeten toestaan die de dbInterface implementen.
Nu heb je een minder generieke oplossing, maar wel een type safe oplossing.

Echter een goede echte mooie generieke oplossing heb ik niet, ik zal Singelton pattern ff opzoeken :)

Acties:
  • 0 Henk 'm!

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 19-09 22:18

chem

Reist de wereld rond

LET OP!
PHP is zo lek als een zeef met by-reference pasen van argumenten.
Lees hieronder wat ik (vergeten) naar php's bug wilde sturen:

Solution for memoryleak with by-reference passing of objects

As some of you might know, PHP has the tendency to leak a certain amount of memory when passing objects to other objects by reference. Refreshing the page in the browser results in a build up of lost memory - eventually resulting in, to say the least, odd behaviour.
Destroying either or both objects leaves the memory in use, resulting in a memoryleak.

Using a patch made by Hans found here we were able to determine the amount of memory in use after completion, and find a solution.
Just apply the patch, recompile and change your Apache logformat to:
LogFormat "%h %l %u %t \"%r\" %>s %b PHP: used:%{mod_php_memory_usage}n left:%{mod_php_memory_left}n." common_with_php_memusage
and then use it with:
CustomLog /www/logs/access_log common_with_php_memusage

The following code demonstrates a 22 byte memoryleak.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class a
{
    function a()
    {
        $this->b = new b($this);
    }

    function b()
    {
        return $this->b->name;
    }
}
class b
{
    var $name = "abc";

    function b(&$a)
    {
        $this->a =& $a;
    }
}
$a = new a();
echo $a->b();


To solve the problem, we extend the class from PEAR, and use it's destruct mechanism to set the objects being referenced to to NULL. Unset() doesn't help, as it merely removes the 'link' to the object, and doesn't delete the object itself.

code:
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
require_once "PEAR.php";
require_once "PEAR.php";
class a
{
    function a()
    {
        $this->b = new b($this);
    }

    function b()
    {
        return $this->b->name;
    }
}
class b extends PEAR
{
    var $name = "abc";

    function b(&$a)
    {
        $this->PEAR();
        $this->a =& $a;
    }

    function _b()
    {
        $this->a = null;
    }
}
$a = new a();
echo $a->b();


I hope this will be fixed as promised in PHP 4.3.x (ZE2).

Klaar voor een nieuwe uitdaging.


Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

chem schreef op 07 augustus 2002 @ 10:51:
LET OP!
PHP is zo lek als een zeef met by-reference pasen van argumenten.
Lees hieronder wat ik (vergeten) naar php's bug wilde sturen:

<SNIP>

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class a
{
    function a()
    {
        $this->b = new b($this);
    }

    function b()
    {
        return $this->b->name;
    }
}
class b
{
    var $name = "abc";

    function b(&$a)
    {
        $this->a =& $a;
    }
}
$a = new a();
echo $a->b();


<SNIP>
Maar geef je hem nu niet verkeert door? of ligt het aan mij?


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
class a
{
    function a()
    {
        $this->b = new b(& $this); // Hier de reference doorgeven
    }

    function b()
    {
        return $this->b->name;
    }
}
class b
{
    var $name = "abc";

    function b($a)
    {
               //    $this->a =& $a;  // En niet hier reference doorgeven
                     $this->a=$a;      // $a is tenslotte al de reference van object a
 
    }
}
$a = new a();
echo $a->b();

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
thanx allemaal, hier kan ik verder mee :)

Acties:
  • 0 Henk 'm!

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 19-09 22:18

chem

Reist de wereld rond

lucard: hij lekt toch, ook zonder die =&

Klaar voor een nieuwe uitdaging.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Please note, PHP is moving to eliminate passing variables by reference on
the function call. You must declare the variable is pass-by-ref in the
function definition.

In the past this was possible, given the following function definition:

function foo ( $a ) {
...
}

$b = 5;
foo ( &$b );

In your php.ini, it is stated that they are moving to eliminate this.
Thus, you should (for future compatability) not use this method. Instead,
you should do:

function ( &$a ) {
...
}

$b = 5;
foo ( $b );

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

ow? :? :?

* LuCarD duikt weer eens de manual in...

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
wtf? Da's best vreemd :{

Acties:
  • 0 Henk 'm!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
LuCarD schreef op 07 augustus 2002 @ 17:01:
ow? :? :?

* LuCarD duikt weer eens de manual in...
Lijkt me toch logisch? Als programmeur van de functie weet je niet of je nou het argument in je functie als reference of als value argument moet gaan behandelen, wat toch een behoorlijk verschil maakt. Hierdoor zou misvormde data kunnen ontstaan bij het geven van een reference argument terwijl men een value verwacht!

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Vergelijk het met C++ references:

void foobar(A& a) {
a.doSomething();
}

A a(1);
foobar(a);

Als je zou schrijven:
foobar(&a);

Stuur je eigenlijk een pointer. (PHP kent geen pointers overigens, een & is een alias wat het meest lijkt op een reference)

edit:
In het laatste geval zou je compiler onmiddelijk een type mismatch uitspugen. Weer een voordeel van strong type checking...

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Vreemd, nee niet echt...

Aangezien je nu bij de definitie al kan opgeven of je met de reference wil werken of niet.

Maar PHP kennende kan je beide door elkaar gebruiken (helaas :| )
Glimi schreef op 07 augustus 2002 @ 17:08:
[...]
Lijkt me toch logisch? Als programmeur van de functie weet je niet of je nou het argument in je functie als reference of als value argument moet gaan behandelen, wat toch een behoorlijk verschil maakt. Hierdoor zou misvormde data kunnen ontstaan bij het geven van een reference argument terwijl men een value verwacht!
Logisch en realiteit ontlopen elkaar wel eens.....

Ik wist het niet...

[edit]
Waar staat deze note eigenlijk? Ik kan hem niet zo snel vinden en om de hele manual "nogmaals" door te lezen is een beetje... O-)

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

LuCarD schreef op 07 augustus 2002 @ 17:10:
Logisch en realiteit ontlopen elkaar wel eens.....
En in PHP land lopen ze hand in hand...

Haha, oops, ik bedoelde het juist andersom :P Maar hij klonk zo leuk...

Acties:
  • 0 Henk 'm!

  • Rense Klinkenberg
  • Registratie: November 2000
  • Laatst online: 03-09 14:12
chem schreef op 07 augustus 2002 @ 10:51:
I hope this will be fixed as promised in PHP 4.3.x (ZE2).
Waarschijnlijk zal er wel verbetering zijn, omdat het hele object model opnieuw is gebouwd.

* Rense Klinkenberg gaat eens kijken of de patch ook php4.3.0-dev-zend2 werkt om eens te testen.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

LuCarD schreef op 07 augustus 2002 @ 17:10:
Waar staat deze note eigenlijk? Ik kan hem niet zo snel vinden en om de hele manual "nogmaals" door te lezen is een beetje... O-)
Weet niet zo snel meer, ergens bij het stukje over references ;)

Maar in je .ini staat overigens ook dit:
; Whether to enable the ability to force arguments to be passed by reference
; at function call time. This method is deprecated and is likely to be
; unsupported in future versions of PHP/Zend. The encouraged method of
; specifying which arguments should be passed by reference is in the function
; declaration. You're encouraged to try and turn this option Off and make
; sure your scripts work properly with it in order to ensure they will work
; with future versions of the language (you will receive a warning each time
; you use this feature, and the argument will be passed by value instead of by
; reference).
allow_call_time_pass_reference = Off

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

|:( |:( |:(

Zucht... dat had ik toch wel moeten kunnen vinden... Maar zo vaak lees ik mijn php.ini niet door...

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
LucarD schreef:
offtopic:
Nielsz: Hoever ben je met jouw class handler?


Goed, ik heb dus een class $classes gemaakt.
ALs ik nou een ander object aanmaak (user ofzo) dan doe ik dat zo: $user= new user($classes);

Nog niet echt mee gewerkt, maar het ziet er goed uit :)

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Hmm... Ik zit geloof ik een beetje op de zelfde route...

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Zoijar:
Vergelijk het met C++ references:

void foobar(A& a) {
a.doSomething();
}

A a(1);
foobar(a);

Als je zou schrijven:
foobar(&a);

Stuur je eigenlijk een pointer. (PHP kent geen pointers overigens, een & is een alias wat het meest lijkt op een reference)
't woord pointer is hier een beetje slecht gekozen, imo :)
Je geeft een adres mee. Een pointer wordt meestal genoemd wanneer men het heeft over een 'variabele' of een 'constante' die een 'adres' bevat, en daarmee 'een pointer is'. Je geeft dus niet de pointer mee, maar 't adres van a.

Niet om te zeiken, maar 't is wellicht iets duidelijker :)
edit:
In het laatste geval zou je compiler onmiddelijk een type mismatch uitspugen. Weer een voordeel van strong type checking...
En terecht! ;)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

Verwijderd

om alles aan elkaar beschikbaar te krijgen heeft er nog eens iemand iets bedacht met een core class... even zoeken...

[rml][ PHP] Extenden van een class (onb. naam)[/rml]
en dan bij het lange bericht van graasgast...

Acties:
  • 0 Henk 'm!

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 23:31
Ik dacht Patterns, eindelijk een serieus topic. Blijkt het over PHP te gaan. :(

Niks mis met PHP. Prima beginners taal, veel mensen leren er voor het eerst mee werken. Maar PHP en serieus OO proggen. Euhm... Sorry lui.

In ieder geval...

Indien mogelijk gewoon een Singleton gebruiken. Een object aan maken en dan met methoden pointers in de class configureren is gewoon VIES. Is bah, getuigd van slecht design. (Misschien wel praktisch design, maar ik ken PHP niet :D)

Als je een singleton goed kan implementeren in PHP (een Singleton op zich is een eitje), dan werkt het prima. Doe je het echt goed, dan heb je een component wat generiek is en betrekkelijk eenvoudig is te herbruiken. (Bijvoorbeeld door het ding configureerbaar te maken aan de hand van een config file.)

Implementatie details van een Singleton in PHP heb ik geen idee van. Simpelweg omdat ik nooit praktisch gewerkt heb met PHP. Heb er wel is naar gekeken, maar kwam al snel tot de conclusie dat het niks voor mij is.

Acties:
  • 0 Henk 'm!

Verwijderd

In PHP kun je zowiezo geen functies static maken binnen een klasse dus het singleton pattern kun je wel vergeten idd :) . Dan ben je al snel weer aangewezen op smerige constructies zoals onnodig veel parameters in constructors, of nog erger, globals :r .

Acties:
  • 0 Henk 'm!

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 23:31
Ieuw!! :r

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

(Bijvoorbeeld door het ding configureerbaar te maken aan de hand van een config file.)
:?

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz

Pagina: 1