Avatar billede dk-andersson Nybegynder
05. november 2010 - 17:10 Der er 26 kommentarer og
1 løsning

PHP OOP class i class??

Hey

Jeg har gået i gang med at lære OOP, men er løbet ind i lidt problemer. Jeg har lavet en class Mysqldb. Den håndtere alle mine mysql kald.

Nu vil jeg så lave en class Login. Fra den skal jeg så hente nogle funktion fra Mysqldb for at se om brugerne findes.. men kan ikke rigtig få det til at virker..

Så mit spørgsmål er hvordan bruger jeg funktion fra en anden class... eller findes der en anden måde at gøre dette på??
Avatar billede coderdk Praktikant
05. november 2010 - 17:24 #1
Din login-class skal nedarve fra Mysqldb:

class Login extends Mysqldb {
  // osv
}

Så kan du kalde metoderne i Mysqldb fra Login :)
Avatar billede arne_v Ekspert
05. november 2010 - 17:32 #2
Jeg vil snarere antage at Login skal have en instans af Mysqldb.
Avatar billede coderdk Praktikant
05. november 2010 - 18:26 #3
Det var også en mulighed; at lave en instans af Mysqldb i Login-contructoren. Jeg ser dog intet problem i at extende Mysqldb.
Avatar billede arne_v Ekspert
05. november 2010 - 18:32 #4
Jeg ser 2 problemer ved det:
* Login - Mysqldb er ikke en ægte "is a"
* Login bliver meget tightly coupled med MySQL

Send en Mysqldb med over i Login constructor og gem den i et felt er bedre.
Avatar billede dk-andersson Nybegynder
05. november 2010 - 18:46 #5
Hvad er den bedst løsning så.

Skal jeg oprette mysql forbindelse i alle mine nye class?? Kan jeg ikke have min mysql funktioner et sted
Og så benytte dem i alle mine kommende class??

Tænker mere på nemheden ved at man kun et sted skal indskrive data login oplysninger??
Avatar billede majbom Novice
05. november 2010 - 18:55 #6
jeg ville også lave en instans af mysql-klassen i login-constructoren - det virker mest logisk

hvis du skal bruge mysql-funktioner i en ny class opretter du bare en instans af mysql-class'en
Avatar billede dk-andersson Nybegynder
05. november 2010 - 19:24 #7
okay jeg er helt ny inden for programmering i OOP så hvordan lave man en instans??

Her er et uddrag af min class mysqldb:
class Mysqldb {

    function dbconnect($host, $user, $pass, $db){
         
        if($this->hostname_logon == "") {
            $this->hostname_logon = $host;
        }
       
        if($this->database_logon == "") {
            $this->database_logon = $db;
        }
       
        if($this->username_logon == "") {
            $this->username_logon = $user;
        }
       
        if($this->password_logon == "") {
            $this->password_logon = $pass;
        }
       
        // Try to make a connection to the server
        if (!$this->connection = @mysql_connect($this->hostname_logon,$this->username_logon,$this->password_logon,true)){
            $this->mailerror($this->errorCode=mysql_errno(), $this->errorMsg=mysql_error());
            return false;
        }
       
        // Now select the database
        if (!@mysql_select_db($this->database_logon,$this->connection)){
            $this->mailerror($this->errorCode=mysql_errno(), $this->errorMsg=mysql_error());
            @mysql_close($this->connection);
            return false;
        }
           
        return true;
    }
   
    function dbquery($query) {
     
        ++$this->queryCounter;
       
        if(!$this->resultSet = @mysql_query($query,$this->connection)) {
            $this->mailerror($this->errorCode=mysql_errno(), $this->errorMsg=mysql_error());

            return false;
        }
       
        return $this->resultSet;
    }

}

så hvis jeg skulle bruge noget fra denne i min anden class login hvordan gør jeg så det??
Avatar billede intenz Novice
06. november 2010 - 11:29 #8
F.eks. sådan:

class Login {
  private $db;

  function __construct() {
    $this->db = new Mysqldb();
  }

  function checkLogin($username, $password) {
    $result = $this->db->dbquery("SELECT * FROM users WHERE username='".$username."' && password='".$password."'");
  }
}
Avatar billede dk-andersson Nybegynder
07. november 2010 - 00:05 #9
mange tak for hjælpen... hvem vil have point???
Avatar billede arne_v Ekspert
07. november 2010 - 00:47 #10
Jeg ville lave:
- en abstrakt klasse Anydb
- en konkret klasse Mysqldb som arver fra denne
- en factory klasse som producerer Anydb'er
- en constructor i Login med et argument (som så skal være en Anydb)
- et kald af den cosntructor med en Anydb fra factory klassen som argument

Men måske er det en lille smule overkill hvis du først er igang med at lære OOP.

Men man hardcoder ikke en database vendor specific klasse i noget business logic funktionalitet.
Avatar billede majbom Novice
07. november 2010 - 16:51 #11
springer over...
Avatar billede danco Nybegynder
08. november 2010 - 11:14 #12
Jeg tænker at det ville være smart at bruge et Singleton pattern her eftersom det er database kontakt.
Det vil i betyde at du kun kan oprette et objekt af din handler.
Jeg smider her et udsnit af min egen Singleton Mysql Connector.

Det er så meningen at du kalder på klassens getInstance() som returnerer et et objekt af klassen. Derefter kan du udbygge funktioner på klassen som du kan kalde på det objekt du får tilbage.

$instance = dbHandler::getInstance();
$instance->someFunction();



class dbHandler {
        private $dbuser = '';
        private $dbPass = '';
        private $dbHost = '';
        private $dbName = '';
    private static $Instance;

    private function __construct()     {
        mysql_connect($this->dbHost, $this->dbuser, $this->dbPass);
                mysql_select_db($this->dbName) or die(throw new MysqlException());
        }

        /**
        * Returns an object of the database connection
        * @return Mysql Connection object
        */
    public static function getInstance()    {
        if (!self::$Instance)
        {
            self::$Instance = new dbHandler();
        }
        return self::$Instance;
    }
}
Avatar billede arne_v Ekspert
08. november 2010 - 13:12 #13
Aldrig singleton for database klasse som indeholder en database connection.

Den dag du har brug for to database forbindelser er du toast.

Singleton er glimrende for en factory som producerer database klasse instanser.
Avatar billede danco Nybegynder
08. november 2010 - 16:46 #14
Arne, jeg har svært ved at forstå præcis hvad du mener. Jeg finder det oplagt at bruge Singleton i sådan en situation.
At gå over og bruge en factory patttern synes jeg er overkill set i lyset af at kun er behov for MySQL her, skulle der også være mulighed for oracle eller andre databaser kunne jeg forstå hvor du ville hen.

Og egentlig forstår jeg heller ikke hvad du mener med
"Den dag du har brug for to database forbindelser er du toast"

Men nok om det, det må være op til trådstarter at afgøre hvilken løsning der passer bedst.
Avatar billede arne_v Ekspert
08. november 2010 - 17:20 #15
Hvis man kan se ind i fremtiden og ved at man aldrig vil skifte database, så er der ikke nogen grund til at forberede koden på andre databaser. Men det rækker mine evner ikke til.

Hvis du har din database connection i en singleton, saa har du kun mulighed for 1 database connection. Hvis du har brug for 2, saa har du et problem.

Singleton med database connection er et meget kendt anti-pattern. P.g.a. PHP's execution model er det ikke så slemt som i ASP.NET og Java EE. Men det er stadig skidt.

Det er formentligt ikke saa relevant for spoerger. Men der kan jo ogsaa vaere andre brugere.
Avatar billede intenz Novice
08. november 2010 - 20:39 #16
Arne_v:
Jeg kan godt se det problem du nævner, men finder det alligevel også brugbart at bruge en singleton for at sikre, at der altid kun findes én instans af det givne forbindelse.

Hvordan ville du sikre det uden en singleton? Kontrollere det i factory klassen eller hvordan?

Det er ren nysgerrighed. Jeg har heller aldrig været ude for, at skulle have en ny forbindelse.
Avatar billede arne_v Ekspert
08. november 2010 - 20:56 #17
Hvad formål er der ved at sikre at der kun er en connection?

Du skal bruge to connections hvis:
- du skal lave en ny query inden du er færdig med at hente alle data fra den første query
- du skal lave en opdatering udenfor transaktion mens du har en transaktion i gang på den oprindelige query
- bruger to forskellige databaser
Avatar billede intenz Novice
08. november 2010 - 21:35 #18
Jeg tænker på, man vil vel ikke køre f.eks. en mysql_connect() hver gang man skal kalde databasen.

Man er vel, typisk, kun interesseret i at have én forbindelse til databasen, for at forhindre unødigt overhead.

Hvad ville være den logiske måde, at sørge for det på, hvis ikke med en singleton?
Man kunne selvfølgelig lave det i et registry eller kode noget i dens 'parent', det virker bare ikke som den nemme løsning.
Avatar billede arne_v Ekspert
08. november 2010 - 21:48 #19
Der er ikke noget som forhindrer en i at constructe sin connection wrapper øverst i siden, sende den med over i diverse funktions/metode kald og close den til sidst.

Når det ikke er en singleton har man muligheden af at lave en instans mere hvis man vil.

Hvis det er vigtigere at minimere antallet af database connections fremfor latency på side generering, så kan man også vælge at betale prisen for flere mysql_connect og mysql_close par.

Og så er der the dark horse muligheden nemlig at skifte fra mysql_connect til mysql_pconnect.
Avatar billede intenz Novice
08. november 2010 - 22:13 #20
Ah ja, mysql_pconnect, den brugte jeg for mange år siden efterhånden, kører stadig fint :)

Men jeg kan godt se logikken i dit svar, tak :)
Avatar billede arne_v Ekspert
08. november 2010 - 22:26 #21
mysql_pconnect er en undervurderet mulighed i PHP.

Der er jo nok en grund til at 99% af alle ASP.NET og Java EE løsninger bruger en tilsvarende teknik.

Indrømmet p.g.a. den måde eller måske mere præcist udtrykt de mange forskellige måder PHP kan køres på er der masser af faldgruber. Men den slags kan jo løses.
Avatar billede arne_v Ekspert
27. december 2010 - 00:41 #22
Tid at få afsluttet her?
Avatar billede dk-andersson Nybegynder
13. januar 2011 - 08:00 #23
Avatar billede arne_v Ekspert
13. januar 2011 - 13:22 #24
Er det ikke 3. og 2. udgave af samme bog?

Man maa antage at 3. udgave er bedre end 2. udgave!
Avatar billede dk-andersson Nybegynder
13. januar 2011 - 13:36 #25
takker for svaret... vil du have point??
Avatar billede arne_v Ekspert
13. januar 2011 - 15:18 #26
gerne

men jeg er jo ikke den eneste som har vaeret med i traaden
Avatar billede dk-andersson Nybegynder
13. januar 2011 - 15:21 #27
okay hvis der er andre som vil have del i point... så skal i ligge et svar i dag inden kl. 24 TAk
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester