[PHP / OOP] function uit andere class oproepen

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

Onderwerpen


  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Na een jaar of drie niet meer geprogrammeerd te hebben, ben ik maar weer eens begonnen in PHP.

Ik ben op dit moment een script aan het schrijven (d'uh) en maak gebruik van meerdere bestanden waarin een class zit met haar eigen functies. Ik heb op dit moment de bestanden sql.inc.php en login.inc.php, waarin de classes SQL en USER staan. Beide bestanden worden met behulp van require_once geinclude in index.php en ik zorg met het new-command dat ik de functions kan gebruiken.

Echter kom ik nu een op een klein probleempje waar ik niet uit kan komen. Ik moet namelijk in het bestand login.inc.php een functie aanspreken uit sql.inc.php (namelijk activelink()), maar krijg dit met geen mogelijkheid aan de praat. De melding kunnen jullie denk ik wel raden:
Fatal error: Call to a member function on a non-object in /home/alternativity/public_html/incs/login.inc.php on line 33. Op line 33 probeer ik dus de activelink aan te roepen.

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
Het precieze stukje code op die regel(s) zou handig zijn natuurlijk...

Maar ik denk dat je of een methode (functie) van een het object aanroept in plaats van de instance van het object.
PHP:
1
2
3
4
USER->activelink();
i.p.v.
$eenVariabele = new USER();
$eenVariabele->activelink();


Of dat je eigenlijk een static methode (functie) wil aanroepen zonder dat je een new object hebt gemaakt. (Moet het wel een static functie zijn natuurlijk)
PHP:
1
USER::activelink();


Zie ook http://nl3.php.net/manual/en/language.oop5.php

[ Voor 5% gewijzigd door keisersose op 20-09-2007 23:35 ]


Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Het is overigens SQL waarin activelink(); zit, anders had ik het probleem niet gehad :)

Ik wil dus in class USER iets oproepen uit SQL. Maar op beide manieren zoals jij ze aangeeft werkt het niet.

Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 20-09 23:15

NetForce1

(inspiratie == 0) -> true

Kun je misschien wat code laten zien dan? Want zo komen we ook niet echt verder.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
NetForce1 schreef op vrijdag 21 september 2007 @ 09:56:
Kun je misschien wat code laten zien dan? Want zo komen we ook niet echt verder.
Okee dan, maar ik denk echt niet dat het veel zal helpen. De vraag blijft duidelijk. Verder niet letten op andere fouten in de scripting, graag focus op het probleem zelf.

sql.inc.php
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
32
33
34
35
36
<?PHP
class SQL 
{
    var $settings = array(  "sql_host"      => "",
                            "sql_user"      => "",
                            "sql_passwd"    => "",
                            "database"      => ""
                            );
    
    function connect()
    {
        $this->link = mysql_connect(    $this->settings['sql_host'], 
                                        $this->settings['sql_user'], 
                                        $this->settings['sql_passwd']
                                    );
        $this->db = mysql_select_db($this->settings['database'], $this->activelink());
        echo("Connecting to database was succesful.");
    }
    
    function activelink()
    {
        if (!$this->link)
        {
            echo("There was no connection active to the database, creating one now.");

            SQL::connect();
        }
        return $this->link;
    }
    
    function close()
    {
        mysql_close($this->link);
    }
}
?>


login.inc.php
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
class USER
{
// Original code by SuperdeBoer@MyReact Support Forum
    function checklogin()
    {
        // Check if cookie contains md5-like content
        $this->read_cookie = preg_match ( '/^[a-f0-9]{32}$/i', $_COOKIE['ReactID']);
    
        if ($this->read_cookie)
        {    
            // Get UserID when ReactID is in F_Sessions    and when user is not banned
            // You might want to extend this query by checking if a user is member
            // of a certain group (in F_Groupusers) or something... it's up to you
            $this->query = "
                     SELECT
                        F_Sessions.UserID,
                        F_Sessions.IP,
                        F_Users.Nickname
                    FROM
                        F_Sessions,
                        F_Users
                    WHERE
                        F_Sessions.SessionID = '" . $_COOKIE['ReactID'] . "'
                    AND
                        F_Users.UserID = F_Sessions.UserID
                    AND
                        F_Users.Banned = 0
                    ";
                
 [b]           $this->result = mysql_query($this->query, $sql->activelink());[/b]
            while ($row = mysql_fetch_array($this->result))
            {
                $login['UserID'] = $row['UserID'];
                $login['IP'] = $row['IP'];
                $login['Nickname'] = $row['Nickname'];
             }

        // Check whether remote address matches with IP the session is bound to
        // If not, session may be hijacked, therefore it won't login then

            if ( !empty($login['IP']) && $login['IP'] != $_SERVER['REMOTE_ADDR'] )
            {
                return;        
            } 
        
        
            return $login;
        }
        else
        {
        return;
        }
    }
}
?>


index.php
code:
1
2
3
4
5
6
7
8
9
<?PHP
require_once("incs/sql.inc.php");
require_once("incs/login.inc.php");

$sql = new SQL();
$user = new USER();

$user->checklogin();
?>

Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Je pakt nu de variabele in je global scope (namelijk van de functie checklogin()). Je moet $sql als global definieren en dan kan je er wel naar refereren. Zie ook http://php.net/variables%20scope

[ Voor 3% gewijzigd door mithras op 21-09-2007 10:19 ]


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
En naast de scope document is ook de OOP document heel helder, dus ik raad je aan eerst http://nl.php.net/manual/en/language.oop.php door te nemen.

{signature}


Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Ik zag daarnet dat ik vanwege MyReact dus PHP4 gebruik, maakt dat heel veel uit met de code? Upgrade naar PHP5 staat overigens wel op de planning, maar nog geen tijd voor gehad...

Overigens heb ik dat OOP-document wel al vluchtig doorgenomen.

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
in PHP5 geeft hij de melding: Fatal error: Call to a member function activelink() on a non-object in /home/alternativity/public_html/incs/login.inc.php on line 33

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

DanielB schreef op vrijdag 21 september 2007 @ 10:24:
Ik zag daarnet dat ik vanwege MyReact dus PHP4 gebruik, maakt dat heel veel uit met de code? Upgrade naar PHP5 staat overigens wel op de planning, maar nog geen tijd voor gehad...

Overigens heb ik dat OOP-document wel al vluchtig doorgenomen.
Dan adviseer ik, om eerst eens goed de OOP documentatie door te nemen. En de documentatie mbt Variable Scope. Als je die twee zaken goed bestudeert dan los je dit probleem snel op.

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Je roept SQL::connect() aan als static function, waarna je daarna in je connect functie refereert aan $this. Dat is behoorlijk vreemd te noemen. Zou kunnen werken, maar dat is meer random toeval dan by design. Zet je active link opzetten gewoon in de constructor van je SQL class, veel netter.

Verder, zoals hierboven al staat, $sql is niet bekend in de scope van je USER class.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
DanielB schreef op vrijdag 21 september 2007 @ 10:24:
Overigens heb ik dat OOP-document wel al vluchtig doorgenomen.
Je hebt eerlijk gezegd meerdere basic oop vragen, dus kan je maar beter de docs eerst minder vluchtig doornemen. ;)

{signature}


Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Grijze Vos schreef op vrijdag 21 september 2007 @ 10:54:
Je roept SQL::connect() aan als static function, waarna je daarna in je connect functie refereert aan $this. Dat is behoorlijk vreemd te noemen. Zou kunnen werken, maar dat is meer random toeval dan by design. Zet je active link opzetten gewoon in de constructor van je SQL class, veel netter.

Verder, zoals hierboven al staat, $sql is niet bekend in de scope van je USER class.
De bedoeling van activelink(); is het checken of de $this->link dus bestaat en zo nee, dat hij gaat connecten. Als ik 'm in de constructor zet, wordt hij alleen bij het laden uitgevoerd en wanneer tussendoor om welke reden dan ook de verbinding wegvalt zal hij niet opnieuw connecten...

Acties:
  • 0 Henk 'm!

Verwijderd

DanielB schreef op vrijdag 21 september 2007 @ 16:00:
[...]


De bedoeling van activelink(); is het checken of de $this->link dus bestaat en zo nee, dat hij gaat connecten. Als ik 'm in de constructor zet, wordt hij alleen bij het laden uitgevoerd en wanneer tussendoor om welke reden dan ook de verbinding wegvalt zal hij niet opnieuw connecten...
Ten eerste dat je huidige code dat ook niet. Je kijkt alleen of the variable $this->link een geldige pointer naar de database bevat. Deze pointer blijft binnen de uitvoering van de pagina gewoon bestaan mocht de verbinding wegvallen.

Ten tweede is de kans dat de verbinding wegvalt (en daarna weer te herstellen) is binnen die 3 milliseconden van uitvoering heel erg klein.

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Verwijderd schreef op vrijdag 21 september 2007 @ 16:08:
[...]


Ten eerste dat je huidige code dat ook niet. Je kijkt alleen of the variable $this->link een geldige pointer naar de database bevat. Deze pointer blijft binnen de uitvoering van de pagina gewoon bestaan mocht de verbinding wegvallen.

Ten tweede is de kans dat de verbinding wegvalt (en daarna weer te herstellen) is binnen die 3 milliseconden van uitvoering heel erg klein.
Als de pointer dus niet bestaat of niet in werking is, zal hij dus connecten. Gisteren kreeg ik een flood nadat ik wat vergat, dus hij probeert toch echt wel bij geen verbinding opnieuw te verbinden. Correct me again if I'm wrong, maar dat heb ik dus echt waargenomen.

Misschien handig als iemand ff duidelijk voorbeeld kan geven van de begrippen die gebruikt worden in OOP? Ik kan er namelijk vanuit de manual echt geen hout van maken, wat ik ook lees.

[ Voor 10% gewijzigd door DanielB op 21-09-2007 16:30 ]


Acties:
  • 0 Henk 'm!

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
DanielB schreef op vrijdag 21 september 2007 @ 16:18:
Misschien handig als iemand ff duidelijk voorbeeld kan geven van de begrippen die gebruikt worden in OOP? Ik kan er namelijk vanuit de manual echt geen hout van maken, wat ik ook lees.
Op http://www.mastercode.nl/artikel/57/ staat een stuk over OOP in PHP in het nederlands, misschien dat je daar wat meer helderheid uit kan halen ;)

Er staat daar overigens niets in over static, maar heb je niet nodig op de manier waarop je het wil laten werken.


Let wel dat er een aantal verschillen zijn in OOP tussen versie 4 en 5 van php. (zie http://www.webmaster-talk...etween-php4-and-php5.html)

En op http://nl.php.net/manual/en/language.oop.php staat de php4 versie van de al eerder geposte oop docs van php5.

Anders nog op http://www.phphulp.nl/php/tutorials/8/302/599/

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Mastercode was ik al mee bekend, maar wel erg bedankt! Ik ga er morgen nog even een keer goed naar kijken. Maar wanneer ik een function met public definieer, dan geeft hij een foutmelding...

Acties:
  • 0 Henk 'm!

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
DanielB schreef op vrijdag 21 september 2007 @ 17:04:
Maar wanneer ik een function met public definieer, dan geeft hij een foutmelding...
Dat kan pas vanaf PHP5 (helaas)...

Ik raad je toch aan om te upgraden naar PHP5 als je serieus/netjes/uitgebreid/goed met OOP aan de slag gaat. (Mits dat mogelijk in bij je host en werkt in combinatie met bijvoorbeeld je MyReact)

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
keisersose schreef op vrijdag 21 september 2007 @ 17:10:
[...]

Dat kan pas vanaf PHP5 (helaas)...

Ik raad je toch aan om te upgraden naar PHP5 als je serieus/netjes/uitgebreid/goed met OOP aan de slag gaat. (Mits dat mogelijk in bij je host en werkt in combinatie met bijvoorbeeld je MyReact)
Is al gebeurd inmiddels ;). Ik ben zelf mijn eigen provider wat betreft hosting (geen homeserver ofzo), dus heb dat vanochtend gelijk gedaan.

Acties:
  • 0 Henk 'm!

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
Wat is de foutmelding die je krijgt als je de functie defineert als public? (In PHP5)

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Ik heb nu geen foutmelding meer, het lijk erop dat ik nu zonder problemen door het definen van public functions en het extenden van de classes (USER extends SQL) het wel aan de praat heb gekregen. Eerst wat laten outputten, dan volgt er update :P

Update:
Ik heb nu activelink() via SQL:: aanroepen, wat mogelijk is door de extend. Hij verbindt nu met de database en kan mijn username eruit halen. Toch heb ik zelf het gevoel nog niet helemaal goed te zitten... De source is nu alsvolgt:

sql.inc.php / class SQL
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
32
33
34
35
36
37
38
39
40
41
42
<?PHP
class SQL 
{
    public $settings = array(   "sql_host"      => "",
                            "sql_user"      => "",
                            "sql_passwd"    => "",
                            "database"      => ""
                            );
    
    public function connect()
    {
        $this->link = mysql_connect(    $this->settings['sql_host'], 
                                        $this->settings['sql_user'], 
                                        $this->settings['sql_passwd'])
                                        or die ('Could not create connection');

        $this->db = mysql_select_db($this->settings['database'], $this->activelink()) or die(bla);
        echo("Connecting to server was succesful.");
    }
    
    public function activelink()
    {
        if (!$this->link)
        {
            echo("There was no connection active to the database, creating one now.");

            $this->connect();
        }
        return $this->link;
    }
    
    public function close()
    {
        mysql_close($this->link);
    }
    
    public function query($query)
    {
        return mysql_query($query, $this->activelink());
    }
}
?>



login.inc.php / class USER
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Original code by SuperdeBoer (@ MyReact Support Forums)
class USER extends SQL
{
    function checklogin()
    {
        // Check if cookie contains md5-like content
        $read_cookie = preg_match ( '/^[a-f0-9]{32}$/i', $_COOKIE['ReactID']);
    
        if ($read_cookie)
        {    
            // Get UserID when ReactID is in F_Sessions    and when user is not banned
            // You might want to extend this query by checking if a user is member
            // of a certain group (in F_Groupusers) or something... it's up to you
            $query = "
                     SELECT
                        F_Sessions.UserID,
                        F_Sessions.IP,
                        F_Users.Nickname
                    FROM
                        F_Sessions,
                        F_Users
                    WHERE
                        F_Sessions.SessionID = '" . $_COOKIE['ReactID'] . "'
                    AND
                        F_Users.UserID = F_Sessions.UserID
                    AND
                        F_Users.Banned = 0
                    ";
                
            $this->result = mysql_query($query, SQL::activelink());
            while ($row = mysql_fetch_array($this->result))
            {
                $login['UserID'] = $row['UserID'];
                $login['IP'] = $row['IP'];
                $login['Nickname'] = $row['Nickname'];
                echo $login['Nickname'];
             }

        // Check whether remote address matches with IP the session is bound to
        // If not, session may be hijacked, therefore it won't login then

            if ( !empty($login['IP']) && $login['IP'] != $_SERVER['REMOTE_ADDR'] )
            {
                return;        
            } 
        
        
            return $login;
        }
        else
        {
        return;
        }
    }
}


index.php
code:
1
2
3
4
5
6
7
8
9
10
11
12
<?PHP
require_once("incs/sql.inc.php");
require_once("incs/login.inc.php");

$sql = new SQL;
$user = new USER;

//while ($row = mysql_fetch_array($sql->query("SELECT * FROM F_Users")))
$user->checklogin();

echo $user->login['UserID'];
?>

[ Voor 86% gewijzigd door DanielB op 22-09-2007 15:36 ]


  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik heb het idee dat je nog steeds niet het principe van OOP en de implementatie ervan in php doorhebt.
DanielB schreef op zaterdag 22 september 2007 @ 13:20:Update:
Ik heb nu activelink() via SQL:: aanroepen, wat mogelijk is door de extend. Hij verbindt nu met de database en kan mijn username eruit halen. Toch heb ik zelf het gevoel nog niet helemaal goed te zitten.
Door te extenden ben je een andere klasse aan het overerven. Je hebt een klasse dier, en een klasse paard. Je kan dan de klasse paard extenden met de klasse dier, omdat een paard een "specialisatie" van een dier is.
Je kan dan bijvoorbeeld een functie binnen de klasse dier zoek_ouders() ook binnen de klasse dier gewoon aanspreken met $this->zoek_ouders().

Wat jij nu doet met SQL:: is de public (static) function aanroepen zonder daarvoor de klasse SQL te instantieren. Leer nu gewoon wat over scopes en OOP, want het is nu gewoon een rommeltje met je global scopes, local scopes (binnen klasse én binnen functies) en het instantieren van de klasse SQL die je vervolgens niet gebruikt maar direct aanroept.

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
Dat het werkt is natuurlijk mooi, maar zoalsje zelf ook zegt, het zit nog niet helemaal goed.

Ik moet ook zeggen dat het extenden in dit geval niet is wat je wil. (Zoals mithras ook zei, USER is niet een soort van SQL, dus het zou geen extend situatie moeten zijn)

Dat het werkt komt omdat de class USER nu ook de variabele $link kent, en zelf de functie activelink heeft. Dus de class USER is nu ook de class SQL. Als je dit door trekt zou je elke class die gebruik moet maken van de database de class SQL moeten extenden, dat is onzinnig.

Nog even een vraag tussendoor. Klopt het dat je er van uit gaat dat de gebruiker al is ingelogd in MyReact? Als het antwoord nee is, dan klopt de checkuser() functie niet echt...

Om toch maar een stukje code te plaatsen voor je die in het geval van één enkele database in het project veel makkelijker werkt (Ook als is dat niet helemaal de bedoeling aangezien je daar niet echt wat van zal leren als je niet snapt hoe het werkt :S)
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
53
54
55
// Example of SQL class in an all static form (Did not make it PHP4 compatible)
class SQL {
    // The settings
    private static $settings = array(
        "host" => "localhost",
        "user" => "testuser",
        "password" => "testpassword",
        "database" => "testdb"
    );
    
    // The link/resource identifier
    private static $link = false;
    
    // Connect
    private static function connect() {
        // Try to connect to the mysql server
        self::$link = @mysql_connect(
            self::$settings['host'],
            self::$settings['user'],
            self::$settings['password']
        );
        
        // Trigger error if connect failed 
        if (self::$link === false) {
            //echo mysql_error(); // DEBUG ONLY
            self::$link = false;
            trigger_error('Could not connect to database server!', E_USER_ERROR);
            // retrun false; // As alternative to trigger_error
        }
        
        // Select database and trigger error if it fails
        if (@mysql_select_db(self::$settings['database'], self::$link) === false) {
            //echo mysql_error(); // DEBUG ONLY
            self::$link = false;
            trigger_error('Could not select database!', E_USER_ERROR);
            // retrun false; // As alternative to trigger_error
        }
        
        return true;
    }
    
    // Get the mysql link (returns false if not connected)
    public static function getLink()
    {
        if (self::$link === false) {
            self::connect();
        }
        return self::$link;
    }

    // Execute a query
    public static function query($query) {
        return mysql_query($query, self::getLink());
    }
}


Daarna kan moet je de extend bij USER weghalen, en de $sql = new SQL(); in index.php moet ook weg.

In de class USER:
PHP:
1
2
3
4
Vervang:
$this->result = mysql_query($query, SQL::activelink());
Door:
$this->result = SQL::query($query);


Ik raad wel aan om om eerst eens wat tutorials over OPP en objecten in PHP te gaan volgen, om de essentiele aspecten ervan onder de knie te krijgen!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
De function checklogin(); roept alleen maar wat gegevens op die dan terecht komen in $login. Als er dus geen $login['UserID'] is, worden bepaalde dingen ook niet op de pagina weergegeven, dat was buiten het OOP-verhaal ook.

Zoals mithras al zei, ik krijg het gewoon niet door. Ik lees echt wel, maar het werken op deze manier is echt gewoon nieuw voor mij.

[ Voor 23% gewijzigd door DanielB op 22-09-2007 15:40 ]


Verwijderd

Snap je het verschil tussen een method en een static method? En tussen een property en een static property? En tussen een class en een object?

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Verwijderd schreef op zaterdag 22 september 2007 @ 15:40:
Snap je het verschil tussen een method en een static method? En tussen een property en een static property? En tussen een class en een object?
een static method kan niet via een instanced object aangeroepen worden en een static property kan niet gebruik worden met behulp van de ->. Ook heb je dan geen $this-> dus meer, omdat static methods op te roepen zijn zonder instance.

Een class is het skelet van je object. Bij bijvoorbeeld een vervoersmiddel staat er het aantal willen in. Dus als mijn class vervoersmiddel is, kan ik er een object fiets van maken... En dan aangeven dat hij twee wielen heeft... En dat laten echo'en... ($fiets->aantalwielen)...

Van het laatste ben ik niet helemaal zeker, maar dat klopt volgensmij wel aardig...

Verwijderd

Kijk dan eens in deze post van jou naar de code van sql.inc.php op regel 12 en 23, en login.inc.php regel 30, en dan naar wat je iets eerder zegt:
Ik heb nu activelink() via SQL:: aanroepen, wat mogelijk is door de extend.
Of nog eerder, in deze post naar die sql.inc.php en regel 12 en 26.

Kortom, het lijkt er nu met die laatste reactie op dat je er wel iets van doorhebt, maar in de praktijk is dat nog niet echt helder.

Sowieso, als je dan een SQL class hebt, waarom moet een class als USER dan op de hoogte zijn van de "active link" van die SQL class? Schrijf een method voor die SQL class die gewoon alle rows van een query in een array teruggeeft. Dan hoef je ook niet de rest van je classes te vervuilen met mysql_query en mysql_fetch_* aanroepen.

De vraag is dus vooral of je de object oriented mogelijkheden wel goed weet te gebruiken. Op dit moment vind ik dat je de boel alleen maar vertroebelt.

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Verwijderd schreef op zaterdag 22 september 2007 @ 18:20:
Kortom, het lijkt er nu met die laatste reactie op dat je er wel iets van doorhebt, maar in de praktijk is dat nog niet echt helder.
Wat klopt er dan niet in het verhaaltje wat ik vertelde? (in het kader van fouten leren)
Sowieso, als je dan een SQL class hebt, waarom moet een class als USER dan op de hoogte zijn van de "active link" van die SQL class? Schrijf een method voor die SQL class die gewoon alle rows van een query in een array teruggeeft. Dan hoef je ook niet de rest van je classes te vervuilen met mysql_query en mysql_fetch_* aanroepen.
Dat had ik in principe al met SQL::query, alleen heb ik die nog niet gebruikt in class USER.
De vraag is dus vooral of je de object oriented mogelijkheden wel goed weet te gebruiken. Op dit moment vind ik dat je de boel alleen maar vertroebelt.
Vertroebelen?

Acties:
  • 0 Henk 'm!

Verwijderd

Een abstract class is ook nog een optie!

En waarom trigger_error(); ? Daar hebben we hele mooie throw new Exception(); toch voor...

Acties:
  • 0 Henk 'm!

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
Verwijderd schreef op zaterdag 22 september 2007 @ 18:20:
Kortom, het lijkt er nu met die laatste reactie op dat je er wel iets van doorhebt, maar in de praktijk is dat nog niet echt helder.
Het lijkt er inderdaad op dat de stap van theorie naar parktijk wat lastig is...
Verwijderd schreef op zondag 23 september 2007 @ 05:26:
Een abstract class is ook nog een optie!

En waarom trigger_error(); ? Daar hebben we hele mooie throw new Exception(); toch voor...
Abstract is hier niet echt nodig lijkt mij zo. (Maar inderdaad, dat bestaat ook nog)
Een Exception zou ik normaal ook doen, maar met een stukje example code, ach dan blijft er tenminste ruimte voor verbetering ;)

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
keisersose schreef op zondag 23 september 2007 @ 13:21:
[...], maar met een stukje example code, ach dan blijft er tenminste ruimte voor verbetering ;)
Een klein vraagje: als ik de hoe/en wat van het stukje script kan omschrijven, zou ik het dan (deels) mogen gebruiken? Wat je post is weliswaar 'voor iedereen beschikbaar', maar ik wil geen code gebruiken die ik ook niet snap. Ik denk het zo langzamerhand wel te gaan snappen, al ben ik voor mijn gevoel er nog steeds niet (wat betreft OOP).

Acties:
  • 0 Henk 'm!

  • Jimbolino
  • Registratie: Januari 2001
  • Laatst online: 20-09 08:54

Jimbolino

troep.com

Als je een class wilt maken waar maar één function in zit, moet je je afvragen of het wel nuttig is om er een class van te maken.
Hetzelfde geldt voor een function van één regel.

Anderzijds is het zo dat als een class te groot wordt, het verstandig is deze op te splitsen in logische subclasses.

The two basic principles of Windows system administration:
For minor problems, reboot
For major problems, reinstall


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Jimbolino schreef op dinsdag 25 september 2007 @ 02:27:
Hetzelfde geldt voor een function van één regel.
Getters en setters zijn anders vaak een eenregelige functie ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Jimbolino schreef op dinsdag 25 september 2007 @ 02:27:
Als je een class wilt maken waar maar één function in zit, moet je je afvragen of het wel nuttig is om er een class van te maken.
Hetzelfde geldt voor een function van één regel.

Anderzijds is het zo dat als een class te groot wordt, het verstandig is deze op te splitsen in logische subclasses.
Eigenlijk incorrect op alle drie de uitspraken.
- Een class bestaat niet bij gratie van een aantal functies maar door de eigenschap. Het aantal functies binnen een class doet er dus niet toe.
- Het aantal regels maakt natuurlijk helemaal niets uit. Denk bijvoorbeeld aan het belangrijke OO-principe data-hiding.
- Wat is te groot? Omvang rechtvaardigt geen splitsing, type functionaliteit/eigenschappen doen dat.

Acties:
  • 0 Henk 'm!

  • dwa
  • Registratie: Augustus 2002
  • Niet online

dwa

http://www.phpit.net/article/using-globals-php
hier staat een artikel over het gebruik van het registry pattern in php. Als ik je probleem goed begrijp zou dat een oplossing kunnen zijn voor je probleem.

  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
DanielB schreef op dinsdag 25 september 2007 @ 01:58:
Een klein vraagje: als ik de hoe/en wat van het stukje script kan omschrijven, zou ik het dan (deels) mogen gebruiken?
Van mij mag iedereen het door mij geposte stukje code gebruiken. (Maar inderdaad, het is wel prettig om de werking ervan te snappen ;))

@Jimbolino: Ben het volledig eens met de reactie van mark platvoet.

@dwa: Dat zijn inderdaad interessante dingen. Ook al is dat (deels) weer een stapje verder dan dit. (Ik gebruik zelf ook een aantal van die technieken, ook in het door mij geposte stukje code)

@DanielB: Lukt het verder een beetje met de desbetreffende code?

  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 08-07 14:27
globals moet je ten alle tijden zien te vermijden in OOP..

Misschien moet je de database class opzetten als singleton

Dan kun je hem overal waar je hem nodig hebt gewoon opvragen.

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


Verwijderd

OxiMoron schreef op woensdag 26 september 2007 @ 08:45:
globals moet je ten alle tijden zien te vermijden in OOP..
Daar ben ik het niet helemaal mee eens, zeker omdat de OO ondersteuning van PHP niet geweldig is. Ik vind het gebruik van $GLOBALS['var'] niet zo verkeerd, omdat daaruit exact blijkt wat je aan het doen bent. Een singleton gebruiken alleen maar omdat je geen globals moet gebruiken biedt in PHP geen meerwaarde boven het gebruik van $GLOBALS.

PHP:
1
2
3
function bla () {
   global $db;
}

Dit is dan weer wél een beetje vragen om problemen.

[ Voor 9% gewijzigd door Verwijderd op 26-09-2007 09:30 ]


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Verwijderd schreef op woensdag 26 september 2007 @ 09:29:
[...]

Daar ben ik het niet helemaal mee eens, zeker omdat de OO ondersteuning van PHP niet geweldig is. Ik vind het gebruik van $GLOBALS['var'] niet zo verkeerd, omdat daaruit exact blijkt wat je aan het doen bent.
Het probleem met zowel globals als Singletons is dat je aan de buitenkant van de class de dependency niet kunt zien waardoor je dus coupling problemen krijgt. En of je die globals met $GLOBALS of met global $var aanspreekt is compleet irrelevant*, op functieniveau is het niet zo lastig om te zien wat er gebeurd. Als je echter een overzicht wilt hebben van je complete systeem en de flow van gegevens heb je wél ineens een probleem. De problemen zijn eenvoudig op te lossen door het gebruik van een Registry/Locator/Dependency Injection.

* Het verschil in gedrag tussen global en $GLOBALS daargelaten.

[ Voor 3% gewijzigd door PrisonerOfPain op 26-09-2007 09:51 ]


  • koli-man
  • Registratie: Januari 2003
  • Laatst online: 12-09 14:21

koli-man

Bartender!!!!

OxiMoron schreef op woensdag 26 september 2007 @ 08:45:
globals moet je ten alle tijden zien te vermijden in OOP..

Misschien moet je de database class opzetten als singleton

Dan kun je hem overal waar je hem nodig hebt gewoon opvragen.
Nou omzeil je met een Singleton ook een beetje de OO regels... :X

Hey Isaac...let's go shuffleboard on the Lido - deck...my site koli-man => MOEHA on X-Box laaaiiiff


  • mithras
  • Registratie: Maart 2003
  • Niet online
Verwijderd schreef op woensdag 26 september 2007 @ 09:29:
[...]

PHP:
1
2
3
function bla () {
   global $db;
}

Dit is dan weer wél een beetje vragen om problemen.
Waarom zou dit eigenlijk niet kunnen? Ik heb in mn cms plugins, zegmaar gewoon classes. Bij de initialisatie van het cms maak ik een $database aan die een connectie opzet en feitelijk een ADOdb abstraction layer is.

Binnen de plugin is het dan een kwestie van
PHP:
1
2
3
4
5
6
7
class plugin{
  function get_something(){
    global $database;
    $result = $database->Execute("SELECT * FROM table WHERE something='else'");
    return $result;
  }
}

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

PHP:
1
2
3
4
5
6
7
while ($row = mysql_fetch_array($this->result))
{
    $login['UserID'] = $row['UserID'];
    $login['IP'] = $row['IP'];
    $login['Nickname'] = $row['Nickname'];
    echo $login['Nickname'];
}
is het niet gewoon makkelijker om te zeggen, aangezien dat de enige velden zijn die je selecteerd én weer in een andere array proppen wilt... :
PHP:
1
2
3
4
while ($row = mysql_fetch_array($this->result))
{
  $login = $row;
}
Op zich kan je dan net zo goed gebruik maken van $row, omdat $login dan een referentie word naar $row, een aanpassing vind dan toch ook plaats bij $row, tenzij $login &= $row oid toch?
Of was het juist andersom? :?

Verwijderd

mithras schreef op woensdag 26 september 2007 @ 09:56:
[...]
Waarom zou dit eigenlijk niet kunnen? Ik heb in mn cms plugins, zegmaar gewoon classes. Bij de initialisatie van het cms maak ik een $database aan die een connectie opzet en feitelijk een ADOdb abstraction layer is.

Binnen de plugin is het dan een kwestie van
PHP:
1
2
3
4
5
6
7
class plugin{
  function get_something(){
    global $database;
    $result = $database->Execute("SELECT * FROM table WHERE something='else'");
    return $result;
  }
}
In mijn ogen is het gebruik van global ranzig. Net zo als het gebruik van $GLOBALS. Het is leuk en handig om één array te hebben met daarin referenties naar al je variables/objects/etc., maar de structuur van je code wordt er niet duidelijker op imo. Ik zou het dan ook zo doen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class plugin{
    
    var $database = null;
    
    function plugin(&$db) {
        $this->database =& $db;
    }
    
    function get_something(){
        
        $result = $this->database->Execute("SELECT * FROM table WHERE something='else'");
        return $result;
    }
}
GJ-tje schreef op woensdag 26 september 2007 @ 11:28:
[...]
is het niet gewoon makkelijker om te zeggen, aangezien dat de enige velden zijn die je selecteerd én weer in een andere array proppen wilt... :
PHP:
1
2
3
4
while ($row = mysql_fetch_array($this->result))
{
  $login = $row;
}
Op zich kan je dan net zo goed gebruik maken van $row, omdat $login dan een referentie word naar $row, een aanpassing vind dan toch ook plaats bij $row, tenzij $login &= $row oid toch?
Of was het juist andersom? :?
Het is een referentie naar $row, totdat je een wijziging in $login maakt, dan geeft PHP $login zijn eigen stukje geheugen (en wijzig je dus niet $row). Tenzij je $login =& $row gebruikt.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Verwijderd schreef op woensdag 26 september 2007 @ 12:15:
[...]


In mijn ogen is het gebruik van global ranzig. Net zo als het gebruik van $GLOBALS. Het is leuk en handig om één array te hebben met daarin referenties naar al je variables/objects/etc., maar de structuur van je code wordt er niet duidelijker op imo. Ik zou het dan ook zo doen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class plugin{
    
    var $database = null;
    
    function plugin(&$db) {
        $this->database =& $db;
    }
    
    function get_something(){
        
        $result = $this->database->Execute("SELECT * FROM table WHERE something='else'");
        return $result;
    }
}
Tja, definieer ranzig ;) Sommige vinden het ook ranzig om meerdere exit points in een functie te hebben, maar ik vind het bijvoorbeeld prima om een exit point te creeeren na een niet-valide inputcontrole:
PHP:
1
2
3
4
5
6
function test($int){
  if (!is_int($int) )
    return;
  $int = do_something_with($int);
  return $int;
}
Hoewel dit natuurlijk een heel andere discussie betreft, is dit een van de meest duidelijke voorbeelden waar voor beide kampen echt wat te zeggen valt. Het is iets anders dan een eigen fuctie schrijven die in feite in_array() nabootst; iets wat je vaak ziet bij beginnende (php) programmeurs:
PHP:
1
2
3
4
5
6
function fake_in_array($needle, $array){
  for($i=0;$i<count($array);$i++){
    if($array[$i]==$needle)
      return true;
  }
}
^^ betreft ook een andere discussie, maar dit is wel een voorbeeld van ranzigheid omdat er bijvoorbeeld een (geoptimaliseerde) php functie voor bestaat en je hiermee resources verspilt.

Het gebruik van een (of specifieker: deze) global is niet ranzig, omdat het voor iedereen duidelijk is dat het een database object is wat in de bovenste "laag" van het systeem geinitialiseerd is. Het gebruik van een reference via $this->database=&$database is alleen maar onnodig en biedt op geen enkel vlak extra duidelijkheid: wat is $this->database? Als je er achter komt dat het een reference is naar het mee-gegeven &$database, zit je nog steeds met dezelfde vraag ;)

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
DanielB schreef op zaterdag 22 september 2007 @ 17:47:
[...]


een static method kan niet via een instanced object aangeroepen worden en een static property kan niet gebruik worden met behulp van de ->. Ook heb je dan geen $this-> dus meer, omdat static methods op te roepen zijn zonder instance.

Een class is het skelet van je object. Bij bijvoorbeeld een vervoersmiddel staat er het aantal willen in. Dus als mijn class vervoersmiddel is, kan ik er een object fiets van maken... En dan aangeven dat hij twee wielen heeft... En dat laten echo'en... ($fiets->aantalwielen)...

Van het laatste ben ik niet helemaal zeker, maar dat klopt volgensmij wel aardig...
Wat klopt er dan niet in het verhaaltje wat ik vertelde? (in het kader van fouten leren)
Je vertelt eigenlijk alleen maar wat wel en niet kan bij static methods, maar je hebt geen woord gerept over de betekenis. Een static variable/method van een class is een variabele die geshared wordt door alle instanties van die class, daarbij kun je zelfs die static var/method gebruiken zonder de class geinstantieerd te hebben.

Een class is geen skelet van een object, maar een definitie van een object. Een abstract class zou een skelet zijn voor een reguliere class die van die abstract class inherit.

[ Voor 3% gewijzigd door Grijze Vos op 26-09-2007 12:40 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
mithras schreef op woensdag 26 september 2007 @ 12:37:
Het gebruik van een (of specifieker: deze) global is niet ranzig, omdat het voor iedereen duidelijk is dat het een database object is wat in de bovenste "laag" van het systeem geinitialiseerd is.
Nee, niet alles is dijdelijk, je vind alleen de variabelenaam blijkbaar duidelijk. Maar het is dus niet duidelijk wat je wel en niet mag met die variabele, en waar er iets mee gebeurt. Het niet global hebben cq. OOP goed toepassen kan ook met deze variabele voordelen bieden.
Het gebruik van een reference via $this->database=&$database is alleen maar onnodig en biedt op geen enkel vlak extra duidelijkheid: wat is $this->database? Als je er achter komt dat het een reference is naar het mee-gegeven &$database, zit je nog steeds met dezelfde vraag ;)
Je wil een object maken en je weet dat deze een db nodig heeft, dus geef je die mee met de constructor. Daarna hoef je er helemaal niet meer over na te denken. Uiteraard kan die constructor controleren of een goed object is meegegeven, en verder kan je gewoon netjes OO denken, zonder global shit te gebruiken.

{signature}


  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 08-07 14:27
Ik vind een singleton netter dan een global, aangezien je met een global nooit zeker weet welk object je krijgt en je je rot kunt zoeken wat er nou in die global $x zat.
Terwijl je met een singleton oplossing meteen weet met welk object je te maken hebt, en je hebt ook niet de kans dat iemand per ongeluk je vage global overschrijft met iets anders.

Google maar eens op "php globals vulnerability".

je weet nooit op wat voor server je code zal draaien dus lijkt het me altijd beter om het veilig te houden ongeacht de configuratie.

[ Voor 14% gewijzigd door OxiMoron op 26-09-2007 13:15 ]

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


  • keisersose
  • Registratie: Maart 2003
  • Laatst online: 29-05 17:34
Nogmaals, zoals op http://www.phpit.net/article/using-globals-php staat, globals moet je vermijden. Er zijn zoals gezegd goede alternatieven zoals een class met alleen maar statics, of de singleton aanpak.
De registry aanpak kan natuurlijk ook, maar dat is weer een soort van je eigen $GLOBALS uitbreiding maken.

Verwijderd

Het voordeel van $GLOBALS['var'] versus global $var is dat je op elke plek in de code kunt zien dat er een global wordt gebruikt. Nou kun je alle prachtige academische OO kennis loslaten op je projecten, maar als je van tevoren weet dat 100% mooie OO code in PHP toch al een illusie is, kun je best af en toe even zondigen door $GLOBALS te gebruiken. Daarbij hoor je natuurlijk te beseffen dat het vast mooier kan, maar ik besef me dan ook altijd dat ik geen zin heb om een stukje code te gaan schrijven omdat je volgens iemand vooral GEEN globals mag gebruiken. Als je de risico's kent, weet je ook hoe je die zo klein mogelijk kunt maken. Dus voor een ervaren PHP developer is het af en toe gebruiken van een global echt geen schande, als je dat maar niet doet uit een gebrek aan kennis. Lekker ranzig maar effectief doen moet soms kunnen.

Verwijderd

Verwijderd schreef op woensdag 26 september 2007 @ 13:37:
Het voordeel van $GLOBALS['var'] versus global $var is dat je op elke plek in de code kunt zien dat er een global wordt gebruikt. Nou kun je alle prachtige academische OO kennis loslaten op je projecten, maar als je van tevoren weet dat 100% mooie OO code in PHP toch al een illusie is, kun je best af en toe even zondigen door $GLOBALS te gebruiken. Daarbij hoor je natuurlijk te beseffen dat het vast mooier kan, maar ik besef me dan ook altijd dat ik geen zin heb om een stukje code te gaan schrijven omdat je volgens iemand vooral GEEN globals mag gebruiken. Als je de risico's kent, weet je ook hoe je die zo klein mogelijk kunt maken. Dus voor een ervaren PHP developer is het af en toe gebruiken van een global echt geen schande, als je dat maar niet doet uit een gebrek aan kennis. Lekker ranzig maar effectief doen moet soms kunnen.
'Lekker ranzig' doe je bij huis-tuin-en-keuken websites, niet bij grotere projecten, waarbij je de code na een jaar weer tegenkomt. De risico's wat het gebruik van globals met zich meeneemt op de lange termijn (en de tijd daardoor) wegen niet op tegen 'nette' code.
Wat denk je wat ik zou zeggen als m'n collega naar me toe komt met 'hier, je code is af, maar eh.. ik heb wel globals gebruikt. Is op zich niet erg hoor, het risico is maar minimaal...'.

100% nette OO code (voor php) is dan wellicht niet mogelijk, maar het is ook niet de bedoeling om het nog erger te maken dan het al is, onder het mom van 'net kan toch niet, dus een beetje slechter maakt ook niet uit'

  • mithras
  • Registratie: Maart 2003
  • Niet online
Voutloos schreef op woensdag 26 september 2007 @ 12:56:
[...]
Nee, niet alles is dijdelijk, je vind alleen de variabelenaam blijkbaar duidelijk. Maar het is dus niet duidelijk wat je wel en niet mag met die variabele, en waar er iets mee gebeurt. Het niet global hebben cq. OOP goed toepassen kan ook met deze variabele voordelen bieden.
[...]
Daar heb je gelijk in, maar nog steeds heb je het probleem door het af te vangen in de constructor niet opgelost. Het is, of het nu een global is of vastgelegd in de klasse, een object waar je vanuit de klasse niet kan zien wat er wel en niet mag. Via $this-> of een global: dat maakt afaik geen verschil.
Je wil een object maken en je weet dat deze een db nodig heeft, dus geef je die mee met de constructor. Daarna hoef je er helemaal niet meer over na te denken. Uiteraard kan die constructor controleren of een goed object is meegegeven, en verder kan je gewoon netjes OO denken, zonder global shit te gebruiken.
En daar gaat het in mijn casus fout: ik kan er vanuit gaan dat een object een database nodig heeft, maar hoe weet ik dat zeker? Ik vind dat het object zelf bepaald of een database nodig is of niet, en niet de initiator. Daarom wil ik per definitie geen reference meegeven bij het object, omdat op die manier niet het object bepaald dat het een database nodig heeft, maar het opgelegd krijgt :)
keisersose schreef op woensdag 26 september 2007 @ 13:11:
Nogmaals, zoals op http://www.phpit.net/article/using-globals-php staat, globals moet je vermijden. Er zijn zoals gezegd goede alternatieven zoals een class met alleen maar statics, of de singleton aanpak.
De registry aanpak kan natuurlijk ook, maar dat is weer een soort van je eigen $GLOBALS uitbreiding maken.
Als ik even verwijs naar de 3 punten die aan het einde van het artikel staan:
  1. Heb ik er iets mee te maken dat een bepaald deel van mijn script hergebruikt wordt door iemand anders? Mijn script zit in een bepaalde context (cms, framework achtig iets), waarvoor het is geschreven. Je kan, mocht je dat willen, een wrapper gebruiken om een plugin te gebruiken in $randomsysteem, maar moet ik nu rekening houden met het feit dat in mijn framework wordt geknipt? Moet ik het dus zo makkelijk mogelijk maken om andere mijn code te herbruiken? Ik zie niet in dat een global daarin je tegenhoud, zeker als ik alleen maar een $database ADOdb object gebruik ;)
  2. Ik heb serieus in de jaren dat ik met het systeem werk nog nooit tegen een bug van ADOdb aangelopen wat het resultaat is van het gebruik van globals. En ik kan ook niet inzien dat als je een open en clean systeem bouwt, je dit niet snel zou kunnen oplossen.
  3. Hier gaat het erom dat het gebruik van veel (onnodige) globals fout is: iets wat ik zeker erken. Echter nog steeds: het principe van globals is niet erg. Een global dat een individueel deel van het systeem representeert, zegmaar een dienst verleent (want dat doet een database abstraction layer) aan de "echte" onderdelen van je framework is niet erg imho.
Verwijderd schreef op woensdag 26 september 2007 @ 13:37:
[...] omdat je volgens iemand vooral GEEN globals mag gebruiken. Als je de risico's kent, weet je ook hoe je die zo klein mogelijk kunt maken. Dus voor een ervaren PHP developer is het af en toe gebruiken van een global echt geen schande, als je dat maar niet doet uit een gebrek aan kennis. Lekker ranzig maar effectief doen moet soms kunnen.
+1 inzichtvol
offtopic:
Bedenk trouwens wel: ik ben een student, en niet in de ICT sector. Al zeg ik het zelf, maar ik heb hersens om dit soort stukken te snappen, maar zit niet in de zakelijke ICT wereld, waar imho gebruikelijkheden soms als waarheden worden gepresenteerd. Iets waar ik dus graag door heen wil prikken. Maar ik heb geen boeken, leer van internet en dit soort discussies. En al zeg ik het zelf, daardoor ben ik wel een goede html/css + php programmeur van geworden.

[ Voor 5% gewijzigd door mithras op 26-09-2007 13:57 ]


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
mithras schreef op woensdag 26 september 2007 @ 13:55:
[...]

En daar gaat het in mijn casus fout: ik kan er vanuit gaan dat een object een database nodig heeft, maar hoe weet ik dat zeker? Ik vind dat het object zelf bepaald of een database nodig is of niet, en niet de initiator. Daarom wil ik per definitie geen reference meegeven bij het object, omdat op die manier niet het object bepaald dat het een database nodig heeft, maar het opgelegd krijgt :)
Je kunt ervoor kiezen om een soort manager class te hebben waar je je database connectie opvraagt. (Registry Pattern) Maar goed, je moet je afvragen in hoeverre dat object niet gewoon een veredelde globals array is.

Mensen moeten in de gaten hebben dat het idee van 'globals == evil' afstamt van gevaarlijke namespace pollution, drie entries in je globals array doet daar niks aan af.

Overigens kun je nog altijd in je class in de constructor iets als dit zetten:

PHP:
1
2
3
4
5
6
7
global $db;

$this->db = $db;

// of:

$this->db = $GLOBALS["db"];


Je hoeft natuurlijk niet al je member functions te polluten met referenties aan een global iets. Maakt refactoren ook makkelijker btw, mocht je het op je heupen krijgen en het Registry Pattern toe te willen passen. :)

[ Voor 9% gewijzigd door Grijze Vos op 26-09-2007 14:06 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Verwijderd

Verwijderd schreef op woensdag 26 september 2007 @ 13:48:

'Lekker ranzig' doe je bij huis-tuin-en-keuken websites, niet bij grotere projecten, waarbij je de code na een jaar weer tegenkomt. De risico's wat het gebruik van globals met zich meeneemt op de lange termijn (en de tijd daardoor) wegen niet op tegen 'nette' code.
Wat denk je wat ik zou zeggen als m'n collega naar me toe komt met 'hier, je code is af, maar eh.. ik heb wel globals gebruikt. Is op zich niet erg hoor, het risico is maar minimaal...'.
PHP:
1
2
3
$GLOBALS['activeLocale'] = new Locale('nl_NL');
// versus
Locale::setActiveLocale(new Locale('nl_NL'));

Als je je gaat afvragen wat nou exact de meerwaarde is van het tweede, dan valt dat best wel mee. Natuurlijk, het implementeren van het 2e is 3 regels code, maar eigenlijk win je er niet zoveel mee. Dat bedoel ik te zeggen. Niet dat je te pas en te onpas globals moet gebruiken, want sowieso creëer je dan een soort van niet re-entrant geheel. Maar dat hoeft ook niet altijd. Het angstvallig vasthouden aan je moet NOOIT globals gebruiken vind ik zwaar overdreven. Er zijn meestal mooiere oplossingen, dat zeker. Maar er moet nou ook weer niet de doodstraf staan op het duidelijk toepassen van zo'n $GLOBALS variabele.
100% nette OO code (voor php) is dan wellicht niet mogelijk, maar het is ook niet de bedoeling om het nog erger te maken dan het al is, onder het mom van 'net kan toch niet, dus een beetje slechter maakt ook niet uit'
Soms maak je het ook niet erger, maar levert het "mooier" doen ook niet zoveel op.

Verwijderd

mithras schreef op woensdag 26 september 2007 @ 13:55:
[...]

En daar gaat het in mijn casus fout: ik kan er vanuit gaan dat een object een database nodig heeft, maar hoe weet ik dat zeker? Ik vind dat het object zelf bepaald of een database nodig is of niet, en niet de initiator.
Even los van de discussie over wel of geen (goed/slecht) gebruik van globals;
Dus jij vindt dat een object zelf bepaald wat voor andere variables/objecten deze nodige heeft, en laat het object dit per geval zelf oplossen door, daar waar nodig, een global $var te plaatsen in een functie?
Het lijkt me dat je tijdens het bedenken van je app en hoe je je app op gaat bouwen, er al achter komt wat voor objecten/classes je nodig gaat hebben en hoe de onderlinge verhoudingen liggen?
Of gebruik je objects als een veredelde vorm van include("functions.php")?

Als een method in een object een bepaalde variable/object nodig heeft, dan hoort dat mijn inziens of bij de requirements van de class, of je geeft die specifieke variable/object mee aan de functie zelf. (afhankelijk van die situatie)
Daarom wil ik per definitie geen reference meegeven bij het object, omdat op die manier niet het object bepaald dat het een database nodig heeft, maar het opgelegd krijgt :)
Als je per definitie wel een reference mee geeft aan het object (en evt. een foutmelding teruggeeft als dat niet gebeurd) dan weet je zeker dat je object over alle benodigdheden beschikt om goed te werken. (Jaja, dit kan ook met globals, maar zie mijn reactie hier pal boven).

En wat betreft "omdat op die manier niet het object bepaald dat het een database nodig heeft, maar het opgelegd krijgt" - code heeft geen vrije wil >:)

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 16:36
Verwijderd schreef op woensdag 26 september 2007 @ 14:10:
PHP:
1
2
3
$GLOBALS['activeLocale'] = new Locale('nl_NL');
// versus
Locale::setActiveLocale(new Locale('nl_NL'));
Het voordeel van de tweede is dat in de Locale klasse een type afgedwongen kan worden en in de global niet.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Class Locale {
  private static $_active;

  public static function setActiveLocale(Locale $loc) {
    self::$_active = $loc;
  }
  
  public static function getActiveLocale() {
    if (self:$_active instanceof Locale) {
      return self::$_active;
    } else {
      //do something sensible: error, default locale
    }
  }
}

Regeren is vooruitschuiven


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Verwijderd schreef op woensdag 26 september 2007 @ 14:10:
[...]

PHP:
1
2
3
$GLOBALS['activeLocale'] = new Locale('nl_NL');
// versus
Locale::setActiveLocale(new Locale('nl_NL'));

Als je je gaat afvragen wat nou exact de meerwaarde is van het tweede, dan valt dat best wel mee.
Die meerwaarde is er niet, en de reden lijkt me op zich vrij duidelijk. Een static behoord ook tot de globale scope en heeft dus met dezelfde problemen te maken als wanneer je een globale variabele zou gebruiken.
Het angstvallig vasthouden aan je moet NOOIT globals gebruiken vind ik zwaar overdreven. Er zijn meestal mooiere oplossingen, dat zeker. Maar er moet nou ook weer niet de doodstraf staan op het duidelijk toepassen van zo'n $GLOBALS variabele.
Dit hangt compleet af van de omgeving waarin je ontwikkeld. Zodra je automatische tests zoals unit tests in gaat voeren heb je vrijwel meteen een probleem als je van globale symbolen gebruik probeert te maken.
Soms maak je het ook niet erger, maar levert het "mooier" doen ook niet zoveel op.
"Don't Live with Broken Windows"

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
keisersose schreef op woensdag 26 september 2007 @ 01:14:
[...]

Van mij mag iedereen het door mij geposte stukje code gebruiken. (Maar inderdaad, het is wel prettig om de werking ervan te snappen ;))

@DanielB: Lukt het verder een beetje met de desbetreffende code?
Als ik iets al niet denk te snappen, dan gebruik ik het ook niet... Maar ik denk dat ik het nu langzamerhand wel begin te snappen... :)

Wat betreft de code: ik zit al sinds maandag aan een marktanalyse over Amsterdam, dus nog weinig er aan kunnen doen... Zeker gezien school voor hobby/vrije tijdsproject gaat.

Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Ik was bezig met scripten, maar nu komt misschien een stomme vraag... $user->id werkte wel, maar wanneer ik $user->id naar $user->userid of $user->user_id veranderde, werkt het niet meer. Zijn userid/user_id reserved?

Ik kan dat namelijk niet terugvinden.

Acties:
  • 0 Henk 'm!

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Nee die zijn niet reserved.

Programmer - an organism that turns coffee into software.


Acties:
  • 0 Henk 'm!

  • DanielB
  • Registratie: Augustus 2003
  • Laatst online: 21-08 17:20
Ik ben gewoon weer dummy bezig... Je moet natuurlijk wel de JUISTE lines wijzigen.

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
php.net > search 'reserved' > http://nl3.php.net/manual/en/reserved.php

{signature}


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

T-MOB schreef op woensdag 26 september 2007 @ 15:10:
[...]


Het voordeel van de tweede is dat in de Locale klasse een type afgedwongen kan worden en in de global niet.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Class Locale {
  private static $_active;

  public static function setActiveLocale(Locale $loc) {
    self::$_active = $loc;
  }
  
  public static function getActiveLocale() {
    if (self:$_active instanceof Locale) {
      return self::$_active;
    } else {
      //do something sensible: error, default locale
    }
  }
}
Daarbij zet ik toch wat kanttekeningen bij je getter, i.e. dat deze misschien overbodige regels aan code bevat. Ik begrijp dat je deze eventueel erbij zou willen doen omdat het hier om typehinting gaat, maar als code faalt hoort deze imho hard te falen. Dit omdat de fout dan meteen opgemerkt wordt en verholpen kan worden.

In dit geval check je of self::$active een Locale is, maar dit wordt in zekere zin al gegarandeerd door de setter, zeker met de error_reporting op z'n hoogst ingesteld (i.e. zou je hier al van de op de hoogte moeten gebracht). Ik weet niet of het dus handig is om hier uberhaupt LOC aan te besteden om defensief bij iets te programmeren dat eigenlijk hard hoort te falen (en ja, je zou dat opzich ook in het laatste geval nog kunnen doen, maar dan ben je nog meer LOC's verder, en als je dat in een groot project zou doen heb je eigenlijk code die vervuild is met crosscutting concerns.). Unittesting is in zulke gevallen meer aan te raden dan.
Pagina: 1