login  Naam:   Wachtwoord: 
Registreer je!
 Forum

Class functie statisch en niet-statisch tegelijk maken

Offline Rik - 22/07/2008 21:38 (laatste wijziging 22/07/2008 21:39)
Avatar van RikGouden medailleGouden medaille

Crew algemeen
Ik heb een class om bestanden mee te bewerken, met daarin onder andere een functie om de inhoud uit te lezen. Heel simpel ziet die er zo uit:
  1. class File {
  2. public $location = null;
  3.  
  4. public function __construct($location) {
  5. $this->location = $location;
  6. }
  7.  
  8. public function getContents($location = null) {
  9. $location = isset($this) ? $this->location : $location;
  10. // return de contents
  11. }
  12. }


Nu kan ik een instance van die class aanmaken en daarna de functie getContents aanroepen, maar dat zou ik tegelijk ook graag statisch willen kunnen doen, met File::getContents() dus.

Helaas geeft dat een strict error:[error]Strict Standards: Non-static method File::getContents() should not be called statically[/error]

Dat klinkt logisch, dus dan maak ik er een static function van door er het keyword static voor te zetten. Nu geeft het statisch aanroepen geen probleem meer, maar bij vanuit een instance aanroepen bestaat de $this variabele niet meer.

Dat is ook logisch omdat php de functie nu als geheel statisch behandelt. Op deze manier kom ik dus niet tot een oplossing.

Als ik dan besluit de strict errors te negeren werkt dit opzich goed, todat ik het volgende probeer:
  1. class Andere {
  2. public function doeWat($location) {
  3. echo strrev(File::getContents($location));
  4. }
  5. }
  6.  
  7. $andere = new Andere;
  8. $andere->doeWat('bestand.txt');
Dan krijg ik een vanuit de eerste regel van m'n getContents functie:[error]Notice: Undefined property: Andere::$location[/error]Php vindt blijkbaar dat $this gedefinieerd is in getContents() als ik getContents() vanuit een andere instance aanroep.

Zoiets heb ik nog nooit eerder meegemaakt, dus ik ben gaan zoeken of het misschien een bug in php is. Toen kwam ik dit tegen:
http://bugs.php.net/bug.php?id=9005

Daarin wordt uitgelegd dat dit helemaal klopt en juist handig zou zijn:
Citaat:
class::method() isn't a static call in PHP (it isn't always a static
call in C++ either).
The primary use for class::method() is actually calling methods from
your parent class, not calling 'static methods' (the ability to create
static classes and call their methods is pretty much a positive 'side
effect').

So, this is the intended behavior.


Handig of niet, hierdoor kan ik mijn probleem niet oplossen. Heeft iemand een idee hoe ik dit wel aan zou moeten pakken?

Aan antwoorden als: "Waarom gebruik je niet gewoon file_get_contents()?" heb ik niets, want in getContents() moet meer gebeuren dan alleen file_get_contents() aan roepen. Voor de geïnteresseerden: er wordt bijboorbeeld rekening gehouden met het include path.

5 antwoorden

Gesponsorde links
Offline nemesiskoen - 23/07/2008 01:20 (laatste wijziging 23/07/2008 01:21)
Avatar van nemesiskoen Gouden medaille

PHP expert
Er zit een grote fout in je ontwerp. Een functie kan enkel een of een klassefunctie (static) zijn of niet, niet allebei. Daar php niet zo strict is bestaat de mogelijkheid (jammer genoeg) wel. Je zou een kleine aanpassing kunnen toevoegen: een andere functie maken "getFileContents" oid waarin een instantie van de klasse wordt gemaakt en daarop getContents wordt aangeroepen:
  1. <?php
  2. class File {
  3. // ...
  4. public static getFileContents($location = null) {
  5. $temp = new File($location);
  6. return $temp->getContents();
  7. }
  8. }


Waarom is dit verkeerd in ontwerp: dit heeft niets met de klasse File te maken, wel met een instantie ervan. (maw: eerder groeperen van functies ipv modelleren).
Offline Stijn - 23/07/2008 01:22
Avatar van Stijn PHP expert Als getContents() eigenschappen gebruikt of verandert van de class, zie ik het nut niet in van getContents() statisch te maken.
Offline Rik - 23/07/2008 09:49
Avatar van Rik Gouden medailleGouden medaille

Crew algemeen
@stijn,
Ik wilde het ook statisch maken om ook met File::getContents('bestand.txt'); de inhoud op te kunnen vragen. Dus zonder eerst een instance van File te maken.

Als ik in plaats van
  1. $location = isset($this) ? $this->location : $location;
het op deze manier zou doen:
  1. $location = isset($this) && get_class($this) === 'File' ? $this->location : $location;
dan zou het volgens mij (niet strict) wel werken.

Ik zie nu meer dan eerst dat dit niet handig is. Een extra functie inbouwen zoals vage voorstelt doe ik liever niet omdat het dan wel erg onoverzichtelijk wordt voor iemand die niet op strict fouten let. Die zou dan net zo makkelijk getContents als getFileContents aanroepen en dat geeft dan problemen.

Dit ga ik dan maar oplossen door een 'normale' functie getFileContents te maken die dan een instance van de File class aanmaakt en dan getContents aanroept.

In die class staan nog meer functies die ik oorspronkelijk static en niet-static tegelijk wilde hebben, maar die verander ik dan op dezelfde manier. Waarschijnlijk wordt m'n hele class dan wat overzichtelijker zonder allemaal van die isset($this) statements overal tussendoor.
Offline nemesiskoen - 23/07/2008 10:54 (laatste wijziging 23/07/2008 11:12)
Avatar van nemesiskoen Gouden medaille

PHP expert
Je kan ook via een factory een dummy instantie maken waar de gebruiker geen besef van heeft:

  1. File::temp("path")->getContents();
  2. // create/factory/... een andere naam kan ook
Offline Rik - 23/07/2008 19:25
Avatar van Rik Gouden medailleGouden medaille

Crew algemeen
Dat kan ook, maar dat wordt voor mij dan te omslachtig. Ik was juist op zoek of je op dezelfde korte manier (File::getContents()) die functie aan kan roepen.

Ik ga dan toch dat soort functies alleen non-static maken en voor static gebruik een losse functie maken die niet in de class zelf zit.

Voor de performance zal dat hopelijk dan niets uitmaken omdat de class-functies wat versimpelen en een extra instance maken (inclusief bijbehorende checks) is ook niet zo waanzinnig zwaar.
Gesponsorde links
Dit onderwerp is gesloten.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.231s