[PHP] static waarde overschrijven

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
Ik probeer wat MVC functies te maken. Ik heb een superclass Model. Hiervan maak ik een subclass Member. in Member wil ik een static variabele maken, bijvoorbeeld table, die vanuit Model beschikbaar is. als ik dan bijvoorbeeld Member::get() aanroep moet hij de tabel die bij Member hoort pakken. waarschijnlijk is code makkelijker, ik heb het nu ongeveer zo geprobeerd:

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
<?php

abstract class Model {

protected static $table;

public static function get() {
 doSql('select from ' . self::$table);
}

}

class Member extends Model {
 public static function init() {
  self::$table = 'MemberTable';
 }
}

class Car extends Model {
 public static function init() {
  self::$table = 'CarTable';
 }
}

?>


dit werkt echter niet. als ik in 1 pagina 2 verschillende soorten models opvraag (bijvoorbeeld Member en Car), overschrijft de tabel van Car die van Model. nu ik erover nadenk, is dit eigenlijk vrij logisch.

hoe los ik dit wel op?

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Als ik me niet vergis werkt die hele 'self' niet als je geen instantie van het object hebt.
Ook weet ik niet wanneer je uberhaupt init() uitvoert, en dus je variabele probeert te vullen?

Een logische manier lijkt mij niet met statics maar met instanties van je object te werken.

[ Voor 20% gewijzigd door frickY op 06-03-2008 16:12 ]


Acties:
  • 0 Henk 'm!

  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
die init voer ik uit onder de declaratie van Member, ben ik hier even vergeten.
self werkt wel, want verwijst namelijk naar de klasse, niet de instantie (dat is $this).

en het moet static of iets wat erop lijkt. het is immers een beetje onzinnig om getMember te doen op een instantie van Member. je voert getMember namelijk uit omdat je dan nog geen Member-instantie hebt.

Acties:
  • 0 Henk 'm!

  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
ok, ik denk dat ik een oplossing heb:

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
<?php

$MODELS = array();
$MODELS['Member'] = array(
 'table' = 'memberTable',
 'fields' = array(
            'name' => self::FT_STRING,
            'password' => self::FT_STRING,
            'type' => self::FT_INT,
            'fullname' => self::FT_STRING,
            'street' => self::FT_STRING,
            'street2' => self::FT_STRING_ORNULL,
            'zipcode' => self::FT_STRING,
            'city' => self::FT_STRING,
            'telephone' => self::FT_STRING_ORNULL,
            'email' => self::FT_STRING
        )
);

abstract class Model {

   public function __construct($type, $data) {
      ...
   }

}

class Member {

   public function getFriends() {
     ...
   }

}

class DAO {

   public function construct($type) {
      ....
   }

   public function get() {
     doSqlThingy('select from ' . $MODEL[$type]['table']);
     new $type($type, $dataFromSql);
   }

}

?>

Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
frickY schreef op donderdag 06 maart 2008 @ 16:11:
Als ik me niet vergis werkt die hele 'self' niet als je geen instantie van het object hebt.
Ook weet ik niet wanneer je uberhaupt init() uitvoert, en dus je variabele probeert te vullen?
Dat werkt dan wel, maar het probleem hier is dat static members en functies niet inherit worden van een superclass. De Member class heeft dus helemaal geen static member $table, dus deze via self::$table opvragen kan niet.

Je kunt proberen om er Model::$table van te maken, maar persoonlijk vind ik dat niet zo netjes. Dit is inderdaad duidelijk een geval voor 'gewone' objecten en inheritance.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
De Member class heeft dus helemaal geen static member $table, dus deze via self::$table opvragen kan niet.
Dat klinkt logisch, maar in PHP kan het toch. self::$table in Member verwijst dan naar Model::$table. Misschien denk je nu aan Java.

Maar goed, het probleem is ongeveer opgelost, zie links:
http://bartvanheukelom.dy...#_fastmvc_classes_models_
http://www.phpfreakz.nl/forum.php?forum=9&iid=1112635

[ Voor 15% gewijzigd door 2playgames op 07-03-2008 11:45 ]


Acties:
  • 0 Henk 'm!

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 20:32
Je kan ook wachten tot PHP5.3 uit is, daar is namelijk een oplossing voor deze tekortkoming van PHP :)

http://nl.php.net/manual/....late-static-bindings.php

(Ik zit hier zelf ook op te wachten voor een eigen implementatie)

What do you mean I have no life? I am a gamer, I got millions!


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Kun je eens een voorbeeld geven wanneer dit handig zou zijn? Ik vraag me namelijk af of het niet netter is op te lossen.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

Michali schreef op vrijdag 07 maart 2008 @ 20:07:
Kun je eens een voorbeeld geven wanneer dit handig zou zijn? Ik vraag me namelijk af of het niet netter is op te lossen.
Zeer handig voor een ActiveRecord design pattern implementatie, en dat is denk ik niet netter op te lossen zonder late static binding. (Volgens mij probeert TS dit ook te doen ;)). Dan heb je b.v. zoiets als:

PHP:
1
2
3
4
5
6
7
8
9
10
11
<?php

class ActiveRecordBase {
  public static $table_name;

  public static find($limit, $options = array()) {
    //...
  }
}

?>


En je wil zoiets als:
PHP:
1
2
3
4
5
6
7
8
9
10
<?php

public Member extends ActiveRecordBase {
  public static function initialize() {
    self::$table_name = 'members';
  }

}

?>


Als static late binding zou werken, zou je nu klassengebonden finders hebben, hetgeen semantisch ook klopt en wat je wil. Je kan dan zoiets doen als

PHP:
1
Member::find('first', array('conditions' => array('username' => 'prototype')));


De 'oplossing' / workaround die ik nu heb door 't ontbreken van static late binding in PHP is om te werken met objecten die als prototypes dienen... (no pun intended ;))

Acties:
  • 0 Henk 'm!

  • Toolskyn
  • Registratie: Mei 2004
  • Laatst online: 22-06 11:01

Toolskyn

€ 500,-

Volgens mij is dit vrij simpel op te lossen in PHP door gebruik van parent::
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
abstract class Model {
    protected static $table;
    
    public static function get() {
        print self::$table;
    }
}

class Member extends Model {
    public static function init() {
        parent::$table = 'MemberTable';
    }
}

Member::init();
Member::get();
?>

Uitvoer:
MemberTable


Late static binding is in dit geval niet van toepassing. Bij late static binding gebruik je in de parentklasse (basisklasse) iets wat je in de childklasse (subklasse) weer wilt veranderen. Dit kan bijvoorbeeld niet in PHP < 5.3:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

class A {
    protected static $var = 'foo';
    
    public static function display() {
        print self::get();
    }

    
    public static function get() {
        return self::$var;
    }
}

class B extends A {
    public static function get() {
        return 'better ' + self::$var;
    }
}

B::display();
?>

Je zou graag willen dat wanneer je B::display() gebruik je ook de get() methode van B gebruikt. In PHP 5.3 of later zal dit als uitvoer geven:
better foo

Terwijl eerdere versies dit zullen doen:
foo

Maar het gegeven voorbeeld kan dus zonder het verhaal van late static binding aangepakt worden.

gewooniets.nl


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Dat klopt niet.

Kijk maar naar dit voorbeeld:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
abstract class Model {
    protected static $table;
    
    public static function get() {
        print self::$table;
    }
}

class Member1 extends Model {
    public static function init() {
        parent::$table = 'MemberTable 1';
    }
}

class Member2 extends Model {
    public static function init() {
        parent::$table = 'MemberTable 2';
    }
}

Member1::init();
Member2::init();
Member1::get()

Dit print "MemberTable 2" uit ipv. het gewenste "MemberTable 1". Dit omdat beide subclasses dezelfde variabel aanspreken.

Overigens zou in je 2de voorbeeld static::get(); in display aangeroepen moeten worden voor die late static binding. Anders krijg je dus wel gewoon 'foo'.


Ik merk wel dat ik geen fan ben van dat ActiveRecord pattern. Klinkt als het misbruiken van een class voor andere doelen dan zijn primaire taak. Lijkt me niet zo veel werk om dit aan een ander object te geven, dan hoef je dit soort vreemde oplossingen ook niet toe te passen.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 20:32
Ik wil het gebruiken voor een model van database entities.

Mijn superklasse heeft een aantal standaard implementaties, die moeten werken met de waardes uit de child klasses.

Mijn superklasse bevat dan namelijk de implementaties om de insert, delete en update queries uit te voeren, maar de childklasse moet dan gedefinieerd hebben welke tabel hij representeert, en welke kolommen die tabel bevat :)

What do you mean I have no life? I am a gamer, I got millions!


Acties:
  • 0 Henk 'm!

  • Toolskyn
  • Registratie: Mei 2004
  • Laatst online: 22-06 11:01

Toolskyn

€ 500,-

Inderdaad je hebt helemaal gelijk, stom van me. PHP is in dit geval wel lichtelijk een 'pain in the ass' om het maar zo uit te drukken.

@TS: Waarom wil je eigenlijk die naam van de tabel perse statisch opslaan? Misschien dat het qua idee wel beter is wat je wil (om wat voor redenen dan ook), maar waarschijnlijk krijg je een elegantere oplossing als je je aan de taal aanpast en van het idee statisch afstapt in dit geval.

gewooniets.nl


Acties:
  • 0 Henk 'm!

  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
Dat heb ik ook allang gedaan :) zie een paar posts terug
Pagina: 1