OOP gedachtengang

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Senior Javascript developer

Functie Het platform is gebouwd in een moderne JavaScript stack, die gebruikt maakt van:  React.js  Redux  TypeScript  Node.js  Google Cloud functions (node.js)  Semantic UI Alle code wordt getest en beoordeeld door collega developers. De continuous integration pipeline maakt het mogelijk om elke dag waarde te leveren aan hun klanten. Het ontwikkelproces is pragmatisch en gebaseerd op Scrum. Wat je zult doen: Ten eerste kun je nadrukkelijk jouw eigen stempel drukken op de technologie, het product en de cultuur van het bedrijf. Je bent bezig met het uitwerken van de architectuur van nieuwe functionaliteiten op

Bekijk vacature »

SQL Database ontwikkelaar

Functie omschrijving Wil jij meewerken aan het creëren van slimme software om magazijnen als een geoliede machine te laten lopen? Wij zoeken een zorgvuldig persoon, iemand die niet snel de hand omdraait voor complexe algoritmes. Denk jij dat jij de SQL ontwikkelaar bent die wij zoeken? Lees snel verder en wie weet zitten we binnenkort samen aan tafel! Jouw werkzaamheden zullen er als volgt uitzien: Je houdt je bezig met het ontwerpen en ontwikkelen van MS SQL server databases, dit doe je met T-SQL als programmeer laag. Je gaat aan high-end software oplossingen werken, dit doe je voor de optimalisatie

Bekijk vacature »

Medior Java developer (fullstack)

Wat je gaat doen: Of beter nog, wat wil jij doen? Binnen DPA GEOS zijn we dan ook op zoek naar enthousiaste Java developers om ons development team te versterken. Als Java developer werk je in Agile/Scrum teams bij onze klanten en daarbij kun je eventueel ook andere ontwikkelaars begeleiden in het softwareontwikkelproces. Verder draag je positief bij aan de teamgeest binnen een projectteam en je kijkt verder dan je eigen rol. Je gaat software maken voor verschillende opdrachtgevers in jouw regio. Je bent een professional die het IT-vak serieus neemt en kwaliteit levert. Je leert snel vanwege je diepgaande

Bekijk vacature »

Oracle APEX developer

Wat je gaat doen: Als Oracle APEX ontwikkelaar bij DPA werk je samen met collega’s aan de meest interessante opdrachten. Je zult je ervaring met SQL, PL/SQL, JavaScript, HTML en CSS inzetten om wensen van opdrachtgevers te vertalen naar technische oplossingen. Je werk is heel afwisselend, omdat DPA zich niet beperkt tot een specifieke branche. Zo ben je de ene keer bezig binnen de zorgsector, de andere keer is dit bij de overheid. Wat we vragen: Klinkt goed? Voor deze functie breng je het volgende mee: Je hebt een hbo- of universitaire opleiding afgerond Je hebt 2 tot 5 jaar

Bekijk vacature »

C# .NET Software Ontwikkelaar

Functie omschrijving C# .NET Developer gezocht. Ben jij een full stack developer die op zoek is naar een nieuwe uitdaging binnen een leuk snel groeiend bedrijf? Lees dan snel verder! Wij zijn op zoek naar een Developer met ervaring op het gebied van .NET die een organisatie in de regio Arnhem gaat versterken. Jij gaat je binnen dit bedrijf vooral bezighouden met het verbeteren van de functionaliteiten van hun dataplatform. Samen met andere ontwikkelaars denk je mee in oplossingsrichtingen, architectuur en nieuwe technologieën. Als C# .NET Developer binnen dit bedrijf houd je je niet alleen bezig met het verbeteren van

Bekijk vacature »

.Net developer

Sogeti is een organisatie met een goede werksfeer en zo min mogelijk hiërarchische verhoudingen. Ga je bij ons als .Net Developer aan de slag? Dan werk je dagelijks met collega’s aan de mooiste IT-projecten. Als developer bouw je in DevOps teams aan enterprise applicaties, nieuwe IOT, Chatbots of AI oplossingen. Deze snelgroeiende groep collega’s krijgt energie van hun vak en dat merk je op de werkvloer. Natuurlijk krijg jij de mogelijkheid je te certificeren in dit vakgebied. We organiseren regelmatig technische Meet-ups en doen we veel aan kennisdeling. Mede hierdoor zij wij vorig jaar Microsoft Partner of the year geworden.

Bekijk vacature »

Junior Software Developer C# Verhuursector Verhuur

Samengevat: Wij ontwikkelen en leveren softwaresystemen voor de logistieke sector en de verhuursector. Ben jij geschikt als Junior Software Developer? Heb je ervaring met Delphi? Vaste baan: C# Software Developer Logistiek HBO €2.500 - €3.900 Deze werkgever is een software ontwikkelaar, gericht op software voor de logistieke sector. Deze werkgever heeft eigen producten ontwikkelen en leveren ook maatwerk. Ons bedrijf kent een boeiende en inspirerende werkomgeving met een open cultuur en mogelijkheden voor je verdere ontwikkeling. Bij bij hun werk je aan onze eigen bedrijfsapplicaties. Je ontwikkelt met ons de meest nieuwe software. Wij blinken uit als het gaat om

Bekijk vacature »

SQL Developer

Functie omschrijving Altijd al willen werken bij een snelgroeiend bedrijf, actief in de logistieke sector? Dit is je kans! Ik ben op zoek naar een ervaren SQL Developer in de omgeving Tilburg. Dit bedrijf is gespecialiseerd in in de ontwikkeling van software en maatwerk oplossingen voor het automatiseren van logistieke processen. Klanten zijn o.a. BOL en andere grote distributiecentrums. Jouw taken worden vooral: Verantwoordelijk voor ontwikkelen van stored procedures, voor snelle afhandeling van data; Optimalisatie van de SQL query's en T-SQL query's; Jij gaat je bezig houden met ontwerpen, ontwikkelen en optimaliseren van de MS SQL Databases; In deze functie

Bekijk vacature »

Belastingdienst - Freelance Senior Cobol Applicati

Startdatum: 01.06.2023 Richttarief: €65,00 - €75,00 Duur van de opdracht: 7 maanden Uren per week: 36 Taal: Nederlands vereist! Gelieve in het Nederlands te solliciteren. Functieomschrijving: In de applicatie ETM zijn nu de inningsvoorzieningen voor ongeveer 25 aangifte- en aanslagmiddelen opgenomen. ETM is een extern aangeschafte service en het huidige contract met leverancier Oracle loopt af op 31-12-2022. Het programma uitfaseren ETM heeft als doel om vervanging te realiseren waarmee alle nu in gebruik zijnde ETM ondersteuning wordt overgenomen in nieuwe Inningsvoorzieningen om de continuïteit van de inningsprocessen te waarborgen. Eén van de inningsvoorzieningen die voor het einde van 31-12-2022

Bekijk vacature »

3D BIM Add-on Developer

As a 3D BIM add- on developer at KUBUS, you will develop add-ons (called BCF- Managers) to the leading building information modeling (BIM) programs Revit, Navisworks, Archicad, AutoCAD and Tekla Structures. BCF Managers enable data transfer between BIM software and BIMcollab. You will work on both the front- and the back-end. As a software company, KUBUS is in a unique position. We build our own products that are used by tens of thousands of users worldwide. Our company is just the right size: big enough to make a real impact in the market, but small enough that as an individual

Bekijk vacature »

Front-end Angular developer

Functie In jouw rol als Front-End developer werk je samen met de backend developers om middels tweewekelijkse sprints het platform naar een hoger niveau te tillen. Hiernaast heb je affiniteit met data en werk je graag samen met het team om de gegevensintegriteit en -beveiliging te waarborgen, om ervoor te zorgen dat de gebruiker wereldwijd de beste SaaS-services heeft. Deze organisatie heeft meer dan 100 mensen in dienst, waarvan er 45 in Nederland werken. Het ontwikkelteam bestaat uit 10 mensen en is verdeeld in 2 scrumteams. Het eerste team bestaat uit Java en Scala ontwikkelaars. Het tweede team, waar jij

Bekijk vacature »

Senior .NET Ontwikkelaar

In het kort Als Senior .NET ontwikkelaar ga je binnen onze business unit Transport en Logistiek aan de slag met complexe maatwerk software voor bedrijf kritische systemen binnen de technische automatisering. Denk bijvoorbeeld een IoT-oplossing voor de logistieke sector waarbij we van ruim 200.000 machines de telemetrie en events verwerken. We zijn actief in de distributielogistiek, havenlogistiek (denk aan ECT) en productielogistiek. Naast C# en .NET Core maken we ook gebruik van Azure technologie. En als trotse Microsoft Gold Partner leren we graag van en met jou. Wil jij jezelf blijven ontwikkelen binnen de technische automatisering met .NET, dan gaan

Bekijk vacature »

Lead C++ Developer

De rol van Lead C++ Developer Als Lead C++ developer bij KUBUS word je verantwoordelijk voor het implementatie design van requirements en de software architectuur van de desktop applicaties van BIMcollab, ons platform voor 3D model-validatie en issue-management bedoeld om de kwaliteit van 3D design-modellen voor gebouwen te verbeteren. Betere 3D modellen leiden tot betere gebouwen, dus zo draag je bij aan verduurzaming van de gebouwde omgeving met slimmer gebruik van materialen, minder verspilling en energie-efficiënte gebouwen. Een goede gebruikerservaring staat bij ons hoog in het vaandel; we gaan in onze ontwikkeling voor innovatie en kwaliteit. In je rol als

Bekijk vacature »

Fasttrack learning & development voor Java dev

Wat je gaat doen: Wij zoeken enthousiaste en ambitieuze junior en medior ontwikkelaars die toe zijn aan de volgende stap in hun carrière. Wij helpen je op je pad naar senior ontwikkelaar door ons fasttrack learning en development programma. Na een kort en intensief programma ga jij aan de slag bij klanten van DPA. Daarnaast krijg je veel ruimte om je te ontwikkelen als persoon en als specialist. De eerste maand gaan we aan de slag om je certificeringen te behalen waaronder OCP (Oracle Certified Professional). Daarnaast nemen we een deepdive in Spring Boot. Ook laten we je kennismaken met

Bekijk vacature »

Database Developer

Functieomschrijving Heb jij ongeveer 3 jaar ervaring als Database Developer met MS SQL of een vergelijkbare database? Wil jij werken voor een gewaardeerde werkgever in regio Tilburg waar jij de tijd en ruimte krijgt jezelf te ontwikkelen? Lees dan snel verder! Hoe ziet jouw takenpakket eruit? Je houdt je bezig met het creëren en bouwen van MS SQL server databases; Je gaat projecten vanaf het begin tot het eind begeleiden. Je sluit aan bij meetings met klanten om hun processen in kaart te brengen. Vervolgens voer jij het project uit en zorgt dat dit zo goed mogelijk verloopt; Je werkt

Bekijk vacature »

Pagina: « vorige 1 2 3 4 5 volgende »

Jasper DS

Jasper DS

12/06/2012 19:02:12
Quote Anchor link
index.php komt dus in de map /testApp/
en mijn User class in /testApp/User.php?

De autoloader klinkt nu nog wel erg ingewikkeld! :s
 
PHP hulp

PHP hulp

24/04/2024 03:34:15
 
Wouter J

Wouter J

12/06/2012 19:29:15
Quote Anchor link
Het is in feite heel simpel. Als je dit doet:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$user
= new Admin('Jasper');
?>

Dan gaat PHP opzoek naar de User klasse, he balen, die kan hij niet vinden. Dan kijkt hij of er autoloaders zijn geregistreerd en roept hij die aan. Deze autoloader laad vervolgens het bestand dat bij die klasse hoort en dan is PHP blij, hij kan nu wel de klasse vinden.

Dat geeft als voordeel dat alleen klassen die je gebruikt worden geincluded, ik hoef niet uit te leggen waarom dat beter is hoop ik.

Nou, nu hebben we nog 1 probleem: Hoe kunnen we de nou weten welke klasse we moeten laden aan de hand van de naam?

We kunnen dit doen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
function myAutoloader($className)
{

    switch ($className) {
        case
'User' :
            require '/lib/User.php';
            break;

        case
'Admin' :
            require '/lib/Admin.php';
            break;
    }
}

?>

Maar nu moeten we per klasse, interface of wat dan ook, hier een case bij voegen. Dat is natuurlijk helemaal niet flexibel en wat niet flexibel is is geen OO.

Dus we moeten een andere manier zien te vinden. Nou heel simpel. De naam van de klasse komt overeen met de naam van het bestand in de lib map:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
function myAutoloader($className)
{

    require '/lib/'.$className.'.php';
}

?>

Lijkt zeer goed toch?

Maar stel je nou eens voor dat je een project hebt meer 50 klassen. Dat is toch totaal onoverzichtelijk om deze allemaal in de /lib/ map te zetten? Je zou ze moeten groeperen. Alles wat met Personen te maken heeft in de /lib/Person/ map en alles wat met berichten te maken heeft in de /lib/Post/ map.

Alleen hoe kunnen we dat nou uit de naam halen? Dan kun je gaan werken met underscores in je klassenaam, elke underscore geeft dan een map aan:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
function myAutoloader($className)
{

    $path = str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
    require '/lib/'.$path;
}

?>

Wat doet deze functie? Deze replaced alle _ in de klassenamen met een constante genaamt DIRECTORY_SEPARATOR die is op windows \ en op de mac en linux /. Dus wat gebeurd er dan:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
// laad /lib/Person/User.php
$author = new Person_User('Jasper');

// laad /lib/Post/ArticleMapper.php
$articleMapper = new Post_ArticleMapper();

// laad /lib/Post/blogPost.php
$post = new Post_BlogPost('title', 'foobar lorem ipsum', $author);

$articleMapper->create($post);

$comment = array(
    [
0] => array(
        // doet niks, want User file is al ingeladen
        'author' => new User('Wouter'),
        '...',
    ),
);

?>


Hoop dat dit het een en ander duidelijk maakt.
 
Jasper DS

Jasper DS

14/06/2012 22:02:49
Quote Anchor link
Volgende situatie, ik ben bezig aan mijn classe VisitReport. Nu hoort bij elk rapport natuurlijk een User. Hoe koppel ik mijn rapport nu aan mijn User class?

Wat ik er van denk:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class VisitReport
{
    protected $id;
    protected $user;
    protected $client;
    protected $company;
    protected $email;
    protected $postalCode;
    protected $city;
    protected $contactPerson;
    protected $visitDate;
    protected $turnOver;
    protected $comment;
    protected $action;
    protected $nextVisit;
    protected $send; // Boolean -> 1 -> sent
        
    public function getUser()
    {

    $userMapper = new UserMapper($db);
    $userMapper->getById($this->user)
        return $this->User;
    }
}

?>
 
Wouter J

Wouter J

14/06/2012 22:14:48
Quote Anchor link
Jasper, nee. Je moet dan gaan werken met een simpele vorm van dependency injection.

Je zal de property $user moeten vullen met een user klasse die bij dat report hoort. Dat doe je door de user klasse mee te geven aan de constructor:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?php
class VisitReport
{
    protected $id;
    protected $user;

    public function __construct(User $user)
    {

        $this->user = $user;
    }
}

?>

In $this->user zit nu gewoon een User klasse. We kunnen dus alle methods aanroepen van die User klasse. Bijv:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class VisitReport
{
    protected $id;
    protected $user;

    public function __construct(User $user)
    {

        $this->user = $user;
    }


    public function foo()
    {

        $this->user->getName();
    }
}

?>

Dit is natuurlijk een hele domme foo method, maar het gaat even om het idee.

Hoe je deze VisitReport nu aanroept:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
$user
= new User('Jasper');

$report = new VisitReport($user);
?>
 
Jasper DS

Jasper DS

14/06/2012 22:24:08
Quote Anchor link
Nee! Man, nu weet ik waarom ik OOP wil leren! :D Haha, nog een vraagje over de autoloader.. Mijn classe noemt nu natuurlijk User_User (-> ../lib/User/User.php) maar dat is toch niet echt netjes?
 
Wouter J

Wouter J

14/06/2012 22:32:46
Quote Anchor link
Nee, dus kan je beter gaan werken met namespaces. Maar dat vond ik nog een stapje te ver voor je, laat je eerst maar even de basis van OOP onder de knie krijgen. Dan kunnen we verder stappen naar nieuwe technieken als namespaces en dingen die ze Design Patterns noemen (al gebruiken we stiekem al 2 design patterns).

En tja, User_User staat niet zo mooi. Maar je kan de map ook Person noemen. Dan plaats je daar alle persoonsgerelateerde klassen in, zoals Person_User; Person_Admin; Person_Visitor; Person_Guest; Person_UserMapper; Person_MapperInterface; Person_AdminMapper;
 
Jasper DS

Jasper DS

14/06/2012 22:43:35
Quote Anchor link
Ok, dan ga ik zo even verder.

Nog een klein vraagje over de constructor, jij zei enkele posten geleden dat je zo weinig mogelijk doet via de constructor maar alles via setters.. Hoe weet ik nu wat via de constructor en wat via een setter?
 
Wouter J

Wouter J

14/06/2012 22:51:39
Quote Anchor link
Quote:
jij zei enkele posten geleden dat je zo weinig mogelijk doet via de constructor maar alles via setters..

Dat kan ik bijna niet geweest zijn...

Via de constructor doe je de dingen die een object verplicht moet hebben. Via setters de dingen die je niet verplicht moet hebben.

Denk bijv. aan het id. Dat is makkelijk om via een setter af te handelen en niet via de constructor, want als je een object net aanmaakt heb je nog geen Id. Die krijg je pas in de DB.
 
Jasper DS

Jasper DS

15/06/2012 13:54:35
Quote Anchor link
Oke, duidelijk!

De code van mijn autoloader ziet er zo uit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
function autoLoader($className)
{

    $path = str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
    require '/lib/'.$path;
}


$classes = array('User_User', 'User_UserMapper');
foreach($classes as $className)
{

    echo autoLoader($className);
}

?>


is dat correct? En zet ik dat in autoLoader.php die ik op elke pagina include alsook in elke classe?
 
Wouter J

Wouter J

15/06/2012 14:53:00
Quote Anchor link
Nee, het moet zo:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php
function myAutoloader($className)
{

    // code
}

// geregistreer de functie myAutoloader als een autoloader
spl_autoload_register('myAutoloader');
?>


En nu kun je gewoon je gang gaan. Als je nu een klasse aanroept:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$user
= new Person_User();
?>

Dan denkt PHP, bestaat deze klasse? Zo ja, gebruik hem, zo nee: Oké, dan moeten we gaan zorgen dat hij wel bestaat. Vervolgens gaat PHP alle autoloaders langs om te kijken of die een bestand kunnen includen waardoor de klasse wel bestaat.

Dus regel 8 t/m 12 kunnen weg en plaats daar spl_autoload_register('autoLoader'); voor in de plaats en je kunt je uitleven.


Omdat dat allemaal een beetje vaag klink hier even een uitbeelding:
Afbeelding
Gewijzigd op 15/06/2012 15:25:00 door Wouter J
 
Jasper DS

Jasper DS

18/06/2012 17:38:45
Quote Anchor link
Prima wouter ik ben weer mee!

Ondertussen heb ik ook een classe gemaakt voor mijn VisitReport en natuurlijk een VisitReportMapper. Daarin heb ik de functies getById, getByUser, etc... allemaal geen probleem werkt goed. Maar dan komt er iets en ik weet niet goed hoe ik dat moet doen. Ik wil een functie maken getAll() -> gewoon alle berichten ophalen. Ik denk dat die in mijn VisitReportMapper moet maar ik ben niet echt zeker... Waar zou jij deze plaatsen?

Alvast bedankt!
 
Wouter J

Wouter J

18/06/2012 19:56:26
Quote Anchor link
Dat denk je goed.

Je kan toch moeilijk aan 1 enkel object vragen om alle objecten op te halen. Dat is niet mogelijk.

VisitReport is een object die gegevens vasthoudt. Het heeft dus setters en getters, maar meer niet. Het vasthouden van gegevens is zijn taak.
VisitReportMapper is een object die alles regelt tussen DB en object. Als je dus alle VisitReports uit de db moet hebben gebeurd dat met deze mapper.
 
Jasper DS

Jasper DS

18/06/2012 21:06:09
Quote Anchor link
dus:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
$report
= new VisitReportMapper();
$allReports = $report->getAll(); // returned dus een array ?

foreach($allReports as $visitReport)
{

    echo $visitReport['veld'];
}


?>


?
 
Wouter J

Wouter J

18/06/2012 21:44:37
Quote Anchor link
Nee, want als het goed is is $visitReport een class en geen array, dus $visitReport->getVeld() (want public properties moet je niet gebruiken).

En VisitReportMapper::getAll() zou een array met VisitReport objects moeten returnen. Dat doe je door uit de DB alles te selecteren, je hebt dan een mooie assoc array. Vervolgens gebruik je array_map met als callback de populate method, zodat er van elk array item een mooi object wordt gemaakt.
 
Jasper DS

Jasper DS

18/06/2012 22:39:10
Quote Anchor link
dus dan heb je evenveel VisitReport objecten als er rapporten zijn?

$array[1] = new VisitReport();
$array[2] = new VisitReport();

Dat gebeurt binnen de code?
 
Wouter J

Wouter J

18/06/2012 22:51:51
Quote Anchor link
Ja. Je doel met OO is dat je straks alles in objecten hebt, dus ALLES is een object, en dat je dan alle maar
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$app
= new Application();
$app->run();
?>

hoeft te doen.

Laat je echt niet afschrikken door het gebruik van heel veel klassen. Dat is heel normaal en het is bijna hoe meer klassen hoe beter, maar je kan natuurlijk ook overdrijven.

Besef wel dat je niet $array[1] = new VisitReport(...); gaat doen, maar gewoon veel makkelijker gaat werken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class VisitReportMapper
{
    // ...

    public function getAll()
    {

        $visitReports = // get all from db;

        return array_map(array($this, 'populate'), $visitReports);
    };


    // ...
}
 
Niels K

Niels K

21/06/2012 12:53:03
Quote Anchor link
Hoi Jasper,

Aan de hand van je vragen op Facebook / MSN / Twitter van mijn kant ook even een reactie.

Inleiding:
De meeste mensen hier op PHPhulp weten dat ik een Zend Framework programmeurtje ben. In deze post probeer ik echter objectief te blijven. Dat betekend dat ik me VOORAL bij de feiten wil houden. Dat betekend dus niet dat ik mijn mening niet op tafel leg.

Tot slot, succes met lezen ;-)

Kiezen van een framework:
Om met de deur in huis te vallen. het kiezen van een framework. Oh? Is dat niet een beetje te snel? NEE! Ik ben van mening dat je op dit moment klaar bent voor een framework. Je bent op dit moment (als ik alles goed gelezen heb) bezig met het schrijven van een (klein / eigen) custom framework. Je hoeft niet het wiel opnieuw uit te vinden.

Maar goed, wat voordelen / nadelen van een eigen framework op een rijtje:

Voordelen:

- Het scheelt veel tijd aangezien je alle onderdelen NIET hoeft te bouwen.
- Wanneer je met gevorderde programmeurs werkt scheelt een framework ook veel tijd. (Je hoeft namelijk je eigen framework niet meer uit te leggen, aangezien de gevorderde programmeurs wel aan elk bekend framework gesnuffeld heeft)
- Er zit een community achter dus gevonden bugs worden gauw opgelost.
- Kwaliteit van de code is hoger omdat er veel mensen naar kijken.

Nadelen:

- Frameworks zijn meestal groot dus het duurt even voordat je helemaal weet hoe een framework in elkaar steekt.
- Limitatie. Dingen gaan misschien net iets anders dan dat je gewend bent.
- In sommige gevallen veroorzaakt het een tunnelsyndroom. (In mijn ogen ben je dan niet een gevorderde PHP programmeur)

[note]Als mensen nog meer voordelen / nadelen hebben, voeg ze toe ;-)[/note]

Goed, tijd om in te zoomen:

Ik ga twee (verschillende) frameworks behandelen. (Zend, Symfony)

Zend Framework:

Zend Framework is een Object Georiënteerd MVC (web) framework gebaseerd op PHP 5.

Wat is nu precies het MVC?

Simpelweg: Programmeren met het MVC pattern scheidt je applicatie in drie delen:

1: Het model
2: De view
3: De controller

Model:
Kort gezegd representeren de models de data van de applicatie.

De view:
Kort gezegd maakt de view een presentatie van de model gegevens.

De controller:
Kort gezegd handelen de controllers de requests van de gebruikers af.

Een afbeelding van een standaard MVC request

Afbeelding

Stel jij zit op een webshop en je klikt op een detail pagina op de button bestellen. Wat gebeurd er dan precies?

1: Jouw browser maakt een request naar de WEB server
2: De dispatcher van Zend Framework controleert de URL van het Request en geeft het request door aan de juiste controller.
3: De controller voert de applicatie logica uit. Bijvoorbeeld: Hij controleert of je bent ingelogd. Want als je niet ingelogd bent kan je niet bestellen.
4: De controller gebruikt één of meerdere modellen om toegang tot de applicatie data te krijgen. (Meestal representeert een model een database tabel, maar dit kan net zo goed een LDAP repository zijn)
5: Zodra de controller zijn kunstjes uitgevoerd heeft wordt het tijd voor het parsen van de data naar de view. De view zorgt voor de presentatie van de data aan de gebruiker. (Views in Zend Framework zijn meestal van HTML format, maar dit kunnen net zo goed XML bestanden of een JSON objecten zijn)
6: Als de view alle data van de controller verkregen en verwerkt heeft wordt de output naar de browser gestuurd.

Heel simpel dus. Wat je echter wel heel goed moet onthouden is, dat dit bij ELK REQUEST gebeurd. Dus elk request volgt dit basispatroon.

Tijd om in te zoemen op de models. Echter lees eerst dit eens: klik. Wil je nog meer informatie over het MVC? Lees dan dit stukje eens.

Models:

Eerder werd je al iets uitgelegd over Mappers en (in tegenstelling van wat veel mensen denken) kan je die ook met Zend Framework netjes blijven gebruiken. Alleen Zend Framework heeft er nog een aantal patterns omheen gebruikt.

Allereerst maakt Zend Framework gebruik van het Table Data Gateway pattern om connectie te maken met jouw data source. Dit principe hebben ze vertaald naar een Zend_Db_Table object.

Voorbeeld van een Zend_Db_Table implementatie voor ons gastenboek:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php

class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abtract {
    protected $_name = 'guestbook'; // Naam van de tabel
}

?>


Oké? Leuk? Maar wat kunnen we er nu precies mee? Dit is een representatie van de (database) tabel guestbook. Het object erft van Zend_Db_Table_Abstract ook de volgende (belangrijke) methodes:

- select();

Hier mee kan je een select opbouwen. Voorbeeld:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php

$tableGuestbook
= new Application_Model_DbTable_Guestbook();

// Zend framework roept nu automatisch de init() methode van je nieuwe Application_Model_DbTable_Guestbook object aan.
// $tableGuestbook->init();

// Maak een select

$tableGuestbook->select(); // Retourneert een nieuw Zend_Db_Select object

?>


Omdat het een Zend_Db_Select object retourneert kan je op basis daarvan je select verder opbouwen. Bijvoorbeeld:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php

$select
= $tableGuestBook->select()
        ->
where('fieldname = ?', 'value')
        ->
where('fieldname = ?', 'value')
        ->
limit(10);

?>


Maar hoe krijg ik nu het resultaat als ik een Zend_Db_Select krijg? Daar heeft Zend_Db_Table_Abstract de methode fetchAll() voor geïmplementeerd. Laten we bovenstaand voorbeeld uitbreiden en het resultaat gaan fetchen.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php

$result
= $tableGuestbook->fetchAll(
    $tableGuestbook->select()
        ->
where('fieldname = ?', 'value')
        ->
where('fiedname = ?', 'value')
        ->
limit(10)
);


?>


Nu is de vraag, wat bevat $result nu? Daarvoor heeft Zend Framework een Zend_Db_Table_Rowset voor in het leven geroepen. $result bevat dus een Zend_Db_Table_Rowset object met daarin een data array met alle gevonden data op basis van de uitgevoerde select.

[note]Zend_Db_Table_Rowset[/note] implementeert (onder andere) ArrayAccess zodat je de data middels een foreach kan benaderen.

Maar goed, wat krijg je dan? Allemaal arrays met daarin de data. Zend Framework dacht slim te zijn en heeft het Row Data Gateway Pattern pattern geïmplementeerd.

Wanneer je dat wil gebruiken moet je wel eerst aan je Application_Model_DbTable_Guestbook object aangeven dat je het principe gaat gebruiken. Dat doe je door de volgende property toe te voegen.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php

protected $_rowClass = 'Application_Model_Guestbook';

?>


Wanneer je nu een selectie uitvoert zit er in het Zend_Db_Table_Rowset object allemaal Application_Model_Guestbook objectjes.

Maar goed, alles leuk en wel, ik dacht dat je in Zend Framework ook data mappers kon gebruiken? Is dat nu nog nodig na bovenstaand verhaal?

ZEKER! Wil je netjes programmeren? Maak dan gebruik van data mappers.

Zend:
A Data Mapper maps a domain object to the database


In ons geval betekent het dat ons object Application_Model_Guestbook naar de data source Application_Model_DbTable_Guestbook wordt "gemapt".

Ja leuk leuk al die termen / verhaaltjes / zinnetje, IK WIL CODE ZIEN!

Prima! Laten we beginnen met ons DbTable object en overgaan naar ons Row object en tot slot de Mapper die alles aan elkaar mapt.

Application_Model_DbTable_Guestbook:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php

class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract {

    protected $_name = 'guestbook';
    protected $_rowClass = 'Application_Model_Guestbook';

}


?>


Appliaction_Model_Guestbook:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

class Application_Model_Guestbook extends Zend_Db_Table_Row_Abstract {

    protected $id;
    protected $comment;
    protected $email;
    protected $date;

    public funtion __set($name, $value) {
        // Hier kan je controleren of een methode set$name() bestaat, zoja functie aanroepen en value zetten.
    }

    public function __get($name) {
        // Idem voor de __get methode
    }

    // Voeg nog wat meer methodes toe. Het gaat immers om het idee.
}


?>


Application_Model_GuestbookMapper:


Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php

class Application_Model_GuestbookMapper {

    protected $dbTable;

    public function setTable(Zend_Db_Table_Abstract $table) {
        // Zet table
    }

    public function getTable() {
        // retourneer table;
    }

    public function save(Application_Model_Guestbook $guestbook) {

        // Haal data op uit guestbook
        $data = array();

        // Insert in het DbTable object. (Zie bovenin mijn verhaal)
        $this->getTable()->insert($data);

        // Schrijf ook een oplossing voor update
    }

    public function fetchAll() {
        // Haal op basis van je table object het resultaat op en retourneer het.
    }
}


?>


Tot slot moet je bovenstaande logica nog koppelen. Daarvoor gebruiken we de GuestbookController. Die ziet er zo uit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

class GuestbookController extends Zend_Controller_Action {

    public function indexAction() {
        $guestbook = new Application_Model_GuestbookMapper();
        
        // Parse naar de view
        $this->view->entries = $guestbook->fetchAll();
    }
}


?>


Bovenstaand verhaal geeft een (klein) MVC request weer.

- Probeer de methodes af te maken. Ik heb ze expres niet helemaal ingevuld aangezien je er dan niets van leert. Om je nu moet gaan 'prutsen' ga je het principe snappen.

Tot slot, lees dit eens door. Het is niet altijd goed om gebruik te maken van een Zend_Db_Table_Row object. Kijk de uitleg van deze beste jongen eens: klik.

Symfony framework:

Allereerst wil ik je mededelen dat ik Symfony niet voor 100% onder controle hebt. (het verhaal is dus iets korter) Ik hoop dat Wouter of Pim mij kunnen aanvullen / verbeteren.

Om te beginnen is het Symfony framework GEEN MVC framework. Onderstaand plaatje legt dat mooi uit:

Afbeelding

Wat zijn dan de verschillende tussen MVC en HTTP? Het grote verschil ligt hem vooral hierin:

Een HTTP framework maak per Request een Request object aan. In dat Request object zitten alle globals die met een Request te maken hebben. Denk aan de volgende globals:

- $_SERVER
- $_POST
- $_GET
- $_SESSION

En zijn er vast nog wel meer op te noemen, maar het gaat om het idee.

In een controller behandeld je dit Request object. (Lees niet: Het request object is een eigenschap van de controller)
Vervolgens kan je in de controller een Response object teruggeven. In het Response object vind je alle data die jij in de controller behandeld / gemanipuleerd hebt.

Fabien Potencier zegt het volgende:

Quote:
I don't like MVC because that's not how the web works. Symfony2 is an HTTP framework; it is a Request/Response framework. That's the big deal. The fundamental principles of Symfony2 are centered around the HTTP specification.


Je moet dus scherp houden dat een MVC en een HTTP framework twee verschillende soorten frameworks zijn. Hoe je exact het verhaal van mij (over Zend Framework models) implementeert is mij niet duidelijk, maar ik hoop dat Wouter of Pim een voorbeeld wil plaatsen.

Wat zeer interessant is om te lezen is het volgende artikel: klik.

In dat atikel legt Fabien Potencier uit wat Symfony2 precies is, en waarom je het zou moeten gebruiken.

Tot slot,

Ik hoop dat je wat van mijn verhaal begrepen hebt, en als je vragen hebt hoor ik dat uiteraard graag.

Niels Kieviet
Gewijzigd op 21/06/2012 12:53:37 door Niels K
 
Ozzie PHP

Ozzie PHP

21/06/2012 12:55:28
Quote Anchor link
Ik heb het (nog) niet gelezen Niels, maar thumbs up voor zo'n uitgebreide uitleg!!
 
Wouter J

Wouter J

21/06/2012 13:46:54
Quote Anchor link
Zo Niels, mooi verhaaltje! (waar een discussie op twitter wel niet goed voor kan zijn)

Je zou kortweg kunnen zeggen dat een MVC framework 3 basis objecten heeft:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
Controller
  ^     ^
  |      \
Model   View


Een HTTP framework heeft dat niet. Een HTTP framework is opgebouwd uit 3 andere basis objecten:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
Request -> Controller -> Response

Die request heeft Niels al uitgelegd, vervolgens heb je de controller. Deze controller voegt de data van de bezoeker (het request) samen met de data van de website (kan bijv. de db zijn) en plaatst die vervolgens in de Response object. Deze response wordt teruggestuurd en die krijgt het browser te zien met allerlei informatie.
Dus i.p.v. de hele controller terug te sturen, met weer de data van de gebruiker en de data van de website en de data samengevoegd, krijg je nu alleen een request object terug met die data samengevoegd.

Je zal nu wel denken, hé waar is nou die model gebleven? Dat is nu het leuke, die is er niet in een HTTP framework!
Helluppie!! Kan ik dan helemaal geen database gebruiken?
Ja, natuurlijk wel. Er bestaan andere handige libaries die daarvoor zorgen. Symfony gebruik standaard Doctrine voor dit. En bied makkelijke mogelijkheden tot het gebruik van Propel.


Van doctrine/propel heb ik ook nog niet heel veel verstand, dus de code voorbeeldjes moeten maar gedaan worden door Pim of Kees (gebruikt ook veel doctrine).

Nu zal je wel denken, waar is dat view object gebleven? Ook dat regelt Symfony met Third-party libaries (libaries niet gemaakt door Symfony zelf, maar wel geïntegreerd in Symfony). Voor view gebruiken ze Twig. Twig is een template engine. Het grote verschil is dat Zend vol zit met View helpers, deze helpen je met het maken van je template en Symfony heeft Twig die geen helpers bevat, maar een eigen syntax. Zend heeft geen template engine, daar gebruik je gewoon HTML en PHP in je template. Bij symfony gebruik je alleen Twig en HTML in je templates

Edit:
Ik ben ik ook volledig eens met Pim zijn conclusie: Silex (micro frameworks) zijn veel beter te begrijpen en veel beter voor beginners en in dit geval misschien beter voor Jasper.
Gewijzigd op 21/06/2012 13:54:30 door Wouter J
 
Pim -

Pim -

21/06/2012 13:51:15
Quote Anchor link
Mooie post, Niels!

Ik weet alleen niet helemaal of ik het met je eens ben. Potencier zegt bijvoorbeeld ook:
Quote:
Because I really don't care whether Symfony2 is MVC or not. Probably because the MVC word is so overloaded and because nobody implements exactly the same MVC pattern anyway.
En daar sluit ik me graag bij aan.

Maar ik denk dat als je frameworks gaat presenteren, je twee betere keuzes had kunnen maken, namelijk micro-framework vs full-stack-framework. SF2 en ZF(2) zijn natuurlijk verschillend, maar lossen hetzelfde probleem (ik heb een volledige gereedschapskist nodig, zodat ik me alleen nog maar met domein-specifieke zaken bezig hoef te houden) op een vrij vergelijkbare manier op.

Micro-frameworks pakken het heel anders aan, zij geven jou de basis van routing en laten de rest voor je open om in te vullen met eigen code of met andere 3rd party code. Op zich volgt SF2 dit systeem ook (geen idee hoe dat met ZF werkt), je kan er in 1000regels een microframework van maken (Silex), maar de Standard Edition neigt toch wel naar het gebruik van alle features.

Als je dan full-stack-frameworks tegen micro-frameworks zet, denk ik dat nu, in deze situatie een micro framework meer geschikt is. En wel om de volgende redenen:
- Een micro-framework is in een dag te begrijpen, terwijl bijvoorbeeld SF2 zo groot en complex is dat dat veel langer duurt.
- Door het framework niet als black-box te zien, maar van elke regel te kunnen begrijpen wat er gebeurt, leer je het veel sneller beter te gebruiken en het gedrag aan te passen.
- Doordat sommige features (auth, ACL, views, persistence) niet aangereikt worden moet je zelf naar oplossingen op zoek. Zelfs als je deze dan niet schrijft leer je ze in die zoektocht ook beter begrijpen.

En als je dan eenmaal doorhebt wat er eigenlijk gebeurt, hoe je een router schrijft, hoe een datamapper werkt, wat het voordeel is van multiple view inheiritance, wat een veilig authenticatie systeem is en hoe je verschillende componenten mooi aan elkaar haakt (DI ;) ), dan kan je overstappen op een full-stack-framework en gebruik maken van de topkwaliteit code die dat vaak biedt en minder kwijt zijn aan de projecten zelf. Maar pas wanneer je weet wat je aan het doen bent :)
 

Pagina: « vorige 1 2 3 4 5 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.