pad ophalen in OOP

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 3 volgende »

Ozzie PHP

Ozzie PHP

19/04/2012 08:24:32
Quote Anchor link
Hallo mensen,

Wat is eigenlijk de mooiste/handigste/meest gebruikte manier om in een OOP MVC framwork een pad op te halen?

Ik kan me grofweg 3 scenario's voorstellen en ik ben benieuwd wat volgens jullie (de OOP experts!) de beste manier is.

1) Je maakt een Paths class en die stop je in de Registry. Als je een path nodig hebt, haal je de Paths class op uit de Registry. Zoiets:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
$paths
= new Paths();
Registry::set('paths', $paths);

// pad ophalen:
$paths = Registry::get('paths');
$path_library = $paths->library;
?>


2) Je gebruikt een singleton:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$paths
= Paths::getInstance();
$path_library = $paths->library;
?>


3) Je gebruikt een statische get method:

$path_library = Paths::get('library');

Wat vinden jullie? Misschien zijn er nog andere, betere methodes?

Alvast heel hartelijk dank voor jullie reacties!!!
 
PHP hulp

PHP hulp

11/08/2020 06:26:15
 
Niels K

Niels K

19/04/2012 10:51:42
Quote Anchor link
Hoi Ozzie,

Wat voor soort paden bedoel je? Kan je deze gewoon niet in je config bestand zetten?
Of snap ik je dan niet goed?

Niels
 
Ozzie PHP

Ozzie PHP

19/04/2012 11:10:57
Quote Anchor link
Bijv. een pad naar de library, of naar je controllers, models of views.

Stel je maakt een autoloader die een model moet inladen... dan heeft die autoloader een path naar de models nodig. Bijv. zoiets:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$model
= 'Some_Model';
include_once $paths->model . $model;
?>


Het lijkt me netjes om die paden via een class te benaderen, maar welke mainer is dan de beste?
 
Pim -

Pim -

19/04/2012 19:52:56
Quote Anchor link
Ik ben niet zo'n fan van singletons en global registries. Gebruik gewoon een DI container als variabele die je doorgeeft aan je controllers.

Maar wat veel mooier is in dit geval: autoloading!
Als je een goede autoloader gebruikt en deze goed configureert, zal je nooit meer een class-file hoeven te includen. Iedereen blij ;)
 
Ozzie PHP

Ozzie PHP

19/04/2012 20:29:10
Quote Anchor link
Hey Pim,

Dat autoloaden is geen probleem! Dat is ook hoe ik het nu doe... maar... in je autoload functie heb je ook een pad nodig, of misschien heb je ergens anders een pad nodig. Ik vind dat dan mooi als ik die uit een class kan ophalen... maar hoe?

Dat DI container heb ik wel eens doorgelezen, maar ik vind het vrij ingewikkeld. Vandaar dat ik dacht aan een van de 3 opties die ik zojuist noemde. Welke van die 3 is dan het beste? Wat zou jij doen?

(Mocht je uiteindelijk toch vinden dat zo'n DI container de enige juiste oplossing is, kun je dan via een klein codevoorbeeld laten zien hoe dat eruit zou zien op een zelfde manier zoals ik in de beginpost toepas?)
 
Pim -

Pim -

19/04/2012 20:43:56
Quote Anchor link
De makkelijkste manier en hoe het ook wordt toegepast in een de Sf2 Standard Edition is de volgende:
Maak een bestand autoload.php
Roep hierin de autoloader aan.

Simpel ;)

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
<?php

use Symfony\Component\ClassLoader\UniversalClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;

$loader = new UniversalClassLoader();
$loader->registerNamespaces(array(
    'Symfony'          => array(__DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'),
    'Sensio'           => __DIR__.'/../vendor/bundles',
    'JMS'              => __DIR__.'/../vendor/bundles',
    'Doctrine'         => __DIR__.'/../vendor/doctrine/lib',
));

$loader->registerPrefixes(array(
    'Twig_Extensions_' => __DIR__.'/../vendor/twig-extensions/lib',
    'Twig_'            => __DIR__.'/../vendor/twig/lib',
));
 
Ozzie PHP

Ozzie PHP

19/04/2012 20:48:40
Quote Anchor link
Ja... pfff.. ik ben niet zo technisch als jij!
Ik bedoelde eigenlijk of je dat DI gedoe kan uitleggen...

Dus zoiets als dit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
$paths
= new Paths();
Registry::set('paths', $paths);

// pad ophalen:
$paths = Registry::get('paths');
$path_library = $paths->library;
?>


alleen dan met DI...

Maar wellicht is dat te complex om 'even' uit te leggen.
 
Pim -

Pim -

19/04/2012 21:10:33
Quote Anchor link
Ahh zo.
Stel dat je idd een sort lib wil maken voor paden.
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
32
33
34
35
36
37
<?php
//Iets als dit
class PathRepository
{
    protected $paths = array();

    public function set($name, $path)
    {

        $this->paths[$name] = $path;
    }


    public function get($name)
    {

        return $this->paths[$name] ? $this->paths[$name] : null;
    }
}

// Je kan daar nog wat pad gerelateerde dingen bij doen, maar daar gaat t nu even niet om.

// In eoa bootstrap file gaat dan: (vrij uitgebreid)

$c = new Container();

$c->set('pathRepository.config.file', __DIR__.'/config/paths.ini'); // Een parameter
$c->set('pathRepository.config', function($c) {
    return parse_ini($c->get('pathRepository.config.file'));
});
// Een callback die bij aanroep de pathRepository.config.file parameter uit de container haalt en deze parsed en teruggeeft. Dit bestand is dan een ini bestand met
//name: path


$c->set('pathRepository', function($c) {
    $repo = new PathRepository();
    foreach($c->get('pathRepository.config') as $name => $path)
        $repo->set($name, $path);
    return $repo;
});

// Dit is je uiteindelijke service
// Er wordt dus een repository aangemaak en de entries uit de config worden ingesteld
// De repository wordt dan teruggegeven.

?>

Bitte

Toevoeging op 19/04/2012 21:11:50:

Als je dat dan wil gebruiken doe je ergens:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$container
->get('pathRepository')->get('ModuleABC');
?>
Gewijzigd op 19/04/2012 22:38:23 door Pim -
 
Wouter J

Wouter J

19/04/2012 22:01:21
Quote Anchor link
Ehh, pim. Het lijkt me dat regel 22 niet kan?
 
Pim -

Pim -

19/04/2012 22:38:00
Quote Anchor link
Eh ja, uit de losse pols maakt iedereen fouten. Ik heb het verbeterd.
 
Ozzie PHP

Ozzie PHP

19/04/2012 22:41:50
Quote Anchor link
Ik vind het nog steeds nogal ingewikkeld. Ik vraag me ook wel af wat nou het verschil is met bijv. zoiets als dit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php
$config
= 'pathsconfig.ini';
$paths = new Paths($config);
Registry::set('paths', $paths);

// pad ophalen:
$paths = Registry::get('paths');
$path_library = $paths->library;
?>


Dit is toch veel makkelijker? En komt volgens mij op hetzelfde neer?

(even ander offtopic vraagje... in jouw PathRepository class gebruikt je get() en set(). Gebruik je bewust niet de magic __set en __get?)
 
Pim -

Pim -

19/04/2012 22:52:43
Quote Anchor link
Ja, ik ben niet zo'n fan van magic methods. Dat vinden de IDE en de docs niet fijn, al is dat vrij persoonlijk.

Het verschil zit hem in een paar dingen:
De container zoals ik hem net gebruikte is lazy: wat niet nodig is wordt niet geladen.
Ook is het modulair: als ik nou het configuratiebestandje zou willen aanpassen of de paden uit de database wil halen, hoef ik alleen maar repo.config.path te veranderen of repo.config aan te passen en kan ik de repo callback zelf met rust laten.

De container gebruikt geen globals, nu lijkt dat misschien niet heel belangrijk, maar als je wil werken met Unit tests of subrequests, kan dat heel handig zijn.

De container stimuleert Dependency Injection. Van elk object is duidelijk waar ze van af hangen. Als je dan het gedrag wil onderzoeken hoef je alleen maar de afhankelijkheden te bekijken, omdat de objecten niet 'out of the blue' informatie uit het register halen. Dit maakt debugging makkelijker.

Genoeg redenen?
 
Ozzie PHP

Ozzie PHP

19/04/2012 22:57:41
Quote Anchor link
Ja, waarschijnlijk wel... maar ik vind het lastig te volgen hoe zo'n container precies werkt. Voor jou is het gesneden koek... voor mij is het nog geen eens koek, haha...

Ik zie dat jij heel overtuigd bent van dat DI gebeuren en ik twijfel dus of ik het ook moet gaan toepassen. Die voordelen zijn ongetwijfeld erg nuttig... maar de logica vind ik nog behoorlijk lastig. Maar ik vrees dat dat gewoon aan mezelf ligt...
 
Ozzie PHP

Ozzie PHP

24/04/2012 13:37:58
Quote Anchor link
@Pim:

Ik ga toch maar eens een poging wagen om zo'n DI container te implementeren. Ik vraag me alleen af... in deze regel:

$c=>set('pathRepository.config.file', __DIR__.'/config/paths.ini');

Waarom gebruik jij puntjes in deze string 'pathRepository.config.file'. Heeft dat een bepaalde reden? Underscores lijkt me gebruikelijker? 'pathRepository_config_file'

Wat betreft de magic __set en __get... zijn er nog meer argumenten waarom dit niet goed is? Ik heb eens gehoord dat het trager is?
Gewijzigd op 24/04/2012 13:38:42 door Ozzie PHP
 
Pim -

Pim -

24/04/2012 14:01:35
Quote Anchor link
Oh, die puntjes. Daar zou ik me niet zo druk om maken. Ik heb deze stijl overgenomen van hoe in Sf2 de services van de FrameworkBundle zijn genoemd. De puntjes geven de hiërarchie aan. Underscores zijn ook prima.

Wel of geen magic methods, dat mag je echt zelf weten. Doe gewoon wat je prettig lijkt. Of het sneller is of niet zou ik me iig 0 zogen maken.
 
Ozzie PHP

Ozzie PHP

24/04/2012 14:08:48
Quote Anchor link
Oké thanks...

Maar weet je heeel toevallig hoe de __set en __get werken?

Stel nu dat ik een class heb met daarin 20 functies en ik roep bijv. de __get functie aan, gaat ie dan eerst controleren of die 19 andere functies overeenkomen met de functienaam en roept ie daarna dan pas de __get functie aan? In dat geval kan ik me namelijk voorstellen dat het wel vertragend werkt...
 
Pim -

Pim -

24/04/2012 14:24:11
Quote Anchor link
Ja, dat is idd het geval, maar dat zal niet zo lang duren.

Array zijn in PHP dictionaries en tegelijkertijd linked lists. De eerste zorgen voor snelle random access ($array[1010]) en de tweede voor snelle iteratie (foreach).

Objecten zijn ook dictionaries. Het opvragen van een parameter of methode (= random access) gebeurt dus razendsnel. Kijken of een param of methode wel of niet bestaat is dus ook heel snel en een fallback als __call() of __get() is dus helemaal niet (veel) langzamer. Er is natuurlijk wel wat extra overhead, maar ik zou me er niet al te veel zorgen over maken.

In het algemeen worden hier op PHPHulp.nl weinig applicaties gebouwd die echt razendsnel moeten zijn en mocht je dat toch willen, maakt een magische getter of setter geen enkel verschil (tenzij je met duizenden objecten gaat werken...)
 
Ozzie PHP

Ozzie PHP

24/04/2012 14:36:57
Quote Anchor link
Thanks voor je uitleg. Ik begrijp bijna alles, behalve dit:

Array zijn in PHP dictionaries en tegelijkertijd linked lists. De eerste zorgen voor snelle random access ($array[1010]) en de tweede voor snelle iteratie (foreach).

Kun je dit nader toelichten?
 
Pim -

Pim -

24/04/2012 14:53:37
Quote Anchor link
Een linked list is een aantal georderde elementen die steeds een verwijzing (pointer) bevatten naar het volgende element. Zo kan je makkelijk itereren door bij het eerste element te beginnen en zo de lijst te doorlopen tot je bij het laatste element komt. Wiki

Een dictionary is een datatype dat een key met een value koppelt. In PHP wordt dat geimplementeerd met een Hash Table. Dit is een array met de waarden. De index van de waarde is afhankelijk van de key. Een hashfunctie (zoals md5, maar dan veel sneller) mapt de key-string naar een numerieke index. In de array wordt dan bij deze index gekeken en de waarde opgezocht.

Maar dat zijn allemaal interne details. Wat ik probeerde te zeggen is dat dus random access heel snel is bij objecten en arrays :).
 
Ozzie PHP

Ozzie PHP

24/04/2012 15:26:07
Quote Anchor link
Euh... ik geloof dat ik die vraag beter niet had kunnen stellen :)


Maareh... het ging er dus om of die __get en __set functies (merkbaar) langzamer zijn dan een "standaard" get() en set() functie. Maar als ik je goed begrijp is dat dus niet het geval?
 
Niels K

Niels K

24/04/2012 18:23:06
Quote Anchor link
Toch is het wel belangrijk dat je snapt wat PHP allemaal doet Ozzie ;-)

TIP: Probeer artikelen / boeken te lezen die echt diep op PHP in gaan. Dan zul je zien, dat je andere problemen ook veel makkelijker gaat oplossen.
Gewijzigd op 24/04/2012 18:29:26 door Niels K
 

Pagina: 1 2 3 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.