Branch due volte per condizioni uniche

5

Considera un'applicazione che visualizza solo i Foobar appartenenti a se stessi agli utenti normali e tutti i Foobar agli amministratori:

-- Normal users:
SELECT * FROM Foobar WHERE user_id=:user_id;

-- Admins:
SELECT * FROM Foobar;

Attualmente, questo è il modo in cui le query sono rappresentate nella base di codice:

$sql = "SELECT * FROM Foobar";

if ( $user['type']!='admin' ) {
    $sql.= ' WHERE user_id=:user_id';
}

$stmt = $pdo->prepare($sql);

if ( $user['type']!='admin' ) {
    $stmt->bindValue(':user_id', $user['id']);
}

Non mi piace questo approccio dual-branching dal punto di vista della mantenibilità. Ad esempio, un errore come digitare $user['type']=='admin' anziché $user['type']!='admin' dovrebbe essere trovato e risolto in due posti anziché uno. Tuttavia, non mi piace l'idea di funzioni separate per ogni caso: amministratori e utenti regolari.

Un terzo approccio sarebbe quello di diramare una volta e lì creare l'SQL da aggiungere e i valori da associare:

$sql_to_add = '';
$array_to_bind = array();

if ( $user['type']!='admin' ) {
    $sql_to_add = ' WHERE user_id=:user_id';
    $array_to_bind = array( ':user_id'=>$user['id'] );
}

$sql = "SELECT * FROM Foobar {$sql_to_add}";
$stmt = $pdo->prepare($sql);

foreach ( $array_to_bind as $k=>$v ) {
    $stmt->bindValue($k, $v);
}

Tuttavia trovo questo approccio ingombrante. Esiste uno schema di progettazione per questa situazione? Qual è il modo canonico per gestire le situazioni in cui il codice deve diramarsi in due posizioni separate sulla stessa condizione if ?

    
posta dotancohen 26.02.2014 - 14:26
fonte

2 risposte

6

Può sembrare banale, ma vorrei semplicemente creare una variabile che tenga la condizione da testare due volte

$is_normal_user = $user['type'] != 'admin';

e quindi usa quella variabile nei controlli if . Ciò non solo rende il codice più leggibile e più facile da mantenere (il nome della variabile descrive cosa dovrebbe fare il controllo, evitando confusione su == vs != ), ma può anche migliorare le prestazioni nel caso in cui il controllo sia più complesso.

    
risposta data 26.02.2014 - 14:39
fonte
1

Non penso che ci sia un modello generale a questo, sebbene ci sia un numero limitato di soluzioni. Una soluzione è riconoscere che ci sono due condizioni che determinano il numero di righe che si ricevono e quindi consentire che entrambe queste condizioni vengano testate sul back-end sql.

-- Normal users:
SELECT * FROM Foobar WHERE user_id=:user_id;

-- Admins:
SELECT * FROM Foobar;

-- actual query
SELECT * FROM Foobar WHERE user_id=:user_id Or is_admin=1;
    
risposta data 26.02.2014 - 17:41
fonte

Leggi altre domande sui tag