Filial duas vezes para condição exclusiva

5

Considere um aplicativo que exibe apenas Foobars pertencentes a eles para usuários normais e todos os Foobars para administradores:

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

-- Admins:
SELECT * FROM Foobar;

Atualmente, como as consultas são representadas na base de código:

$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']);
}

Eu não gosto dessa abordagem de ramificação dupla do ponto de vista de manutenção. Por exemplo, um erro como digitar $user['type']=='admin' em vez de $user['type']!='admin' teria que ser encontrado e corrigido em dois lugares em vez de um. No entanto, também não gosto da ideia de funções separadas para cada caso: administradores e usuários comuns.

Uma terceira abordagem seria ramificar uma vez e criar o SQL para adicionar e os valores a serem vinculados:

$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);
}

No entanto, acho essa abordagem complicada. Existe um padrão de design para essa situação? Qual é a maneira canônica de lidar com situações em que o código deve se ramificar em dois locais separados na mesma condição if ?

    
por dotancohen 26.02.2014 / 14:26
fonte

2 respostas

6

Isso pode soar trivial, mas eu simplesmente criaria uma variável mantendo a condição a ser testada duas vezes

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

e, em seguida, use essa variável nas verificações if . Isso não apenas torna o código mais legível e fácil de manter (o nome da variável descreve o que a verificação deve fazer, evitando confusão sobre == vs != ), mas também pode melhorar o desempenho caso a verificação seja mais complexa.

    
por 26.02.2014 / 14:39
fonte
1

Eu não acho que haja um padrão geral para isso, embora haja um número limitado de soluções. Uma solução é reconhecer que você tem duas condições que determinam quantas linhas você retorna e, em seguida, permite que ambas as condições sejam testadas no backend 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;
    
por 26.02.2014 / 17:41
fonte