Classes in 1 script?
Is het beter om alle classes in 1 script te zetten (lijkt mij handiger en mooier).
Of is het beter om de class te maken in het het desbetreffende php script?
mvg,
Daan
http://www.phphulp.nl/php/tutorial/overig/oop-beginnershandleiding-php5/701/naamgeving/1843/
lees dit eens door, en dan het laatste kopje
lees dit eens door, en dan het laatste kopje
Dus bijvoorbeeld alle classes die je wil maken m.b.t. database verwerkingen in een db.class.php te zetten. En eventuele classes die met inloggen en eventuele user opties te maken heeft in een user.class.php te zetten.
Zodat je niet 300 regels aan classes en functies krijgt in 1 document. Tevens hoef je dan alleen de juiste classes te includen in de plaatsen waar je het nodig hebt, zonder alle classes overal beschikbaar te hebben.
Echter dit is mijn voorkeur en werkwijze, het hoeft uiteraard niet de beste uitkomst te bieden. Wat lijkt je zelf prettiger werken? Dat is tenslotte het belangerijkste :D
Gewijzigd op 09/05/2012 08:46:54 door Chris PHP
Mij lijkt het zo ook het prettiger werken Chris dus dan doe ik het ook zo:D
Succes met OOP.
sla elke class op in een apart .class.php
en voor databasebewerkingen gebruik je dan een datamapper: een class die juist een andere class verwacht als parameters bij de methods, en voor jou de connectie met de buitenwereld vastlegt.
voor de user classe bijvoorbeeld, die doe je helemaal apart.:
user.class.php:
Code (php)
userMapper.class.php:
Een map maken in je root (classes)
Vervolgens zou ik daar submappen in maken bijvoorbeeld (nieuws).
Dan heb je ongeveer zoiets,
Als je hier dan zo je classes in zet dus.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
Classes
| Nieuws
-nieuwsartikel.php
-reactie.php
| Gebruikers
- user.php
- privebericht.php
?>
Classes
| Nieuws
-nieuwsartikel.php
-reactie.php
| Gebruikers
- user.php
- privebericht.php
?>
Deze manier gebruik ik nu en vind ik zelf heel fijn. Maar het is een beetje je eigen manier.
Gewijzigd op 09/05/2012 09:08:38 door Bas van de Steeg
Een andere reden is dat in een echt OOP omgeving je vaak niet voor elke pagina elke class nodig hebt. Als je dus alles in hetzelfde bestand plaatst laad je veel overbodige code in. Als je elke class zijn eigen bestand geeft dan laad je alleen dat wat je daadwerkelijk nodig hebt.
Nog een voordeel. Stel je hebt een class voor een bepaalde taak, zeg het inlezen van je teksten. Nu wil je alleen je website in een andere taal gaan zetten. Wat je kan doen (er zijn natuurlijk veel meer mogelijkheden, maar als voorbeeld) is voor elke taal een dezelfde class gebruiken, maar met een andere implementatie. Dus zelfde naam van de class, zelfde methodes, maar met de teksten in verschillende talen. Je hoeft dan alleen bij de include een ander bestand aan te roepen, de rest van je code (de hele code!) kan gelijk blijven. Als je alle classes in hetzelfde bestand stopt kan dit niet.
Uitzonderingen daargelaten: elke class in een ander bestand. Ga niet voor 'makkelijk', ga voor 'goed'.
Allemaal redenen om mijn manier te gebruiken:)
../ gaat namelijk terug naar je root, ./ gaat 1 folder omhoog. Mijn httpdocs folder ziet er als voobeeld zo uit als ik test.
| httpdocs
- Test website 1 (niet de originele naam uiteraard!)
- Test website 2 (niet de originele naam uiteraard!)
- Test website 3 (niet de originele naam uiteraard!)
Dus i.p.v. dat ../ terug gaat naar de root van Test website 1, gaat hij terug naar httpdocs.
Ik raad aan om dan een folder class te maken en daarin bijvoorbeeld het volgende te doen.
| Class
- nieuws.nieuwsartikel.php
- nieuws.reactie.php
- gebruiker.user.php
- gebruiker.privebericht.php
Dit komt op het zelfde neer, alleen vermijd je subfolders. Alles is toch gecatagoriseerd en duidelijk.
TIP: Als je dus niet bestanden eindigd met .class.php, zet dan bovenaan in het script een comment waar je aangeeft dat het een class betreft. Dit moet uiteraard duidelijk zijn voor mensen die de code zien, echter voor wat beginners in OOP kan het zonder duidelijke comment wat onduidelijker zijn
Gewijzigd op 09/05/2012 10:14:38 door Chris PHP
Bas van de Steeg op 09/05/2012 10:02:48:
Allemaal redenen om mijn manier te gebruiken:)
Eens, gaat verder op jouw manier.
Chris NVT op 09/05/2012 10:10:05:
@Bas, nee ik zou jou manier niet aanraden. Als ik ergens een hekel aan heb is om folder in folder in folder te gebruiken. Je includes worden zo lang en het gebruik van ./ en ../ werkt ook niet overal even goed en zuiver. Voornamelijk als je zelf localhost test en dus sites in verschillende folders in de root zet krijg je hier al problemen.
Dat kan je oplossen met ofwel een autoload functie, ofwel je include path goed te zetten. Dit laatste kan in de ini, of gewoon via een functie aan het begin van je script.
Ik zeg dit wil vaker maar mijn motto is houdt het simpel waar het kan. Dus i.p.v. een rij subfolders te maken, kun je gewoon mijn voorbeeld aanhouden wat op precies het zelfde neerkomt.
Waarom zou je een losse folder maken voor 1 of 2 bestanden? Soms is er natuurlijk maar 1 class bestand voor een bepaalde actie. Ook met het los bewerken van eventuele classes, wordt je alleen al gek van je FTP client om door heel die folders heen te klikken waar je maar 1 bestandje hoeft te vervangen.
Tevens ben ik geen voorstander om zo php ini's te gaan aanpassen, vooral niet omdat je dan dus telkens conflicten krijgt met andere sites. Je hebt maar 1 ini voor je php installatie, niet 1 voor elke 'folder/site' in je httpdocs.
Over die ini, daarom geef ik ook de mogelijkheid dat je het in php zelf kan doen, runtime. Maar dit komt eigenlijk ook weer samen met het vorige punt. Het ligt er net aan hoe groot je project is. Is het klein, dan is er geen noodzaak om meerdere folders/subfolders te hebben en is het ook meteen niet meer nodig om je include path aan te passen. Is het groot dan heb je het mogelijk wel nodig, maar dan heb je waarschijnlijk ook een ander hosting pakket en kan je dus makkelijk(er) de php ini file aanpassen.
Echter programmeer, ontwerp en test je in je localhost waar het 'include' probleem dan te pas komt. De grote van de site is hier dan niet echt van toepassing. Ik ben vaak met verschillende website's bezig per week. Aangezien ik niet telkens mijn root leeg maak en dan de site erin zet heb ik daar last van.
Uiteraard kun je dat natuurlijk wel doen, echter draai ik ook een 'ontwikkel' webapp die ik zelf gemaakt heb. Hier heb ik wat kleine handigheden in gemaakt zoals bijvoorbeeld de md5 laten zien van een wachtwoord wat ik intype. Dit is handig als je voor kleinere site's een config file hebt met login gegevens voor 1 account.
Ik zit dus altijd met subfolders in mijn root op de localhost.
Als de TS alleen dit project in de root heeft staan, lijkt me dat er geen problemen met ../ zal zijn.
Uberhaupt heb ik altijd nog twee bestandjes: een bestand met daarin gedefinieerd of het een test omgeving is of niet en een bestand met daarin de regels voor het includen. Op basis van de test omgeving ja of nee kan je dus eenvoudig bepalen hoe er geinclude moet worden. Daarmee kan je dan dus weer ondervangen dat de situatie op test en productie omgeving verschillend is, zonder dat je elke keer handmatig dit moet aanpassen.
Die include je dan (in de test omgeving) in he index.php zodat hij daar de include aanpast in de ini? Dus telkens als ik een site in mijn test omgeving open hij de ini aanpast?
(en false op de productie server)
En dan in mijn common.inc.php heb ik:
Code (php)
In de index.php include in beide bestanden waardoor het altijd goed gaat, zonder dat ik bij het overzetten van de bestanden van test naar productie ooit nog iets hoef te doen. Die TEST constante gebruik ik verder ook nog om bijvoorbeeld mijn database gegevens in te laden. In de test omgeving staan die gewoon hardcoded in het bestand, maar in de productie omgeving moet ik die op een andere manier laden. Ook dat gaat dus automatisch meteen goed.
Ooit van namespaces, autoloader en config file gehoord? Ik heb bovenstaande problemen nooit.
Als mijn site test1 heet en die staat in de www, dan wordt dus zo?
Autoloader gebruik ik wel, maar dat werkt alleen als je ofwel het pad uit de class naam kan halen, ofwel alle classes binnen het include path hebt staan (wat ik dus op de productie server wel heb en op de ontwikkelomgeving als bovenstaand oplos).
Config file heb ik wel, maar niet specifiek voor dit punt, omdat bovenstaand bij mij prima werkt.
Maar omdat we toch bezig zijn, leg jouw oplossing er naast. Daar kunnen we ongetwijfeld ook iets van leren.
Toevoeging op 09/05/2012 11:15:17:
@Chris
Nee, ik zou wel het huidige include path blijven gebruiken. Dus:
Zo voeg je een extra pad toe, maar gooi je niet weg wat er al in de ini stond.
Ik plaats alle klassen in 1 map (lib of src) en die dan weer onderverdelen in categoriën (namespaces) en daar weer klassen in plaatsen. Zo kun je met een Autoloader klasse heel mooi alleen klassen ophalen die je ook echt gebruikt. Een beetje zo:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?php
// in je bootstrap file staat alles wat je minimaal nodig hebt voor een pagina aanroep
// denk aan variabele/constanten definiëren, autoloader registreren, enz.
require_once __DIR__.'/src/bootstrap.php';
// laad src/WouterJ/Post/Post.php
$post = new WouterJ\Post\Post();
// laad src/WouterJ/User/User.php
$post->setAuthor(new WouterJ\User\User('wouter'));
// laad src/WouterJ/Parser/YamlParser.php
$parser = new WouterJ\Parser\YamlParser();
?>
// in je bootstrap file staat alles wat je minimaal nodig hebt voor een pagina aanroep
// denk aan variabele/constanten definiëren, autoloader registreren, enz.
require_once __DIR__.'/src/bootstrap.php';
// laad src/WouterJ/Post/Post.php
$post = new WouterJ\Post\Post();
// laad src/WouterJ/User/User.php
$post->setAuthor(new WouterJ\User\User('wouter'));
// laad src/WouterJ/Parser/YamlParser.php
$parser = new WouterJ\Parser\YamlParser();
?>
Dit is naar mijn mening een erg mooie structuur die ook in frameworks als Zend en Symfony gebruikt worden.
Het is ook makkelijk kopiëren. Stel ik wil die YamlParser ook in een ander project gebruiken, dan hoef ik alleen de src/WouterJ/Parser/YamlParser.php bestand te kopiëren.
Voor erwin:
Namespaces zijn bijv. WouterJ_Post_Post(), hierbij is de namespace WouterJ_Post (dus de hoofdnamespace WouterJ en de subnamespace Post). PHP5.3 en hoger bied een support voor namespaces. Hierbij kun je WouterJ\Post\Post() gebruiken. Wat extra's dingen bij deze support:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
# src/WouterJ/Post/Post.php
// geef aan dat we hier in de WouterJ\Post namespace zitten
namespace WouterJ\Post;
// Deze klasse zit nu in de WouterJ\Post namespace
class Post
{
...
}
?>
# src/WouterJ/Post/Post.php
// geef aan dat we hier in de WouterJ\Post namespace zitten
namespace WouterJ\Post;
// Deze klasse zit nu in de WouterJ\Post namespace
class Post
{
...
}
?>
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
# index.php
// definieer een shortcut voor WouterJ\Post met de naam WJpost
use WouterJ\Post as WJpost;
$post = new WJpost\Post(); // dit is dus eigenlijk WouterJ\Post\Post()
?>
# index.php
// definieer een shortcut voor WouterJ\Post met de naam WJpost
use WouterJ\Post as WJpost;
$post = new WJpost\Post(); // dit is dus eigenlijk WouterJ\Post\Post()
?>
Of een andere (handigere) manier van use:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
# index.php
// hierbij geven we de use functie de namespace + klassenaam mee
// telkens als we nu de Post klasse gebruiken wordt deze namespace
// aangeroepen
use WouterJ\Post\Post;
$post = new Post(); // wordt WouterJ\Post\Post()
?>
# index.php
// hierbij geven we de use functie de namespace + klassenaam mee
// telkens als we nu de Post klasse gebruiken wordt deze namespace
// aangeroepen
use WouterJ\Post\Post;
$post = new Post(); // wordt WouterJ\Post\Post()
?>
Het makkelijke hiervan is dat elke functie zijn eigen scope krijgt. Hierdoor kun je bijv. 2 klassen hebben met dezelfde naam zonder dat ze elkaar raken.
Tevens kun je via namespaces makkelijk een autoloader maken, zie bijv. de PSR-0 standards + autoloader.
Ook zitten we nu in het WouterJ project. Maar stel nu dat we dit in een ander project gaan gebruiken dan hoeven we in de index alleen maar die WouterJ te veranderen in de nieuwe projectnaam bij die use functies en dan wordt er in het hele bestand meteen de juist namespaces gehanteerd.
Gewijzigd op 09/05/2012 11:32:44 door Wouter J