Do $ _POST, $ _GET, etc violano il principio di incapsulamento?

8

L'utilizzo di globals rende difficile la verifica del codice, quindi più soggetto a bug, non sicuro e imprevedibile. Ecco perché passiamo le variabili che vogliamo all'interno di una funzione / oggetto. Quindi la mia domanda è semplice:

Do $ _POST, $ _GET, ecc violano il principio di incapsulamento ?

Sto pensando che, per mantenere il controllo di quelle variabili in modo OO, una soluzione ideale sarebbe aggiungere alcune righe come questa al codice:

// Convert the $_GET array to an object
$get = json_decode(json_encode($_GET), FALSE);  // stackoverflow.com/a/1869147
// Stop it from being included from anywhere
unset($_GET);

// Small example of what could be done later on
$DB = new PDO(/* ... */);
$Person = new Person($DB, $get->id);

Non l'ho visto da nessuna parte, nemmeno un tutorial o una raccomandazione. Inoltre, possiamo vedere chiaramente come il codice sopra sia molto più facile da test rispetto a quello che include $Person = new Person($DB, $_GET['id']); o even (il brutto) $Person = new Person($DB); dato che puoi usare un oggetto fittizio $get .

Il codice è nella giusta direzione o mi manca qualcosa?

EDIT: dopo alcune indagini ( quadro Zend e Cake PHP ) come suggerito da Alexander Kuzmin, sembra essere la cosa giusta andare. Probabilmente sono troppo grandi per me da scavare nel codice ATM, ma lo terrò a mente.

    
posta Francisco Presencia 12.11.2013 - 12:43
fonte

4 risposte

8

Non sono del tutto sicuro del motivo per cui si applica json_decode a $_GET a "convertirlo in un array"; $_GET già è un array.

Usando i super-globals ( $_GET , $_POST etc) è una violazione del principio di incapsulamento. Ma c'è stata una linea disegnata dove smetti di incapsulare le cose. La richiesta di dati è un buon candidato per l'incapsulamento, ma non fatevi ingannare dal tentativo di incapsula tutte le cose .

La maggior parte dei framework di solito avvolge i super-globals di PHP in una qualche forma di oggetto di richiesta. Facendo questo, è più facile prendere in giro i test, ecc. L'approccio più semplice sarebbe:

<?php
class Request
{
    public $get;
    public $post;
    public $session;
    public $cookie;

    public function __construct($get, $post, $session, $cookie)
    {
        $this->get = $get;
        $this->post = $post;
        $this->session = $session;
        $this->cookie = $cookie;
    }
}

$request = new Request($_GET, $_POST, $_SESSION, $_COOKIE);

È semplice e rudimentale, ma fa il lavoro. È anche consigliabile filtrare i dati a questo punto, per difendersi dalle iniezioni di XSS.

Ma è racchiuso in un oggetto Request . L'oggetto Request ha quattro matrici e questi array possono essere facilmente derisi:

$get = array(
    'foo' => 'bar'
);
$post = array();
$session = array(
    'user' => 1
);
$cookie = array();

$request = new Request($get, $post, $session, $cookie);
    
risposta data 12.11.2013 - 15:15
fonte
2

L'uso di superglobali $_{POST,GET,SERVER} o qualsiasi altra cosa viola l'incapsulamento.

Questo problema aumenta quando si desidera creare "richieste locali" all'interno del lato server dell'applicazione come molti framework fanno oggigiorno.

Non sono abituato a lavorare con frameworkds, ma quello che faccio di solito è creare una coppia di richiesta / risposta all'inizio del mio processo. La richiesta contiene i valori di questi parametri globali.

Se voglio creare un subrequest lato server, ho due opzioni: usare il contesto corrente o crearne uno completamente nuovo. Quindi, penso che non dovresti disabilitare queste variabili superglobali perché FORSE vorresti usarle di nuovo. Inoltre, per questo motivo, non sono d'accordo sul fatto che i parametri di richiesta dovrebbero essere singleton.

Contenendo solo valori, non riferimenti a questi superglobali, una modifica in un oggetto Request non influirà mai su un altro, quindi il problema con lo stato globale è risolto.

Quindi, in sostanza, ho due opzioni:

// Using global context
$request = new Request(array(
    'post' => $_POST,
    'get' => $_GET
));

// or creating a new context

$request = new Request(array(
    'post' => ['someKey' => 'someValue'],
    'get' => ['queryParam' => 'queryValue'],
));
    
risposta data 12.11.2013 - 15:07
fonte
0

POST- e GET-vars sono inviati al server in un'unica soluzione e php deve capirli. In un certo senso, ha senso averli disponibili a livello globale, così lo sviluppatore può scegliere dove elaborarli.

Molti framework (come CakePHP per esempio) leggono i Parametri e li posizionano tutti in una matrice, oggetto o struttura simile. Dopodiché, vengono gestiti come qualsiasi altro dato e vengono passati a tutti i metodi che li richiedono.

    
risposta data 12.11.2013 - 12:51
fonte
0

L'incapsulamento è un buon principio quando c'è la possibilità che tu possa aver bisogno di più istanze di qualcosa. Ma c'è solo un set di parametri per una pagina web. Se fossero in una classe invece di variabili globali, probabilmente sarebbero dei singleton. Non c'è alcun miglioramento significativo passando dalle variabili globali alle classi Singleton, è solo una sintassi diversa per accedervi. Sono ancora oggetti intrinsecamente globali, è solo più ingombrante perché devi gestire l'istanza della classe e passarla in giro.

Dato che questi parametri sono accessibili così frequentemente, i progettisti di PHP hanno deciso di renderli facilmente accessibili, piuttosto che aderire a rigidi principi di progettazione. È una buona idea rendere convenienti le operazioni più comuni, altrimenti i programmatori ti malediranno per averle ripetute ogni volta la stessa cosa lunga.

    
risposta data 12.11.2013 - 13:06
fonte

Leggi altre domande sui tag