Archief - PHP: classes en OOP

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Erlend

Legacy Member
Na het lezen van dit artikel ben ik al heel wat wijzer geworden uit
classes in php, toch blijf ik met enkele vragen zitten. Ik probeer
mijn 'uitvoerende' code en html meer te scheiden van elkaar, dit
door het gebruiken van classes en bijhorende functions. Om alles
toch maar is zelf te proberen en het onder de knie te krijgen ben
ik bezig aan een klein testje waarin ik dit alles probeer uit te voeren.

De vragen:
  • Hoe zien jullie classes eruit, meer specifiek hoe springen jullie om met het invoeren/uitlezen van data in een db. Vb. één functie die de query's uitvoerd; maar wat dan met het resultaat? Daar waar het resultaat niet overal hetzelfde is.
  • Echo's/boodschappen zoveel mogelijk in de pagina zelf of toch in de class? (Ik nu werk vaak met return true om in de pagina zelf de gepaste boodschap weer te geven.)
Hopelijk is het niet te onduidelijk. Ik heb gewoon het idee van; probeer je code te standariseren zodat je die kan hergebruiken en je vb. een query uitvoeren geen 100 keer moet typen. Graag iets meer uitleg en liefst met voorbeelden uit php applicaties. Want die voorbeelden van beren die zwemmen en eten doen het mij wel deels begrijpen, toch heb ik het moeilijk om classes ( en OOP) te vertalen naar mijn applicatie.

Dit alles is misschien veel gevraagd, ik wil gewoon weten waar ik sta
en wat ik fout doe! Hieronder vind je mijn php-pagina zelf en een
php bestand met de twee gebruikte classes in.

http://www.artueel.be/telenet/

Twee bestanden staan ook samen in een rar.

Alvast bedankt!
Spuien maar :)

Disa

Legacy Member
Meestal scheid ik men code en layout compleet door gebruik te maken van een template parser. Atm gebruik ik nog een template parser van killgore gebaseerd op phpBB waar ik zelf wat kleine aanpassingen op heb gedaan.

Ik vind het veel overzichtelijker om op die manier te werken.

Ik weet echter niet of dit de pagina veel vertraagt of niet. Het kan soms wat tricky zijn, maar het levert wel veel voordelen op. Zo kan de persoon die designs voor je maakt al de layout doen, zonder al teveel kennis van php. (heeft eigenlijk geen kennis van php nodig).


Ik ken eigenlijk maar weinig van OOP toestanden en ik geef toe dat ik daar eens naar zou moeten kijken maar de luiheid en examens zijn alom tegenwoordig ;>.

Het enige dat ik in classes steek, is mysql (connect, select_db, query, error afhandeling) en gameserver data fetchen.

Anywayz het is al een tijdje geleden dat ik nog php heb gebruikt dus forgive me als ik hier major mistakes maak ofzo :p

- Disa

.kw

Legacy Member

Ik maak één klasse, die de smarty klasse uitbreidt en de ezSQL-functies overneemt, waarmee elke pagina kan worden gegenereerd. De templates bevatten niets van PHP, enkel variabelen en functies van Smarty. Veel overzichtelijker op die manier. Ik ben nog wat aan het uitzoeken hoe ik de klassen het best samenbreng, maar het werkt voorlopig toch al tamelijk vlot en er zijn dikwijls minder query's nodig om hetzelfde resultaat te bekomen.

Tyfius

Legacy Member
Ik heb zelf een klein framework geschreven, aantal core klassen (database (mysql, mssql, ...), net (url, email), ...). Werkt ook met templates.

PC_Freak

Legacy Member
Ik werk al een tijdje aan forumsoftware maar die is nog niet compleet OO geschreven. Voor de moment enkel de basis: database, template-parser etc.

De nieuwe zo zou moeten zijn:

- Database-access, queries, results worden aparte klassen. Zo kan je bvb met de database klassen een nieuw query object aanmaken, die dan op zijn beurt een result kan teruggeven.
- Beetje hetzelfde met templates en andere zaken zoals sessies.

- Om de database makkelijk te gebruiken wordt er een API geschreven, klassen voor topics, posts, forums, enz. die overal gebruikt kunnen worden om wijzigingen te maken aan de data in de database. Maw in de eigenlijke actiecode zelf moet je dan geen queries meer gebruiken.

- De "pagina's" worden dan aparte klassen die overerven (extend) van een algemene klasse die een "pagina" beschrijft.

Op die manier heb je dan een mooi OO systeem. Wat je dan enkel nog nodig hebt is 1 klasse die als eerste wordt aangeroepen en die vervolgens alles "gereed zet" en de juiste pagina-klasse oproept.

Jos_Albatros

Legacy Member
ik gebruik db_dataobject in combinatie met quickform om db data te inserten en updaten
(2 packages van Pear) = super combinatie :niceone:

mini voorbeeld :

$product = DB_DataObject::factory ("products");
$product -> setFrom ($_POST);
$product -> insert();

in deze 3 regels code wordt een product toegevoegd aan de database,
dit is een heel simpel voorbeeld natuurlijk, is maar om een idee te geven hoe makkelijk het werkt

smarty dan weer voor template's
(heel handig voor de ingebouwde functies voor strings enz, sections zijn ook handig)

PC_Freak

Legacy Member
Voor templates wil ik wel proberen van XML/XSL te gebruiken (op PHP5). Daar zit een kant-en-klare XML-parser in met XSL support, dus waarom nog een andere library zoals Smarty gebruiken + XSL is een standaard.

dJeez

Legacy Member
Voor het "zwaardere" werk gebruik ik Propel, en dat is zalig om mee te werken. Je maakt gewoon je object model in XML formaat (met de nodige referenties) en Propel zorgt ervoor dat je makkelijk met die objecten kan werken (de basiscode wordt dus door Propel zelf gegenereerd).

Enige potentiële nadeel : het werkt best met PHP5, en er zijn nog niet veel hosting providers die die aanbieden (tot op heden heb ik 't dan ook enkel voor Intranet toepassingen gebruikt aangezien je daar alles zelf in de hand hebt).

WHiSPy

Legacy Member
Ik hoop dat er nu geen mensen OOP gaan gebruiken omdat 't cool klinkt. Misschien is het beter om toch ff eerst te bekijken tot wat voor doel 't kan dienen alvorens ge 't effectief gaat gebruiken. :)

.kw

Legacy Member
WHiSPy zei:
Ik hoop dat er nu geen mensen OOP gaan gebruiken omdat 't cool klinkt. Misschien is het beter om toch ff eerst te bekijken tot wat voor doel 't kan dienen alvorens ge 't effectief gaat gebruiken. :)

Als ik wilde verhalen vertel aan mensen over hoe ik OOP programmeer, kom ik naam mijn idee nochtans niet cool over.

Ik leer zo programmeren op school en zelf vind ik het ook een duidelijke manier. Je moet mee zijn met je tijd vind ik. :cool:

killgore

Legacy Member
.kw zei:
Als ik wilde verhalen vertel aan mensen over hoe ik OOP programmeer, kom ik naam mijn idee nochtans niet cool over.

Ik leer zo programmeren op school en zelf vind ik het ook een duidelijke manier. Je moet mee zijn met je tijd vind ik. :cool:
kdenk eerder dat whispy bedoelt dat veel mensen nu in php oop gaan programmeren omdat het zo populair (lees: noobs gebruiken et cst) is geworden sinds php5. Dit terwijl elke site nog extreem veel aparte zaken hebt die je beter uit empirisch, puur functioneel programmeren kan benaderen aangezien oop je daar eerder tijd & resources kost als oplevert.

OOP is prachtig voor hergebruikbaarheid of grotere systemen, maar o zo stom om bv. een heel nieuwssysteem in OOP te schrijven (je kan enkele dingen in klasses rammen omdat het handig is, but that's it).

Zelfde voor een taal als java eigenlijk.
Je gaat toch geen klasse MachtBerekenaar maken als je dit in een doodnormale functie Math.pow kan steken? Hoe je het ook draait of keert, dat is nu eenmaal nog steeds functioneel programmeren!

Erlend

Legacy Member
Ik kan volgen wat whispy zegt, dat is een stukje mijn vraag hier; waar en wanneer kies ik voor classes. Ik wil het doel van classes en OOP niet
voorbijlopen en het zomaar gaan gebruiken.

Momenteel kan ik moeilijk de lijn trekken tussen wat ik in een class
steek en wat niet, vandaar dat ik hier een idee wil opdoen van wat
jullie juist allemaal doen.

Aanvullend; zijn er mensen die handige websites hebben liggen, dit
inverband met classes, frameworks,OOP (daarom niet enkel over php).

Alvast bedankt voor de reacties!

dJeez

Legacy Member
killgore zei:
OOP is prachtig voor hergebruikbaarheid of grotere systemen, maar o zo stom om bv. een heel nieuwssysteem in OOP te schrijven (je kan enkele dingen in klasses rammen omdat het handig is, but that's it).
Dat is imho nu net een slecht voorbeeld dat je aanhaalt, een nieuwssysteem is nl. uitermate geschikt om op OOP manier te benaderen. Want wat is een nieuwsbericht nu? De basis is een datum (van publicatie), titel, korte inhoud, volledige inhoud, bronvermelding, eventueel wat foto's. Op elke site dus (quasi) dezelfde inhoud, enkel het uitzicht verschilt, wat het dus uitermate geschikt maakt voor een OOP klasse, waarvan je overerft indien er bepaalde specifieke zaken zijn die bij het nieuwsbericht horen voor (enkel) die site.

OOP - mits correct gebruikt - bespaart dus enorm veel tijd in ontwikkeling (niet initieel, wel op lange termijn), en niet zo'n klein beetje.

Wil dat dan zeggen dat je elk project object oriented moet aanpakken? Zeer zeker niet, OOP is geen wondermiddel, het heeft geen zin om met een kanon naar een mug te schieten, en je moet het dus gewoon project per project bekijken. Soms is rechttoe rechtaan functioneel programmeren aangewezen (maar dan toch eerder voor eenmalige kleine projecten zonder direct vooruitzicht op uitbreidingen, en niet voor complexe toepassingen).

Erlend

Legacy Member
Is iemand bereid snel even mijn twee classes na te kijken
en hierover een woordje te doen?
---
Zijn er soms mensen die hun class willen tonen zodat ik meer
een idee krijg van hoe het er daadwerkelijk uitziet. Het is niet
de bedoeling dat ik jullie class ga kopieren/gebruiken, enkel
om juist te zien hoe de vork in de steel zit want de meesten
geven hier goede voorbeelden, ik kan mij enkel niet volledig inbeelden
hoe en wat er nu allemaal gebeurd in de class zelf en hoe dit
eruit ziet in php.

Tyfius

Legacy Member
Hieronder mijn database klasse, van enkele maanden geleden. Tegenwoordig is het allemaal iets geavanceerder, maar hiermee heb ik mijn eerste OOP ervaring in PHP beleefd.

database.php
PHP:
<?php
/**
* Database class.
*
* @package core
* @subpackage database
* @version 0.1.0
*/

class Database {
    /////////////////////////////////////////////
    // CLASS VARIABLES
    /////////////////////////////////////////////

    var $hostname;
    var $username;
    var $password;
    var $database;

    /////////////////////////////////////////////
    // CLASS FUNCTIONS
    /////////////////////////////////////////////

    function database($hostname, $username, $password, $database) {
        $this->setHostname($hostname);
        $this->setUsername($username);
        $this->setPassword($password);
        $this->setDatabase($database);
    }

    function setHostname($hostname) {
        $this->hostname = $hostname;
    }

    function setUsername($username) {
        $this->username = $username;
    }

    function setPassword($password) {
        $this->password = $password;
    }
    
    function setDatabase($database) {
        $this->database = $database;
    }

    function getHostname() {
        return $this->hostname;
    }

    function getUsername() {
        return $this->username;
    }

    function getPassword() {
        return $this->password;
    }

    function getDatabase() {
        return $this->database;
    }
}; // END DATABASE CLASS
?>

mysql.php
PHP:
<?php
/**
* MySQL database class.
* 
* @package core
* @subpackage database
* @see database.php
* @version 0.1.0
*/

class MySQL extends Database {
    /////////////////////////////////////////////
    // CLASS VARIABLES
    /////////////////////////////////////////////

    var $kernel;            // A pointer to the kernel object.
    var $resource;
    var $connectstatus;
    
    /////////////////////////////////////////////
    // CLASS FUNCTIONS
    /////////////////////////////////////////////

    function mysql($hostname, $username, $password, $database, &$kernel) {
        parent::database($hostname, $username, $password, $database);
        $this->setKernel($kernel);
        $this->setConnectStatus(false);
        $this->connect();
        $this->selectDatabase();
    }

    function getKernel() {
        return $this->kernel;
    }
    
    function setKernel($kernel) {
        $this->kernel = $kernel;
    }

    function getResource() {
        return $this->resource;
    }

    function setResource($resource) {
        $this->resource = $resource;
    }

    function getConnectStatus() {
        return $this->connectstatus;
    }

    function setConnectStatus($connectstatus) {
        $this->connectstatus = $connectstatus;
    }

    function connect() {
        if ($this->getConnectStatus() === false) {
            $succes = mysql_connect(parent::getHostname(), parent::getUsername(), parent::getPassword());
            if ($succes === false) {
                $this->getKernel()->getError()->handleError("An error has occured while trying to connect to the database server.");
            } else {
                $this->setResource($succes);
                $this->setConnectStatus(true);
            }
        }
        // Already connected.
    }

    function disconnect() {
        if ($this->getConnectStatus() === true) {
            $succes = mysql_close($this->getResource());
            if ($succes === false) {
                $this->getKernel()->getError()->handleError("An error has occured while trying to close the connection with the database server.");
            } else {
                $this->setConnectStatus(false);
            }
        }
        // Nothing to close.
    }

    function selectDatabase($database = parent::getDatabase()) {
        if ($this->getConnectStatus() === true) {
            $succes = mysql_select_database($database);
            if ($succes === false) {
                $this->getKernel()->getError()->handleError("An error has occured while selecting the database ".$database.".");
            }
            // Database succesfully selected.
        } else {
            $this->getKernel()->getError()->handleError("Tried to select a database, but without a connection to a database server.");
        }
    }

    function query($querystring) {
        if ($this->getConnectStatus() === true) {
            $succes = mysql_query($querystring);
            if ($succes === false) {
                $this->getKernel()->getError()->handleError("Tried to execute the following query, but failed. >> ".$querystring);
                return false;
            } else {
                return $succes;
            }
        } else {
            $this->getKernel()->getError()->handleError("Tried to execute the following query, but failed: no connection with a database server. >> ".$querystring);
            return false;
        }
    }
}; // END MYSQL CLASS   
?>

De functies voor mysql_num_rows() en dergelijke heb ik hier even achterwege gelaten. Identieke klassen bestaan voor MSSQL, Postgres, ...
Kernel heb ik laten staan.
Basicly werk ik dus met 1 kernel pointer die het ganse framework beheerd. De juiste classes inlaad, de url opbouwt, error handling doet, ...
't Is niet veel, en very basic, maar 't zou je toch een goed idee moeten geven. Kijk zeker ook eens naar de PEAR packages, daar heb ik mijn huidige klassen meer en meer op gebaseerd, maar ook alleen wat ikzelf nodig achtte, want je kunt ook zeer ver gaan in die dingen.

Het aanmaken van de database connectie is dus zeer eenvoudig:
PHP:
$mysql = new MySQL($hostname, $username, $password, $database, $kernel);
$resultresource = $mysql->query("SELECT * FROM table");

WHiSPy

Legacy Member
Ik ben persoonlijk meer 'n fan van setter injection ipv constructor injection. Maar op dat vlak kan je natuurlijk best eerst eens kijken naar het dependency injection en het inversion of control design pattern.

Design patterns zijn immers 'n aanmoediging om propere OO code te schrijven door 'n theoretische oplossing te formuleren voor veel voorkomende problemen. Doordat die oplossing zuiver theoretisch is, kan je zelf de uitwerking ervan aanpassen aan jouw situatie.

Erlend

Legacy Member
@ Tyfius

Er zijn mij nog enkele dingen niet duidelijk, zoals die kernel pointer waarover
je spreekt. Wil je ook wat meer uitleg geven bij de HandleError (functie).

killgore

Legacy Member
WHiSPy zei:
Ik ben persoonlijk meer 'n fan van setter injection ipv constructor injection.
Persoonlijk vind ik dat je best beiden implementeert zoals tyfius deed. Zeker voor zo vrij algemene klassen als dit. Dit omdat het vaak de bedoeling is dat meerdere mensen dit gebruiken (veel meerdere).
Ik prefereer in gebruik ook setters omdat je dan betere/makkelijkere fout-afhandeling hebt en mogelijkheid tot return-values.

Wat ik fout vindt aan zijn code (kan zijn dat het door simplificatie is) is het ontbreken van controllers bij set-code. Ik kan bv. setKernel(1) doen, wat bij mijn weten niet echt de bedoeling is :). Wat zou moeten zijn is dat hij controleert of het een kernel is en dan de juiste foutafhandeling doen (false teruggeven, error gooien, ...). Hetzelfde voor setResource.

Erlend: kernel moet je je niet druik om maken. Dit is gewoon de kern van zijn programma (ge kent wrsch wel de kernel.dll's die zowat de kern van uw OS zijn). Ik gok dat hij via $kernel->getError() het systeem opvraagt waar errors worden afgehandeld, en via HandleError dan de functie binnen dat systeem aanspreekt om een bepaalde Fout af te handelen. Hij kan dus op een ander niveau instellen dat zijn error-systeem die fouten opslaat, weergeeft, ...

Erlend

Legacy Member
Goed, das nu ook duidelijk voor mij. Waar ik toch nog mee zit, ik zie
de functie die connect met de databank maar k'vind niet echt terug
waar deze wordt aangeroepen.

Is het ook zo dat zijn systeem ervoor zorgt dat ik geen controle
moet uitvoeren of connectie/uitvoeren van query is gelukt omdat
deze controle al gebeurd in de class zelf? Momenteel kijk in de
pagina zelf (waar'k de class gebruik) na of het uitvoeren van mijn
query true is.

killgore

Legacy Member
Erlend zei:
Goed, das nu ook duidelijk voor mij. Waar ik toch nog mee zit, ik zie
de functie die connect met de databank maar k'vind niet echt terug
waar deze wordt aangeroepen.

Is het ook zo dat zijn systeem ervoor zorgt dat ik geen controle
moet uitvoeren of connectie/uitvoeren van query is gelukt omdat
deze controle al gebeurd in de class zelf? Momenteel kijk in de
pagina zelf (waar'k de class gebruik) na of het uitvoeren van mijn
query true is.
1) das omdat em enkel de klasseimplentatie levert he, hij heeft nergens een vb. gegeven van gebruik van die klasse :p.
2) ja en nee. Aangezien die kernel eigenlijk zo ingesteld is voor die pagina dat ze vrij uniek is (hoop ik toch) wordt de fout dus afgehandeld door de pagina zelf, maar in de kernel. Je moet dus in je pagina zelf niet meer op fouten checken, je moet wel je kernel laten weten hoe hij fouten afhandelt.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan