Plaats nieuw bericht Plaats reactie Vorige onderwerp | Volgende onderwerp
Interaddict forum index » Multimedia, Internet en Design » [OOP - PHP4] Functie hergebruiken binnen een class
Bram
Site Admin

Bericht Geplaatst: 11 Apr 2007 12:36 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Ik ben bezig met een database class te schrijven in php. Ik ben nog niet zo heel erg thuis in het OOP (Object Orientated Programming) en heb de volgende vraag die iemand hier hopelijk kan beantwoorden.

Onderstaand is de complete class + een query extensie.

Code:
class Database
{   
   // Declare local variables
   var $_connect;
   var $_select;
   var $_name;
   var $_listTables = Array();
   var $_listFields = Array();
   var $_fieldscount;
   var $_connecttime;
   var $_tablestime;
   var $_numrowstime;
   var $_fieldstime;
   
   //Imitate PHP5 microtime behaviour
   function microtime_float()
   {
          list($usec, $sec) = explode(" ", microtime());
          return ((float)$usec + (float)$sec);
   }
   
   // Constructor; Connects to databaseserver and selects database
   function Database( $DB_location = NULL, $DB_username = NULL, $DB_password = NULL, $DB_databasename = NULL )
   {
      if($DB_location != NULL && $DB_username != NULL && $DB_password != NULL)
      {
         $startTime = $this->microtime_float();
         if( $this->_connect = @mysql_connect($DB_location, $DB_username, $DB_password) )
         {
            if( $DB_databasename != NULL )
            {
               $this->_name = $DB_databasename;
               if( !$this->_select = @mysql_select_db($this->_name, $this->_connect) )
                  return false;
            }
            else
            {
               return false;
            }
         }
         else
         {
            return false;
         }
         $endTime = $this->microtime_float();
         $this->_connecttime = round(($endTime - $startTime), 5);
      }
      else
      {
         return false;
         $this->_connecttime = 0;   
      }
   }
   
   //Return the time (in seconds) it took to connect to the database
   function ConnectTime()
   {
      return $this->_connecttime;
   }
   
   // Store all table name in the currently active database in an array
   function Tables()
   {
      $startTime = $this->microtime_float();
      $tables = @mysql_list_tables( $this->_name );
      if( $tables_count = @mysql_num_rows($tables) )
      {
         for( $i=0; $i<$tables_count; $i++ )
            $this->_listTables[$i] = @mysql_tablename( $tables, $i );
         return $this->_listTables;
      }
      else
      {
         return false;
      }
      $endTime = $this->microtime_float();
      $this->_tablestime = round(($endTime - $startTime), 5);
   }
   
   //return the time it took to fetch the list of tables in the current database
   function TablesTime()
   {
      return $this->_tablestime;
   }

   //Return the number of rows in a given table
   function NumRows( $table = NULL )
   {
      if( $table != NULL )
      {
         $startTime = $this->microtime_float();   
         $result = @mysql_query( "SELECT * FROM ". $table );
         $result_count = @mysql_num_rows( $result );
         if( !$result_count )
            $result_count = 0;
         return $result_count;
         $endTime = $this->microtime_float();
         $this->_numrowstime = round(($endTime - $startTime), 5);   
      }
   }
   
   //Return the time it took to fetch the number of rows in the given table
   function NumRowsTime()
   {
      return $this->_numrowstime;
   }
   
   // Store all field names in a given table in an Array
   function Fields($table = NULL)
   {
      if( $table != NULL )
      {
         $startTime = $this->microtime_float();   
         $fields = @mysql_list_fields( $this->_name, $table );
         if( $this->_fieldscount = @mysql_num_fields($fields) )
         {
            for( $j=0; $j<$this->_fieldscount; $j++ )
            {
               $this->_listFields[$j]['name'] = @mysql_field_name($fields, $j);
               $this->_listFields[$j]['length'] = @mysql_field_len($fields, $j);
               $this->_listFields[$j]['type'] = @mysql_field_type($fields, $j);
            }
            return $this->_listFields;
         }
         else
         {
            return false;
         }
         $endTime = $this->microtime_float();
         $this->_fieldstime = round(($endTime - $startTime), 5);
      }
   }
   
   //Return the time it took to fetch a list of fieldnames
   function FieldsTime()
   {
      return $this->_fieldstime;
   }
   
   //Returns the number of fields in a given table.
   function NumFields( $table = NULL )
   {
      if( $table != NULL )
      {
         $fields = @mysql_list_fields( $this->_name, $table );
         return @mysql_num_fields( $fields );
      }
      else
      {
         return false;   
      }
   }
   
   //Free the stored results and close the currently active databse connection
   function Close()
   {
      if( !@mysql_free_result( $this->DB_result ) )
            unset( $this->DB_result );
      mysql_close( $this->_connect );
   }
}



class Query extends Database
{
   var $_query;
   var $_numrows;
   var $_result;
   var $_ARR_result = Array();
   var $_querytime;

   

   //Pass a query and the function will store the result in a two dimensional array
   function Query( $query = NULL )
   {
      if( $query != NULL )
      {
         $startTime = parent::microtime_float();

         if( !$this->_query = @mysql_query($query) )
         {
            return false;
         }
         else
         {
            $this->_numrows = @mysql_num_rows( $this->_query );
            if( $this->_numrows > 0 )
            {
               while( $this->_result = mysql_fetch_array( $this->_query ) )
                  $this->_ARR_result[] = $this->_result;
            }
            else
            {
               $this->_numrows = 0;
            }
         }

         $endTime = parent::microtime_float();
         $this->_querytime = round(($endTime - $startTime), 5);
      }
      else
      {
         return false;
         $this->_querytime = 0;   
      }
   }

   //Return the result of the query if there was a result
   function Result()
   {
      if( $this->_numrows > 0 )
         return $this->_ARR_result;
      else
         return false;
   }

   //Return the number of rows from a given table. If no table is passed the result count from the table used in the last query passed is returned
   function NumRows( $table = NULL )
   {
      if( $table != NULL )
      {
         $result = @mysql_query( "SELECT * FROM ". $table );
         $result_count = @mysql_num_rows( $result );
         if( $result_count < 1 )
            $result_count = 0;
         return $result_count;   
      }
      else
      {
         return $this->_numrows;
      }
      
   }

   //Return the executiontime of the the last executed query
   function ExecTime()
   {
      return $this->_querytime;
   }
}


De eerste functie binnen de Database class is microtime_float(). Die gebruik ik om te monitoren hoe lang het duurt voordat de verschillende opdrachten binnen de classes zijn uitgevoerd. Nu is het probleem dat ik binnen elk van de twee classes deze functie om de een of andere reden maar in 1 functie kan gebruiken. gebruik ik hem twee keer dan krijg ik geen waarde meer terug. Ik moet de functie op de een of andere manier weer loskoppelen van de functie hem eerder heeft aangeroepen. Maar ik weet dus niet precies hoe ik dat kan doen.

Voorbeeld....

Ik roep binnen 1 instantie van het Database object eerste de volgende functies aan waarbij het gaat om de waarde die de tweede functie teruggeeft...
Code:
function Tables()
   {
      $startTime = $this->microtime_float();
      $tables = @mysql_list_tables( $this->_name );
      if( $tables_count = @mysql_num_rows($tables) )
      {
         for( $i=0; $i<$tables_count; $i++ )
            $this->_listTables[$i] = @mysql_tablename( $tables, $i );
         return $this->_listTables;
      }
      else
      {
         return false;
      }
      $endTime = $this->microtime_float();
      $this->_tablestime = round(($endTime - $startTime), 5);
   }   
   //return the time it took to fetch the list of tables in the current database
   function TablesTime()
   {
      return $this->_tablestime;
   }


De returnwaarde van TablesTime() is nu b.v. 0.00016 (seconden)

Roep ik nu binnen de zelfde object instantie de volgende functies aan (het gaat weer om de returnwaarde van tweede functie) dan krijg ik geen waarde terug van de functie microtime_float().

Code:
// Store all field names in a given table in an Array
   function Fields($table = NULL)
   {
      if( $table != NULL )
      {
         $startTime = $this->microtime_float();   
         $fields = @mysql_list_fields( $this->_name, $table );
         if( $this->_fieldscount = @mysql_num_fields($fields) )
         {
            for( $j=0; $j<$this->_fieldscount; $j++ )
            {
               $this->_listFields[$j]['name'] = @mysql_field_name($fields, $j);
               $this->_listFields[$j]['length'] = @mysql_field_len($fields, $j);
               $this->_listFields[$j]['type'] = @mysql_field_type($fields, $j);
            }
            return $this->_listFields;
         }
         else
         {
            return false;
         }
         $endTime = $this->microtime_float();
         $this->_fieldstime = round(($endTime - $startTime), 5);
      }
   }
   
   //Return the time it took to fetch a list of fieldnames
   function FieldsTime()
   {
      return $this->_fieldstime;
   }


Op de een of andere manier moet ik dus de functie microtime_float() 'unsetten'......?
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Thijs R.
Senior Addict

Bericht Geplaatst: 11 Apr 2007 13:06 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Wel heel gek. En als je de functie eens buiten de class gooit, wat doet ie dan?
_________________
Tony Eveready is known for a scene in which he inserts his testicles into a woman's rectum. He then proceeds to have vaginal intercourse with her whilst groaning, "Nuts in the ass; dick in the pussy!"
Bram
Site Admin

Bericht Geplaatst: 11 Apr 2007 13:18 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Dan werkt de functie gewoon zoals je zou verwachten. Ik denk dat het komt doordat ik de functie toewijs aan het object met
Code:
$this->microtime_float();

Ik zou eigenlijk zoiets moeten kunnen doen als..
Code:
unset( $this->microtime_float() );

...elke keer als ikde functie heb gebruikt. Maar dat pikt hij dus niet. Dat werkt alleen voor variabelen binnen de class, niet voor functies met een returnwaarde.

Wanneer ik de functie aanroep vanuit de Query class, met ....
Code:
parent::microtime_float();

.... dus, dan werkt hij weer wel. Dat lijkt op zich ook wel logisch omdat er dan een nieuwe instantie wordt aangemaakt van die functie binnen het object omdat de caller een child is en niet $self.
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Bram
Site Admin

Bericht Geplaatst: 11 Apr 2007 20:20 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Aaaahggrrr Hamer Ik owrdt er gestoord van. Ik ben dan ook zo iemand die niet kan rusten voordat het opgelost is.

Hoe ik het ook probeer, direct in een variabele wegschrijven (of in een array), of een 'Set' functie gebruiken voor het wegschrijven in de variabele, hij wil maar 1 waarde wegschrijven. Dan houd het op.
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Thijs R.
Senior Addict

Bericht Geplaatst: 11 Apr 2007 20:34 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Hoe werken globals dan eigenlijk binnen een class? Of dat resetten moet weet ik eigenlijk niet zo zeker, ware het niet dat ik het ook niet snap Smiley
_________________
Tony Eveready is known for a scene in which he inserts his testicles into a woman's rectum. He then proceeds to have vaginal intercourse with her whilst groaning, "Nuts in the ass; dick in the pussy!"
Bram
Site Admin

Bericht Geplaatst: 11 Apr 2007 20:58 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Da's nogal een verhaal Tongsmiley

Ik zet het even wat compacter uiteen, misschien dat ik het dan zie...

De voorbeeld class
Code:
class Test
{

     $_timerData = Array();
     
     function foo1()
    {
            $timerStart = microtime();
            //Do stuff
            $timerEnd = microtime();
            $this->_timerData['foo1'] = "foo1 duurde: " .round( ($timerEnd - $timerStart), 5 ). " seconden";
     }

     function foo2()
    {
            $timerStart = microtime();
            //Do other stuff
            $timerEnd = microtime();
            $this->_timerData['foo2'] = "foo2 duurde: " .round( ($timerEnd - $timerStart), 5 ). " seconden";
     }

     function GetTimerData()
    {
            return $this->_timerdata;
     }
}



Het aanmaken van een instantie op opvragen van de timer data...
Code:
$_Test = new Test();
$timer_data = $_Test->GetTimerData;

echo $timer_data['foo1'];
echo $timer_data['foo2'];


Wat ik nu virtueel terugkrijg is
Code:
foo1 duurde: 0.00076 seconden
foo2 duurde:  seconden
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Bram
Site Admin

Bericht Geplaatst: 12 Apr 2007 15:47 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Fuck it.... Ik heb er gewoon een aparte class van gemaakt. Achterafgezien eigenlijk een nog betere oplossing omdat ik de timer nu overal kan gebruiken.

stopwatch.class.php
Code:
class Stopwatch
{
   var $_storedData;
   var $_decimalsDefault = 5;
   var $_decimals;
   var $_seconds;
   
   //Constructor; setting 'type' to 'true' rsults in output in seconds. Otherwise it will return miliseconds.
   //Use the 'decimals' property to set the amount of decimals (obviously)
   function Stopwatch( $decimals = NULL , $type = false)
   {
         if( $type == false )
            $this->_decimals = ($decimals == NULL)?$this->_decimalsDefault:$decimals;
         else
            $this->_desimals = 0;   
         $this->_seconds = $type;
   }
   
   function TimeType()
   {
      if( $this->_seconds == false )
           return array_sum(explode(' ',microtime()));
        else
           return time();
   }
     
   function Start( $caller = NULL )
   {
      if( $caller != NULL )
         $this->_storedData[$caller][0] = $this->TimeType();
   }
   
   function Stop( $caller = NULL )
   {
      if( $caller != NULL )
      {
         $this->_storedData[$caller][1] = $this->TimeType();
         $this->_storedData[$caller][2] = ($this->_storedData[$caller][1] - $this->_storedData[$caller][0]);
      }
   }
   
   function Result( $caller = NULL )
   {
      if( $caller != NULL )
         return round( $this->_storedData[$caller][2], $this->_decimals);
   }
}


test1
Code:
$_Stopwatch_miliseconds = new Stopwatch( 5 );

$_Stopwatch_miliseconds->Start('test');
//Dingen doen die tijd kosten...
$_Stopwatch_miliseconds->Stop('test');

echo "Test met miliseconden duurde: " $_Stopwatch_miliseconds->Result('test'). " seconden";


test2
Code:
$_Stopwatch_seconds = new Stopwatch( true );

$_Stopwatch_seconds->Start('test');
//Dingen doen die tijd kosten...
$_Stopwatch_seconds->Stop('test');

echo "Test met seconden duurde: " $_Stopwatch_seconds->Result('test'). " seconden";



output zou kunnen zijn
Code:
Test met miliseconden duurde: 3.02419 seconden
Test met seconden duurde: 11 seconden
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Thijs R.
Senior Addict

Bericht Geplaatst: 12 Apr 2007 16:15 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Volgens mij ligt het eraan dat je variables decleared die niet global zijn, omdat ze in een class zitten. Als je ze bovenin de class wel decleared met var $variable is er een kans dat ie 't wel doet. Of je decleared ze als private, kan ook denk ik.

En niet alleen dat. Een var binnen een class wordt ook altijd een property, en dient dus te worden aangesproken met $this->var;

Lang geleden allemaal Smiley

Anyhow, je hebt het al opgelost Smiley.
_________________
Tony Eveready is known for a scene in which he inserts his testicles into a woman's rectum. He then proceeds to have vaginal intercourse with her whilst groaning, "Nuts in the ass; dick in the pussy!"
Xurk
Senior Addict

Bericht Geplaatst: 12 Apr 2007 16:15 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Het kan zijn dat ik onzin lul nu [aangezien ik in PHP nog nooit met classes heb gewerkt], maar in Java kun je functions declareren als private, public, protected enzo, kan dat bij PHP ook? Want als dat mogelijk is, dan is dat misschien waarom je de function niet kan aanroepen, omdat deze misschien default of private is.

Als dit helemaal niet van toepassing is, sorry Knipoog
_________________
Hey Jerry Springer? You can keep the guitar... now get the hell off of my stage" - Billie Joe Armstrong, HMH 12-01-2005
Bram
Site Admin

Bericht Geplaatst: 12 Apr 2007 16:36 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

@thijs:
Een variable global maken zorgt er voor dat hij buiten de scope van de class gebruikt kan worden. Dat is verre van wenselijk. Het gebruik van globals wordt overal afgeraden om voor de hand liggende reden.
Ik ga eigenlijk nooit verder dan een statische global ( define('GLOBALNAAM', 'waarde') ).
Het mooie aan een class is o.a. dat het volledig afgeschermd is en je dus in elke class bij wijze van spreken de zelfde variablenamen kunt gebruiken.

In een class zorg je er voor dat de scope van een variable buiten een functie (die gedeclareerd wordt in de 'root' van de class) vanuit een functie aanspreekbaar is d.m.v. $this->varnaam. In principe kun je wanneer de class b.v. 'Foo' heet ook zeggen 'Foo::varnaam'. Het is dus niet nodig om de scope van een variabele permanent te veranderen. Dat is het jezelf onnodig moeilijk maken en meer risico nemen m.b.t. tot veiligheid dan nodig is.

Maar iig bedankt voor het meedenken. Smiley


@Xurk:
Ik werk nu (helaas) met PHP4, omdat alle applicaties die op de server draaien daarvoor geschreven zijn. Dit houd in dat ik geen gebruik kan maken van een boel nieuwe features in PHP. Zoals idd public, privat, protected, static etc. Ook kun je gebruik maken van de duidelijkere functienamen '__construct()' en '__destruct()'. In PHP4 moet je voor de constructor nog de zelfde functienaam gebruiken als de class heeft om PHP te laten begrijpen dat het de constructor is. Wat de code minder overzichtelijk maakt.
In PHP4 zijn variabelen binnen een class standaard privat en functies standaard public. De waarde van een variabele opvragen moet dus altijd middels de returnwaarde van een functie.
Het voordeel is wel dat het zo onder PHP4 en PHP5 werkt.

In PHP5 kun je dus zoiets doen...

Code:
class Foo
{
     public var $_returnValue;

     public function __construct()
     {
           $this->FillReturnValue('Een schaap blaat');
     }

     private function SetReturnValue($string)
     {
           $this->returnValue = split(" ", $string);
     }
}

$OBJ_Foo = new Foo();
for( $i=0; $i<count($OBJ_Foo->_returnValue); $i++ )
     echo $OBJ_Foo->_returnValue[$i]. " ";


Wat vanzelfsprekend "Een schaap blaat" output.
In PHP4 zou dit er zo uit zien...

Code:
class Foo
{
     var $_returnValue;

     function Foo()
     {
          $this->FillReturnValue('Een schaap blaat');
     }

     function SetReturnValue($string)
     {
          $this->returnValue = split(" ", $string);
     }

     function GetReturnValue()
     {
          return $this->_returnValue;
     }
}

$OBJ_Foo = new Foo();
$Rvalue = $OBJ_Foo->GetReturnValue();
for( $i=0; $i<count($Rvalue); $i++ )
     echo $Rvalue[$i]. " ";


Met de zelfde output natuurlijk. Uiteindelijk is PHP4 dus minder veilig en vraagt het om meer code om het zelfde te doen.
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Bram
Site Admin

Bericht Geplaatst: 13 Apr 2007 13:29 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Voor de volledigheid post ik de classes nog maar even zoals ze nu zijn, basic maar bruikbaar

Extended Database Class for PHP4
http://www.stichtingwoonvormen.nl/pzbasis2/classes/database.example.php

Stopwatch Class for PHP4
http://www.stichtingwoonvormen.nl/pzbasis2/classes/stopwatch.example.php
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."
Bram
Site Admin

Bericht Geplaatst: 20 Apr 2007 13:38 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Ik ga het gelijk goed aanpakken. De eerste opzet voor een bibliotheek van classes is gemaakt. Ik heb alweer een hele zooi meer classes geschreven waar nog geen manuals voor zijn. Die zullen via de volgende link te vinden blijven...

http://www.stichtingwoonvormen.nl/oop/classes/
_________________
- "If Murphy's Law can go wrong, it will"
- "If you cannot convince them, confuse them."
- "If at first you don't succeed, redefine success."


Laatst aangepast door Bram op 20 Apr 2007 14:06, in totaal 4 keer bewerkt
Thijs R.
Senior Addict

Bericht Geplaatst: 20 Apr 2007 13:52 Bekijk gebruikers profiel Stuur privé bericht Reageer met quote

Ik voel een Daily Dose aankomen Knipoog (Als ie wat uitgebreider is Smiley)
_________________
Tony Eveready is known for a scene in which he inserts his testicles into a woman's rectum. He then proceeds to have vaginal intercourse with her whilst groaning, "Nuts in the ass; dick in the pussy!"
Plaats nieuw bericht   Plaats reactie
Berichten van afgelopen:   

Ga naar:  
Tijden zijn in GMT + 1 uur
Je mag geen nieuwe onderwerpen plaatsen
Je mag geen reacties plaatsen
Je mag je berichten niet bewerken
Je mag je berichten niet verwijderen
Ja mag niet stemmen in polls