Класс базы данных в PHP;имеет только одну функцию - вопрос о методах и хорошая ли это идея - PullRequest
3 голосов
/ 23 июня 2010

Итак, у меня есть этот класс базы данных в PHP, и у меня есть только 1 функция (кроме __construct и __destruct. Позвольте мне объяснить подробнее ...

Первоначально я написал это так, чтобы при подключении к базе данных я просто вызывал свою функцию connect_to_db(), которая возвращала объект mysqli. Затем я использовал эти объекты функций (->query(), ->prepare(), ->bind_param(), и так далее ..), чтобы сделать что угодно. Это загромождено (и все еще остается тем, что я еще не переключил свой код на мой новый класс) с большим количеством функций, которые просто выполняют определенные действия, например:

function get_country_info($db, $usrid) {
  $statement = "select `name`, `population`, `money`, `food` from `countries` where `usr_id` = ?";
  $qry = $db->prepare($statement) or
    trigger_error("get_country_info():statement failed...");
  $qry->bind_param("i", $usrid);
  $qry->execute();
  $qry->bind_result($name, $population, $money, $food);
  $qry->fetch();
  $res = array("name" => $name, 
    "pop" => $population, 
    "money" => $money, 
    "food" => $food);

  return $res;
}

И то, что я первоначально планировал сделать, это просто бросить их в класс для ясности, но я фактически закончил тем, что создал класс, который при создании создает объект mysqli для конкретной базы данных (предоставляется через аргумент) и при уничтожении закрывается эта ссылка. Мне очень нравится не беспокоиться о наборе $db->close();, так как когда скрипт завершает выполнение, соединение закрывается.

Имеет только 1 другую функцию; query(). Эта функция может обрабатывать любые запросы и выводить их в виде многомерного массива. Используется eval(). Из того, что я понимаю, это, как правило, осуждается - но eval() так полезен; так почему это осуждается?

Я полагаю, что эта функция может быть медленной, но, видимо, я просто использую ее для проекта для домашних животных (браузерная игра по управлению страной), и я не заметил ничего, что меня это совсем не волнует. Меня беспокоит то, будут ли люди обычно делать это в «реальном мире» или есть какой-то стандарт, по которому люди делают это, или, возможно, что-то включенное (или добавляемое) в PHP, которое обычно используется

Я самоучка, поэтому иногда я не знаю, как лучше поступить. Может быть, кто-нибудь мог бы посоветовать мне здесь?

Соответствующую функцию можно увидеть здесь: http://pastebin.org/353721, в виде ~ 60 строк, и я не хочу загромождать страницу. Я также не тестировал его всесторонне (я даже не знаю, что такое модульные тесты, поэтому я тестирую, используя эту функцию различными способами), поэтому могут возникнуть проблемы, о которых вы, ребята, можете не знать. вне.

Спасибо.

Ответы [ 5 ]

4 голосов
/ 23 июня 2010

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

Это может быть полезно для небольших и хорошо организованных проектов, но как только вы начнете работатьболее сложный, вы скоро заметите, что у вашего подхода есть один большой недостаток: ваши SQL-запросы все еще разделены по сайту.В тот день, когда вы что-нибудь измените в базе данных, вам нужно будет просмотреть весь свой сайт и найти все операторы SQL: это плохо (мне пришлось сделать это один раз ...).

ВыТеперь следует переместить весь код SQL в одно место.Так что есть разные варианты.В аналогичном контексте я сделал метод query () защищенным, затем сделал класс Db «абстрактным» и разделил его на подклассы.Каждый подкласс является классом, который содержит несколько методов относительно определенного набора таблиц, и это единственное место, где вы найдете SQL.Все остальные проекты могут вызывать только эти методы.

Или, что еще лучше, вы можете использовать ORM (реляционный маппер oblect), который отображает каждую таблицу в объект.

Что касается зла зла: я никогда не использовал его.Но я подумал, что не собираюсь использовать «goto», потому что это зло, а потом я нашел волшебное место, где это идеально подходило.Итак, если вы исследовали все возможности и считаете, что это оптимальное решение ... используйте его.

2 голосов
/ 23 июня 2010
  • Вместо eval вы можете использовать call_user_func() или call_user_func_array().
  • Вы должны проверить возвращаемое значение execute().
  • Ваша функция не поддерживает подвыборы, содержащие несколько запятых, но возвращает только одно значение.
  • Вы можете использовать trim() вместо ltrim(rtrim()).

Я бы все еще использовал функцию типа get_country_info() поверх этого класса БД. Часто вы хотите что-то сделать с данными, прежде чем ваше приложение сможет их использовать. Что еще более важно, вы хотите абстрагировать хранилище данных от вашего приложения . То есть метод, который использует информацию о стране, не должен знать, что она поступила из базы данных.

1 голос
/ 23 июня 2010

Как писал Techpriester: разбейте его на более мелкие части.Я рекомендую по крайней мере:

  • аргумент для привязки конвертера
  • ветвь if-else для одиночного и многопараметрического параметра
  • синтаксический анализатор операторов sql (узнать о возвращенныхfields)

Другим подходом к вашей проблеме будет создание оператора sql внутри вашего класса запросов (аргументами будут имена полей, таблицы, ограничения where, ...) и разработка подклассовдля разных типов запросов.Это исключит необходимость разбора заявления.Над этим слоем вы бы поместили кучу классов DAO для реальной работы.

Но подождите: другие сделали это ... (может быть, многие другие, чтобы быть конкретными).Поэтому использование PDO, Doctrine, Propel или даже более крупной библиотеки, такой как ZendFramework (активный шаблон записи ...), было бы наиболее ценным и стабильным вариантом.

Если вы, однако, хотите кое-что узнать об архитектуре программного обеспеченияи ОО Системы.Идите дальше и создайте свой собственный, если вы делаете это хорошо, вы можете переключиться на другой уровень БД, как только ваша система вырастет (Версия 2.x :-)).

0 голосов
/ 23 июня 2010

На ваш вопрос - вам нужен некоторый опыт, чтобы узнать, почему существуют "лучшие практики", почему eval() устарела, почему люди используют готовые заявления и т. Д.

Я бы порекомендовал вам посмотретьна http://dibiphp.com/cs/ для красивого и лаконичного слоя БД для PHP.

Вы также можете попробовать Java, когда получите представление о веб-технологиях.Тогда вы можете использовать классные вещи, такие как iBatis , который почти дошел до PHP

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

$aasAreas = Array();
$sSQL = "SELECT id, x, y, x2 AS r, popis FROM ".$oFW->GetOption('tables.areas')
         ." WHERE id_ad=".asq((int)$_GET['id']);
$oRes = $oFW->GetDB()->Select($sSQL);
if(!$oRes || !$oRes->IsOk()){ $sError = $oRes->GetError(); break; }
else while( $a = $oRes->FetchRow() ){
   $aasAreas[] = $a;
}

[OT] И некоторые ORM для PHP попытки используются следующим образом:

<code>// Load by ID
echo "<h3>Load by ID</h3>";
$iID = 1;
echo "<pre>\$oObject = \$oOP->LoadObjectById(".$oClass->GetName().", $iID);
"; $ oUser = $ oOP-> LoadObjectById ($ oClass, $ iID); echo "
oUser: [".gettype($oUser)."]".AdjustedPrintR($oUser)."
"; echo "
GetPoolCount ():". $ oOP-> GetPoolCount (). "
"; // Сохранить эхо "

Сохранить

"; $ oUser = new cObjectPersistenceTestClass_User (); $ oUser-> SetId (1); $ oUser-> SetProperty ('user', 'as'.rand ()); $ oUser-> SetProperty (' pass ','as '); $ oUser-> SetProperty (' fname ',' Astar '); $ oUser-> SetProperty (' lname ',' Seran '); echo "
oUser: [".gettype($oUser)."]".AdjustedPrintR($oUser)."
"; $ bSucc = $ oOP-> SaveObject ($ oUser); echo "
". ($ bSucc? 'сохранено': 'error'). "
"; // Загрузить по значению - загрузить созданный выше объект -> Пул объектов попал в $ xVal = $ oUser-> GetProperty ('user'); $ aoUsers = $ oOP-> LoadObjectsByValue ($ oClass, 'user', $ xVal); echo "
\$aoUsers: [".gettype($aoUsers)."]".AdjustedPrintR($aoUsers)."
";

и т. Д.

0 голосов
/ 23 июня 2010

Во-первых: eval() в вашей функции, на мой взгляд, не служит никакой цели. Почему бы вам не назвать вещи $qry->... напрямую?

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

В-третьих: манипулировать операторами SQL, как правило, очень плохая идея. Он подвержен ошибкам, как только вы наполняете свою функцию чем-то вроде вложенных операторов или другого более сложного кода SQL. Так что просто не делай этого.

Четвертый: я бы не рекомендовал использовать mysqli больше. Вы должны переключиться на PDO .

Насколько я понимаю, ваша функция пытается выяснить, какие поля были в предложении SELECT запроса для построения массива результатов. Это необходимо только в том случае, если вы хотите разрешить слою базы данных выполнять произвольные запросы, что тоже не очень хорошая идея.

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

О eval(): Это полностью и абсолютно зло по нескольким причинам:

  • Это может открыть дверь для внедрения кода.
  • Это делает код нечитаемым для людей и недоступным для IDE
  • Почти невозможно отладить код, который использует eval ()
  • На самом деле не проблема самой eval (), но когда вам приходится использовать его, это признак некорректного дизайна.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...