Выбирая все с ГДЕ - PullRequest
       2

Выбирая все с ГДЕ

3 голосов
/ 07 апреля 2011

В настоящее время я работаю над проектом PHP, где существует несколько прав доступа. Логика проста:
- Когда ваш уровень доступа равен 2, вы можете видеть список только ваших собственных проектов
- Когда ваш уровень доступа равен 3, вы можете видеть ВСЕ проекты

Так в SQL:
Первый:

SELECT project_name FROM projects

Второй:

SELECT project_name FROM projects WHERE user_id = user_id

Проблема в том, что я использую PDO с подготовленными операторами, и такие запросы выполняются несколько раз по всему сценарию. Вот как это выглядит:

if ($_SESSION['access_level'] == 3) {
    $sql = "SELECT project_name FROM projects";
  } else {
    $sql = "SELECT project_name FROM projects WHERE user_id = ?";
}

$res = $db->prepare($sql);

// Some more PHP 

if ($_SESSION['access_level'] == 3)
      $res->execute();
    else
      $res->execute(array($_SESSION['user_id']));

Поскольку я делаю это в нескольких частях сценария, это становится беспорядком. Есть лучший способ сделать это? Лично я думал о предложении WHERE, где каждая запись выбрана. Таким образом, это было бы возможно в начале скрипта:

if ($_SESSION['access_level'] == 3)
      $id = *;
    else
      $id = $_SESSION['user_id'];

Теперь запрашивать намного проще:

$res = $db->prepare("SELECT project_name FROM projects WHERE user_id = ?");
$res->execute(array($id));

(теперь он будет получать все записи, когда ваш уровень доступа 3, но только ваши собственные, когда вы только уровень 2)

Похоже, это довольно симпатичное решение для дампа, поскольку я не использую предложение WHERE, как его следует использовать. Кроме того, использование * просто невозможно.

Какой самый лучший вариант для этого?

Спасибо!

Ответы [ 7 ]

3 голосов
/ 07 апреля 2011

Вы ищете решение совершенно неверным способом.

Каждый раз, когда вы сталкиваетесь с ситуацией, когда вы делаете что-то в нескольких частях сценария, и это становится беспорядком, вы должны создать функцию .

Фактически, вы все еще пишете весь этот уродливый повторяющийся код с подготовкой, выполнением, извлечением, подготовкой, выполнением, извлечением, подготовкой, выполнением, извлечением - для каждого запроса на странице. Разве это не похоже на беспорядок?

Итак, вам нужно создать две функции.

общего назначения, просто для извлечения некоторого значения из запроса без повторения бесполезного кода, чтобы использовать его следующим образом:

$proj_names_arr = $db->getColumn("SELECT project_name FROM projects");

и упомянутое Райзеном, основанное на первом, которое будет использоваться таким образом

$proj_names_arr = getProjects();

Это будет единственное реальное улучшение вашего кода

Что касается функции, это не так сложно
грубый пример:

function getColumn() {
  $args  = func_get_args();
  $query = array_shift($args);
  $res = $db->prepare($query);
  $res->execute($args);
  $data = array();
  while ($row = $res->fetch(PDO::FETCH_NUM)) {
    $data[] = $row[0];
  }
  return $data;
}

итак, это можно назвать

$proj_names = $db->getColumn("SELECT project_name FROM projects WHERE user_id = ?",
                             $_SESSION['user_id']);
2 голосов
/ 07 апреля 2011

А как насчет SQL:

$sql = 'SELECT project_name FROM projects WHERE user_id = ? OR 3 = ?';
$res = $db->prepare($sql);
$res->execute(array($id, $access_level);
2 голосов
/ 07 апреля 2011

Я думаю, что легче хранить предложения where в переменной, а также параметры связывания, а затем составлять запрос при его запуске:

<?php

$sql = 'SELECT project_name FROM projects';
$where = array();
$parameters = array();


if ($_SESSION['access_level'] !== 3) {
    $where[] = 'user_id = ?';
    $parameters = array($_SESSION['user_id']);
}



if( !empty($where) ){
    $sql .= ' WHERE ' . implode(', ', $where);
}
$res = $db->prepare($sql);

$res->execute($parameters);
1 голос
/ 07 апреля 2011

Создайте функцию, такую ​​как getProjects () , где она будет возвращать проекты в соответствии с уровнем пользователя.

Используйте код Альваро, например, внутри функции и верните набор результатов.

0 голосов
/ 07 апреля 2011

Это мое понимание: сначала вы хотите создать предложение, а затем вы можете использовать это предложение в другом контенте, вы можете сделать так:

В начале:

if ($_SESSION['access_level'] == 3)
      $idClause = '1 = 1';
else
      $idClause = 'user_id = '.$_SESSION['user_id'];

Теперь вы можете использовать $ idClause там, где хотите, например

$res = $db->prepare("SELECT project_name FROM projects WHERE ?");
$res->execute(array($idClause));

, и это совместимо с другим предложением WHERE, например

$res = $db->prepare("SELECT project_name FROM projects WHERE ? and project_group = 'group'");
$res->execute(array($idClause));

Надеюсь, это поможет вам.

0 голосов
/ 07 апреля 2011

Поскольку я делаю это в нескольких частях сценария, это становится беспорядком.

Не повторяйся . Если вы обнаружите, что повторяете блоки кода, это признак того, что вы должны рефакторизовать этот общий код в функцию или метод.

Вы также можете избавиться от некоторых более мелких повторений, добавив дополнительную информацию к вашему запросу, а не переписывая ее, и используя что-то вроде bindParam(), чтобы добавить дополнительный параметр, вместо того, чтобы изменять выражение execute():

$userOnly = ($_SESSION['access_level'] == 2);

$sql = "SELECT project_name FROM projects";

if ($userOnly) {
    $sql .= " WHERE user_id = ?";
}

$res = $db->prepare($sql);

if ($userOnly) {
 $res=>bindParam(bindParam(1, $$_SESSION['user_id'], PDO::PARAM_INT);
}

$res->execute(array($_SESSION['user_id']));

Лично я думаю, что это немного аккуратнее, чем оригинал, поскольку части, которые относятся только к более низкому уровню доступа, четко обозначены и автономны, а не повторяют уже представленный код.

Кроме того, использование новой переменной с описательным именем для уровня доступа останавливает вас от повторения магических чисел и дает вам одну точку изменения.

Надеюсь, это поможет.

0 голосов
/ 07 апреля 2011

Я понял: вы хотите WHERE -Statement, это всегда верно?

WHERE 1 = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...