in dubio... extra class of niet?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ozzie PHP

Ozzie PHP

02/04/2013 23:17:30
Quote Anchor link
Ik heb de waardes uit de $_SERVER array in een aparte (soort parameterbag) class opgeslagen. Nu heb ik een extra server class gemaakt, waarmee ik vaak gebruikte informatie kan opvragen. Je moet je dan (ongeveer) zoiets voorstellen. Klopt niet exact, maar het gaat om het idee...

In de extra server class (benaderbaar vanuit het request object) staat bijv. deze functie:

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

# Return the document root.
public function getDocumentRoot() {
    return $this->data_server->get('DOCUMENT_ROOT');
}


?>

Stel dat ik de document root wil opvragen dan gaat dat ongeveer zo:

$document_root = $request->getServer()->getDocumentRoot();

(Het gaat er niet om of de bovenstaande opzet klopt, dus aub daar even niet op reageren.)

In de server class staan nog meer van dit soort functies om gegevens op te halen uit de $_SERVER array.

Wat ik ook zou kunnen doen is die hele exta server class weggooien, en rechtstreeks de data uit de $_SERVER parameter bag ophalen. Je krijgt dan dus zoiets:

$document_root = $request->getDataServer()->get('DOCUMENT_ROOT');

Zoals je ziet moet ik nu zelf de juiste key (in dit geval DOCUMENT_ROOT) invoeren. Nu is dat bij DOCUMENT_ROOT niet zo heel moeilijk, maar als ik bijv. wil weten welke talen de browser ondersteunt dan is de key "HTTP_ACCEPT_LANGUAGE". Dat kan ik niet onthouden, en zal ik dus moeten opzoeken, terwijl ik nu gewoon zoiets kan doen: $languages = $request->getServer()->getLanguages();

Om een lang verhaal kort te maken... ik maak het mezelf dus een stuk makkelijker met die extra class, maar is dat eigenlijk wel de juiste manier? Of zeggen jullie dat ik het zo moet doen: $languages = $request->getDataServer()->get('HTTP_ACCEPT_LANGUAGE');
Gewijzigd op 02/04/2013 23:19:07 door Ozzie PHP
 
PHP hulp

PHP hulp

23/04/2024 19:07:01
 
Joakim Broden

Joakim Broden

02/04/2013 23:25:53
Quote Anchor link
Extra class? Je bedoelt extra method neem ik aan? Je zou kunnen kijken welke data je het meeste van $_SERVER gebruikt en daar een method van maken zoals bv 'REQUEST_METHOD', 'DOCUMENT_ROOT' etc. En voor de anderen die je zelden gebruikt kun je de get function gebruiken. Of begrijp ik je vraag nu verkeerd?
 
Ozzie PHP

Ozzie PHP

02/04/2013 23:32:56
Quote Anchor link
Nee, begrijpt mijn vraag (boven wonder... lastig uit te leggen haha) goed.

Het gaat echt om een aparte class met daarin een aantal methods inderdaad. En zoals jij zelf al aangeeft heb ik van de meest gebruikte een method gemaakt, zodat ik dus niet dit hoef te doen:

$reqest_method = $request->getDataServer()->get('REQUEST_METHOD');

maar dit...

$reqest_method = $request->getDataServer()->getRequestMethod();

Voor mij wordt het programmeren op deze manier wat makkelijker. Maar de vraag is dus of dit een goed idee is. Van de ene kant maak ik het mezelf makkelijker, want ik hoef niet na te denken hoe de key heet die ik wil ophalen, maar van de andere kant... het betekent ook een aantal extra methods. En nu vraag ik me dus af of het gebruikelijk is om het op deze manier te doen?
 
Joakim Broden

Joakim Broden

02/04/2013 23:48:34
Quote Anchor link
Ja maar OOP is ook bedoelt om het de programmeur makkelijker te maken, dus waarom dan niet die extra methods?

-- Offtopic --

Ik zie het wel vaker dat voor $_SERVER, $_SESSION aparte (parameterbags) classes worden gemaakt alleen kan iemand mij hier het nut van vertellen en hoe je dit moet te gebruiken? Want bv ik heb een 'formulieren' class, deze kijkt in een method of het formulier al verstuurd is door $_SERVER['REQUEST_METHOD'] te doen. Stel ik zou dit via de 'server' (parameterbag) class willen doen moet ik deze class eerst weer via de __construct toevoegen aan de formulieren class. Dit lijkt mij beetje onhandig dus wat is de achterliggende gedachte van zon 'server' (parameterbag) class?
 
Ozzie PHP

Ozzie PHP

02/04/2013 23:59:20
Quote Anchor link
Hertog Jan op 02/04/2013 23:48:34:
Ja maar OOP is ook bedoelt om het de programmeur makkelijker te maken, dus waarom dan niet die extra methods?

Nou ja, dat vroeg ik me dus af hè... is het wel "goed" OOP om te doen? En wellicht vertraagt het de boel ietsje die extra methods (alhoewel ik dat niet heb gebenchmarkt).

Hertog Jan op 02/04/2013 23:48:34:
-- Offtopic --

Ik zie het wel vaker dat voor $_SERVER, $_SESSION aparte (parameterbags) classes worden gemaakt alleen kan iemand mij hier het nut van vertellen en hoe je dit moet te gebruiken? Want bv ik heb een 'formulieren' class, deze kijkt in een method of het formulier al verstuurd is door $_SERVER['REQUEST_METHOD'] te doen. Stel ik zou dit via de 'server' (parameterbag) class willen doen moet ik deze class eerst weer via de __construct toevoegen aan de formulieren class. Dit lijkt mij beetje onhandig dus wat is de achterliggende gedachte van zon 'server' (parameterbag) class?

Ik heb een eigen parameter bag gemaakt. Ik heb een request class, en dan heb ik een parameter bag waarin ik bijvoorbeeld alle POST data stop... en bijv. ook eentje waarin ik de SERVER data stop. Als ik dan een POST waarde nodig heb, dan doe ik bijv. zoiets:

$foo = $request->getDataPost()->get('foo');

Dat request object is een service die aanwezig is in de service container. Het is de bedoeling dat ik straks de service container beschikbaar stel aan m'n controllers. Vanuit de controller kun je dan weer zoiets doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$request
= $this->container->get('request');
if ($request->getClient()->isRequestMethodPost()) {
  echo $request->getDataPost()->get('foo');
}

?>
 
Joakim Broden

Joakim Broden

03/04/2013 00:15:44
Quote Anchor link
Ja tot zover snap ik het, in de controller is het wel makkelijk. Alleen stel op de controller wil ik een formulier hebben, deze bouw ik normaal altijd op in een array en die word door een formulieren class omgezet in een formulier. Maar de formulieren class word bijvoorbeeld gekeken of het formulier verzonden is, zoja dan valideert hij alle velden. Met zon 'request' class moet je die weer mee geven in de constructor zoals onderstaande code.

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 Form {
        protected $request = null;

        public function __construct($request) {
            $this->request = $request;
        }


        public function isSubmitted() {
            if ($this->request->isRequestMethodPost()) {
                return true;
            }
else {
                return false
            }
        }
    }

?>

Is dit dan niet makkelijker?
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
<?php
    class Form {
        public function __construct() {
            
        }


        public function isSubmitted() {
            if ($_SERVER['REQUEST_METHOD'] == 'post') {
                return true;
            }
else {
                return false
            }
        }
    }

?>
 
Ozzie PHP

Ozzie PHP

03/04/2013 00:19:52
Quote Anchor link
Uiteindelijk is het natuurlijk je eigen keuze, maar in jouw laatste voorbeeld roep je zomaar rechtstreeks de $_SERVER array aan. Dat is niet zo heel mooi.

Daarnaast denk ik dat je opbouw niet helemaal klopt. Jij controleert in isSubmitted() of je formulier is gepost, maar dat lijkt me de verkeerde plek. Jouw router moet op basis van de aangeroepen URL een bepaalde actie in een controller triggeren. Deze actie moet bepalen of de URL is aangeroepen via een POST request. Zo ja, dan pas wordt het formulier afgehandeld. Dat zou de juiste weg moeten zijn lijkt mij.
 
Ward van der Put
Moderator

Ward van der Put

03/04/2013 08:33:15
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
// Zo kan het ook:
if (Server::hasPost()) {
    // Er is post: formulier verwerken...
}
?>


PHP kent (nog) geen read-only properties, maar juist voor omgevingsvariabelen zoals die in $_SERVER zijn dergelijke "voldongen feiten" voor een applicatie wel relevant. Als je het zo bekijkt, wordt een serverobject vooral een doorgeefluik waar je iets uit kunt halen maar niets in stopt:

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
38
39
40
41
42
43
<?php
class Server
{
    /**
     * @param  void
     * @return string|null
     */

    public static function getRequestMethod()
    {

        if (isset($_SERVER['REQUEST_METHOD'])) {
            if (is_string($_SERVER['REQUEST_METHOD'])) {
                $request_method = trim($_SERVER['REQUEST_METHOD']);
                $request_method = strtoupper($request_method);
                if (!empty($request_method)) {
                    return $request_method;
                }
else {
                    return null;
                }
            }
else {
                return null;
            }
        }
else {
            return null;
        }
    }


    /**
     * @param  void
     * @return bool
     */

    public static function hasPost()
    {

        if (self::getRequestMethod() !== 'POST') {
            return false;
        }

        if (empty($_POST)) {
            return false;
        }
else {
            return true;
        }
    }
}

?>
 
Erwin H

Erwin H

03/04/2013 09:19:58
Quote Anchor link
Ozzie PHP op 02/04/2013 23:32:56:
Voor mij wordt het programmeren op deze manier wat makkelijker. Maar de vraag is dus of dit een goed idee is. Van de ene kant maak ik het mezelf makkelijker, want ik hoef niet na te denken hoe de key heet die ik wil ophalen, maar van de andere kant... het betekent ook een aantal extra methods. En nu vraag ik me dus af of het gebruikelijk is om het op deze manier te doen?

Ga terug naar de basis van OOP. Wat is de reden om alles op te splitsen in verschillende classes? Is die reden hier van toepassing, dan is het nuttig om het te doen, zoniet, dan niet.


P.S.
Dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php
        public function isSubmitted() {
            if ($this->request->isRequestMethodPost()) {
                return true;
            }
else {
                return false
            }
        }

?>

is hetzelfde als dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
        public function isSubmitted() {
             return $this->request->isRequestMethodPost();
        }

?>

Maar het laatste is iets korter ;-)
 
Joakim Broden

Joakim Broden

03/04/2013 11:09:58
Quote Anchor link
Ozzie PHP op 03/04/2013 00:19:52:
Uiteindelijk is het natuurlijk je eigen keuze, maar in jouw laatste voorbeeld roep je zomaar rechtstreeks de $_SERVER array aan. Dat is niet zo heel mooi.

Daarnaast denk ik dat je opbouw niet helemaal klopt. Jij controleert in isSubmitted() of je formulier is gepost, maar dat lijkt me de verkeerde plek. Jouw router moet op basis van de aangeroepen URL een bepaalde actie in een controller triggeren. Deze actie moet bepalen of de URL is aangeroepen via een POST request. Zo ja, dan pas wordt het formulier afgehandeld. Dat zou de juiste weg moeten zijn lijkt mij.


Ja dit was een voorbeeld. In de isSubmited word het formulier zeg maar afgehandeld, worden de elementen (velden) gevalideerd, worden de errors gezet en dat soort handelingen. Dit soort handelingen laat je toch niet door een andere class doen?

bv:
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
    public function isSubmitted() {
        if ($_SERVER['REQUEST_METHOD'] == 'post') {
            foreach ($this->fields as $name => $field) {
                if (!$field->validate()) {
                    $this->errors[$name] = 'Veld '.$name.' is niet gevalideerd.';
                }
            }


            if (count($this->errors) == 0) {
                return true;
            }
        }

    
        return false;
    }

?>

En dan vervolgens zo:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
    $form
= new Form();

    if ($form->isSubmitted()) {
        // Dit word pas uitgevoerd als het formulier is verzonden en alle velden zijn gevalideerd.
    }
?>

Of kan dit beter/anders?
Gewijzigd op 03/04/2013 11:10:57 door Joakim Broden
 
Tim S

Tim S

03/04/2013 12:36:23
Quote Anchor link
@Hertog Jan

In dit geval lijkt me dat de juiste oplossing. Maar stel je heb een gecompliceerd formulier wat je niet maakt met een form builder, een wizard of een formulier in een dialog(al kan je wel je form builder uitbreiden), dan is de klasse van ozzie wel weer bruikbaar.
 
Wouter J

Wouter J

03/04/2013 13:06:18
Quote Anchor link
Hertog Jan, wie zegt dat POST de request method was? En wie zegt dat ik bij een controle of een formulier verzonden is meteen ga kijken of het verzonden pakketje valid is? Dat zijn 2 totaal andere taken. Die verschillen zelfs zoveel dat je waarschijnlijk losse klassen voor de Validatie gaat gebruiken, losse voor het Formulier en losse voor de Request:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
if ('POST' === $request->getMethod()) {
    $form->bind($request); // bind de request data met het formulier

    // wordt gedaan met Validator en Constraint klassen

    if ($form->isValid()) {
        // ... doe wat leuks
    }
}

?>
 
Ozzie PHP

Ozzie PHP

03/04/2013 14:45:29
Quote Anchor link
Al met al heb ik nu nog geen antwoord op mijn vraag. Zijn die extra methods die het mij makkelijker maken de moeite waard? Of is het dubbelop?

Als ik de extra methods niet inlaadt dan duurt de verwerkingstijd tot het moment dat ik de requesst heb aangemaakt ongeveer 0,00350 secondes. Als ik de extra methods wel inlaadt dan duurt het ongeveer 0,00410 seconden. Het wordt er dus wel ietsje trager van. Maar wat is nu het meest gebruikelijk? Wat doen jullie?

Vis je de juiste waarde zelf op uit de $_SERVER array, of maak je daarvoor een functie (met een makkelijke naam) die de juiste waarde ophaalt? Wat is gebruikelijk?

Ward van der Put op 03/04/2013 08:33:15:

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
<?php
class Server
{
    /**
     * @param  void
     * @return string|null
     */

    public static function getRequestMethod()
    {

        if (isset($_SERVER['REQUEST_METHOD'])) {
            if (is_string($_SERVER['REQUEST_METHOD'])) {
                $request_method = trim($_SERVER['REQUEST_METHOD']);
                $request_method = strtoupper($request_method);
                if (!empty($request_method)) {
                    return $request_method;
                }
else {
                    return null;
                }
            }
else {
                return null;
            }
        }
else {
            return null;
        }
    }
}

?>

Waarom bouw je zoveel controles in? Iedere server geeft een request method af, waarom dan controleren of ie geset is, of het een string is, omzetten naar hoofdletters... is dat niet wat overdreven?

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

public static function getRequestMethod() {
  return $_SERVER['REQUEST_METHOD'];
}

?>
Gewijzigd op 03/04/2013 14:48:06 door Ozzie PHP
 
Joakim Broden

Joakim Broden

03/04/2013 15:19:31
Quote Anchor link
@Ozzie ik zou het wel doen puur uit gemak.

@Wouter, ik geef bijvoorbeeld in de constructor de configuration van het formulier op. Hier kun je bijvoorbeeld aangeven of het via POST of via GET gaat en aan de hand van dat word er gekeken of het formulier verstuurd is. En het valideren word bv ook weer gedaan via een aparte validatie class die ik ook mee geef in de de constructor. Maar is een 'request' class echt een toegevoegde waarde?

Nog een voorbeeld, ik heb een 'url' class. Deze stript de URL in de adresbalk op in delen. Dit doet hij bijvoorbeeld aan de hand van de 'HTTP_HOST' en 'SCRIPT_NAME'. Nu gaat dat nog zo:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
    public function setHost() {
        $this->sHost = rtrim(strtolower($_SERVER['HTTP_HOST']), '/');
    }

?>

Maar als ik gebruik ga maken van een 'request' class word het:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
    public function setHost() {
        $this->sHost = rtrim(strtolower($this->oRequest->get('HTTP_HOST')), '/');
    }

?>

En moet ik ook eerst weer de 'request' class aan de constructor van mij 'url' class toevoegen, oftewel extra methods, extra controlles etc. Dus kan iemand mij misschien het nut vertellen van zon 'request' class zodat ik het licht begin te zien? :)
Gewijzigd op 03/04/2013 15:36:11 door Joakim Broden
 
Ozzie PHP

Ozzie PHP

03/04/2013 15:21:35
Quote Anchor link
Oké, thanks Hertog Jan!

Nog meer mensen die het wel (of juist niet) zouden doen? Jullie meningen zijn van harte welkom.
 
Ward van der Put
Moderator

Ward van der Put

03/04/2013 19:04:58
Quote Anchor link
Misschien toch nog even de alias tegen de lat leggen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
public static function getRequestMethod()
{

    return $_SERVER['REQUEST_METHOD'];
}

?>


Dat heeft wel nadelen:

• Je bouwt iets dat er al is. Zonde van de tijd en zonde van de moeite om zoiets steeds te parsen en uit te voeren.

• Je introduceert een nieuw PHP-dialect. Dat kun je doen voor de duidelijkheid of voor het gemak, maar "beauty is in the eye of the beholder". Zo kan isReeelGetal() een mooie aanvulling zijn op is_double(), is_float() en is_real(): de een zal de schoonheid van een PHP/Math-NL geweldig vinden, dan ander ziet het als een hel.

• Je maakt implementaties afhankelijk van getRequestMethod() waar ze gewoon $_SERVER['REQUEST_METHOD'] hadden kunnen gebruiken. Dat is een lastige maar belangrijke: script is niet langer direct afhankelijk van de scripttaal zelf, maar van een specifieke interpretatie daarvan. (Dat is de achilleshiel van frameworks die door de makers van frameworks wordt genegeerd: de afhankelijkheid van het framework.)

• Je bouwt schijnzekerheid en onzekerheid in. Wie de API leest, denkt ten onrechte dat getRequestMethod() iets speciaals doet. Die methode is er niet voor niets, toch? Wie dieper in de code duikt, ziet dat getRequestMethod() eigenlijk niets doet en laat de methode misschien links liggen omdat $_SERVER['REQUEST_METHOD'] de oude en vertrouwde oplossing is.
 
Ozzie PHP

Ozzie PHP

03/04/2013 19:15:48
Quote Anchor link
Hertog Jan op 03/04/2013 15:19:31:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
    public function setHost() {
        $this->sHost = rtrim(strtolower($_SERVER['HTTP_HOST']), '/');
    }

?>

Maar als ik gebruik ga maken van een 'request' class word het:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
    public function setHost() {
        $this->sHost = rtrim(strtolower($this->oRequest->get('HTTP_HOST')), '/');
    }

?>

En moet ik ook eerst weer de 'request' class aan de constructor van mij 'url' class toevoegen, oftewel extra methods, extra controlles etc. Dus kan iemand mij misschien het nut vertellen van zon 'request' class zodat ik het licht begin te zien? :)

Die request class zou dan onderdeel worden van je service container en die geef je als service/argument mee aan de class waar je 'm nodig hebt. Je gaat die host dus niet setten, maar je doet zoiets:

$this->request->getServer()->getHost();

Het gaat er vooral om dat je niet zomaar "out of the blue" ergens informatie vandaan haalt. De server informatie hoort bij het request object, en haal je dus netjes uit je request object en niet uit een globale array.

Maar het is maar net hoe netjes/gestructureerd je wil werken. Je kan ook overal waar je POST data nodig hebt, zeggen:

$foo = $_POST['foo'];

Maar het is mooier als je de POST data echt uit je applicatie haalt en in dit geval uit het request object:

$foo = $request->getPostData()->get('foo');

In het eerste geval grijp je zomaar spontaan iets "uit de lucht" terwijl je in het laatste geval gestructureerd je applicatie aanspreekt: geef mij het request, geef me de POST data en geef me van de POST data de waarde die hoort bij de key 'foo'.

Hoop dat dit een beetje verhelderend werkt.
 



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.