Решил поделиться своими наработками в части работы с базой данных mySql с применением языка PHP. Сразу оговорюсь, объектно-ориентированных подход в данном случае не используется, все написано не в плане максимально приближения к идеалу, а в плане максимального упрощения программирования. Дополнительными плюсами использования данной библиотеки являются: - В глобальной переменной $sql_time всегда хранится время выполнения всех sql запросов - При установке значения $debug[error] = true; на экран выводятся все ошибки исполнения запросов - При установке значения $debug[sql] = true; на экран выводятся все выполняемые запросы + время на выполнения каждого Минусы тоже присутствуют: - Во всех текстовых полях нельзя использовать знак #, удаляем, заменяем, но быть его не должно - Если в таблице нет auto_increment поля insertTable вернет 0 И еще один минус, через месяц работы с этой библиотекой вы забудете как на самом деле по шагам должны были работать с mySql, я к примеру уже не помню Подключение к базе данных, не мучайте себя безумными кусками кода, которые приходиться постоянно вставлять в различные файлы: Код (Text): $dbh = @mysql_connect($mysql_host, $mysql_user, $mysql_pass); if (!@mysql_select_db($mysql_database, $dbh)) { errorLog("Mysql server $mysql_host may be down\n", "error.fatal.log"); @mysql_close($dbh); exit(); } execSql("SET NAMES 'cp1251';"); register_shutdown_function(exitDb); при использовании библиотеки: Код (Text): connectMysql($mysql_database, $mysql_host, $mysql_user, $mysql_pass); Далее очень часто нам необходимо получить всего одну строку: Код (Text): $sql = "SELECT * FROM table WHERE key='some' LIMIT 0,1"; $result = mysql_query($sql); $part = fetchArray($result); При использовании библиотеки: Код (Text): $part = getOneRow("table", "key='some'"); Получение количества строк Код (Text): $sql = "SELECT COUNT(*) as numRows FROM table WHERE key='some'"; $result = mysql_query($sql); $part = fetchArray($result); $numRows = $part[numRows]; С использованием библиотеки: Код (Text): $numRows = getNumRows ("table", "key='some'"); Вставляем новые строки в базу данных Код (Text): $sql = "INSERT INTO table (field1, field2) values ('value1', 'value2')"; $result = mysql_query($sql); $lastId = mysql_insert_id(); С использованием библиотеки: Код (Text): $lastId = insertTable("table", "", "field1# field2", "$value1# $value2"); Обновляем строки в базе данных Код (Text): $sql = "UPDATE table SET field1='value1', field2='value2' WHERE key='some'"; $result = mysql_query($sql); $numRows = mysql_affected_rows (); С использованием библиотеки: Код (Text): $numRows = insertTable("table", "", "field1# field2", "$value1# $value2"); Бывают ситуации, когда мы неуверенны, есть ли в базе данных данная запись, но сохранить данные необходимо Код (Text): If (getNumRows("table", "where")) { updateTable("table", "where", "fields", "values"); } else { insertTable("table", "", "fields", "values"); } Код (Text): $numRows = modifyTable("table", "key='some'", "field1# field2", "$value1# $value2"); Вот собственно и все, вопросы комментарии?
Собственно сама библиотека PHP: <? // =========================================================================================================== // SQL Class // VER. 10.0.0.0 // // Developed by Miftahov Nariman. // [url=http://vseznaut.ru/]http://vseznaut.ru/[/url] // [email=miftahovn@gmail.com]miftahovn@gmail.com[/email] // =========================================================================================================== // Подключение к базе данных // =============================================================================== function connectMysql($mysql_database, $mysql_host, $mysql_user, $mysql_pass) { global $dbh; $dbh = @mysql_connect($mysql_host, $mysql_user, $mysql_pass); if (!@mysql_select_db($mysql_database, $dbh)) { errorLog("Mysql server $mysql_host may be down\n", "error.fatal.log"); @mysql_close($dbh); exit(); } execSql("SET NAMES 'cp1251';"); register_shutdown_function(exitDb); } // Функция завершения связи с Mysql. Вызывается тихо, но всегда // =============================================================================== function exitDb() { global $dbh; flush(); @mysql_close($dbh); } // Получаем результат запроса // =============================================================================== function getResults($table, $where="1") { $sql = "SELECT * FROM ".$table." WHERE ".$where; return execSql($sql); } // Здесь должны выполнятся все SQL выражения! // ========================================== function execSql($sql) { global $_SESSION, $sql_time, $debug; // ======================================= $this_time = getmicrotime(); if ($result=@mysql_query($sql)) { $end_time = getmicrotime(); $spent_time = $end_time - $this_time; $sql_time += $spent_time; if ($debug[sql]) { echo sprintf("%01.2f", $spent_time)." + "; echo $sql."<br>"; } return $result; } else { if ($debug[error]) { echo substr($sql, 0, 5000); echo "<br>".mysql_errno().": ".mysql_error(); } return false; } } // Fetch // Согласен некрасиво, но длинное выражение запомнить не удается -) // =============================================================================== function fetchArray($result) { return mysql_fetch_array($result); } // Получаем одну строку //================================================================================ function getOneRow($table, $where) { if (!eregi("LIMIT", $where)) { $where .= " LIMIT 0, 1"; } if ($result = getResults($table, $where)) { if ($fetch = fetchArray($result)) { return $fetch; } } return false; } // Получаем количество строк // =============================================================================== function getNumRows($table, $where) { $sql = "SELECT COUNT(*) as numRows FROM $table WHERE $where"; return mysql_result(execSql($sql), 0, 0); } // Удаление из таблицы // =============================================================================== function deleteFrom($table, $where) { $sql = "DELETE FROM ".$table." WHERE ".$where; if (execSql($sql)) { return mysql_affected_rows(); } else { return false; } } // InsertTable // Поля fields и $values должны быть представлены в виде "test1# test2# test3" // ========================================================================================== function insertTable($table, $where, $fields, $values) { $fields = explode("# ", $fields); $values = explode("# ", $values); while (list($key, $field) = each($fields)) { if ($field_list) $field_list .= ", "; $field_list .= $field; } while (list($key, $value) = each($values)) { if ($value_list) $value_list .= ", "; $value_list .= "'$value'"; } $sql = "INSERT INTO ".$table." (".$field_list.") values (".$value_list.")"; // Возвращает последний индекс вставки // =================================== if (execSql($sql)) { return mysql_insert_id(); } else { return false; } } // Update table // Поля fields и $values должны быть представлены в виде "test1# test2# test3" // =========================================================================================== function updateTable($table, $where, $fields, $values) { $fields = explode("# ", $fields); $values = explode("# ", $values); if (!fill($where)) { return false; } while (list($key, $field) = each($fields)) { list($key, $value) = each($values); if ($set) $set .= ", "; // Если знак @ то не ставим кавычки для SET on=on+1 // ------------------------------------------------ if (substr($value, 0, 1) == "@") { $set .= "$field=".substr($value, 1, 128); } else { $set .= "$field='$value'"; } } $sql = "UPDATE ".$table." SET ".$set." WHERE ".$where; // Возвращает число затронутых строк // ================================= if (execSql($sql)) { return mysql_affected_rows(); } else { return false; } } // Insert OR Update //=============================================================================== function modifyTable($table, $where, $fields, $values) { // Получаем результат // ------------------------------------- if ($where) { $num = getNumRows($table, $where); } if ($num) { return updateTable($table, $where, $fields, $values); } else { return insertTable($table, $where, $fields, $values); } } ?>
по сабжу: пишется новичком за полчаса. Пользы не так много, ввод данных можно сделать лучше. Массы глобальных переменных, зачем-то сессии подтянуты. Разбивать и сливать массивы можно проще и быстрее. Весь смысл не в том, чтобы забыть синтаксис, а чтобы унифицировать обработку данных. На эту тему тут и ломают копья. Есть лишние запросы. Сам код коряв, постестялся бы его выкладывать в таком виде. то есть не пишешь вообще кроме хелло ворлд? это ваще что? В общем, пример, как делать не надо.
miftahovn Ухх... это довольно серьезное ограничение. Я бы сказал, это грабли с ядерной боеголовкой для разработчика Можно ведь передавать значения в массиве, а не одной строкой, используя разделитель.
Что значит унифицировать обработку данных? Лично для меня стоит задача, как можно более упростить написание кода, а уже затем унификация, рационализация и другое. Какие именно запросы лишние? Что именно криво? PS: Слово "постеснялся" пишется через "н" Код (Text): if (substr($value, 0, 1) == "@") { $set .= "$field=".substr($value, 1, 128); } else { $set .= "$field='$value'"; } Есть два варианта работы с updateTable() 1. Код (Text): updateTable("table", "where", "summ# count", "1# 2"); В итоге выполнит запрос вида: UPDATE table SET summ='1', count='2' WHERE where 2. Код (Text): updateTable("table", "where", "summ# count", "1# @count+1"); В итоге выполнит запрос вида: UPDATE table SET summ='1', count=count+1 WHERE where
Можно, но тогда сам процесс написания запроса усложняется на порядок ... PS: Две функции которые используются в библиотеке, но в её текст не вошли: PHP: <? $ROOT = $_SERVER["DOCUMENT_ROOT"]."/"; function errorLog($string, $location) { global $ROOT; $string = date("H:i:s d-m-Y")." | ".$string."\n"; $location = $ROOT.".temp/logs/".$location; error_log($string, 3, $location); echo $string."<br>"; return true; } function getmicrotime() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } ?> [/php]
чтобы добавление данных в таблицу клиентов и в таблицу товаров было единообразно. писать select aa,bb... вместо $db('aa # bb', нагляднее, дописать query и mysql_fetch_assoc не проблема и не снижает читабельность кода. смысл классов для обработки данных не в этом.
Что значит добавление в таблицу клиентов и товаров единообразно, пример? Если имеется ввиду возможность каскадного обновления нескольких таблиц применительно к свойствам, собираемой статистике объектов, то это совершенно другой разговор пишите классы, наследуйте их, описывайте свойства объектов в виде свойств класса и будет необходимый результат. Здесь же я представил пример библиотеки, которая является промежуточным звеном к mySql, и не берет на себя никаких функций касающихся представлению данных.
нет, не в этом дело. Библиотека не дает ничего, кроме порчи данных и добавления различного синтаксиса ввода данных. Функционал даже инсерта недостаточен. Никакого назначения она не выполняет.
miftahovn Совсем необязательно - в PHP есть понятие ассоциативного массива: PHP: <?php $values=array( "id"=>5, "title"=>"Book", "price"=>3000); insertTable("table",$values); ?>
Вот за одно это я отрываю своим программерам руки. Дальше уже читать нет смысла. Все верно. Уважаемый, уберите рекламу, в противном случае через пару дней эта тема отправится в топку, и вы следом.
И много у Вас Олег программеров своих которым вы отрываете руки? Мифтахов Нариман, Павлодар Казахстан, Телецентр, ул. Павлова. Вы можете говорить и писать все что угодно, но я поверю в это только тогда, когда Вы мне покажете свои проекты. К примеру мой сайт http://students.tomsk.ru 5500 хостов 360000 хитов в сутки http://tbe.tom.ru/date/2007-7-23 55 000 пользователей и 28 миллионов записей в таблицах. Еще раз говорю эта библиотека просто работает, и упрощает жизнь, хотите использовать всю мощь SQL пользуйтесь полными запросами...
Хочу. Количество разве говорит о качестве? Даже проекты — не показатель. Лучший показатель — замеры времени эффективности работы вашей библиотечки, если вам уж так хочется что то доказать кому-то здесь. Вы правы. Эта библиотечка просто работает. Обратного никто и не утверждал. А эффективность ее работы, и даже использования — стоит очень остро. Если вы не хотите это обсуждать, зачем вы вообще здесь? Благодарю, что убрали рекламу. Приятного общения. ЗЫ. Если хочется цифирками мерятся: Код (Text): SQL*Plus: Release 9.0.1.0.1 - Production on Сбт Июл 28 12:30:48 2007 (c) Copyright 2001 Oracle Corporation. All rights reserved. Присоединен к: Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.4.0 - Production SQL> select count(*) from ALL_TABLES; COUNT(*) ---------- 1765 SQL> Правда, у меня не все таблицы под моим аккаунтом видны ))
насмешил, если уж тут PHP клуб, то мерятся именно веб-проектами, я тоже могу сделать COUNT всех таблиц в рабочей базе данных MS Axapta, хранимых в Oracle но те таблицы далеко не моих рук дело... пусть за них будет весело и радостно NAVISION и Microsoft ...
miftahovn, нет, это таблицы приложений нашего отдела, и веб-приложений в частности. Мерится надо не количеством, а качеством. Простите, но тут я не вижу качества.
miftahovn веб-проект имеет все права использовать оракл в качестве базы Горбунов Олег ты же знаешь, к чему здесь приводят соревнования вроде "у кого больше таблиц" ;-)
stas_t, Ну вот почему если я нехочу уезжать с родного города, все считают, что я не могу, потому что я ламер?
у меня начальная . зарезервирована для команд веб интерфейсу, с разделителем для данных передаваемых командой , это дело работает только в интерфейсе поиска, а начальная# там же зарезервирована для мультипоиска по таблицам. За это тоже отрывают руки? (за совмещение командной строки и поисковика)?
извините, что встреваю, но содержание вашей беседы настолько меня заинтересовало, что я не смог остаться в стороне и не высказаться. вы можете мне не верить, но, по-моему, код PHP: <?php $sql = sprintf ("insert into users (usr_login, usr_pass, usr_name) values ('%s', '%s', '%s')" , mysql_real_escape_string ($login) , md5 ($pass) , mysql_real_escape_string ($name) ); db_dml ($sql); ?> гораздо надёжнее, чем, скажем, PHP: <?php sql_insert ('users', array ('login'=>$login, 'pass'=>$pass, 'name'=>$name)); ?> ибо в конечном случае второй вариант всё равно должен привести к первому, но приведёт или нет -- вы не можете быть уверены, пока не разберётесь с внутренностями этой самой sql_insert. и это, как видите, элементарнейший запрос. в случае, если вам надо соединять таблицы по сложным условиям, группировать записи, осуществлять сортировки и пр. гораздо спокойнее написать сам запрос, чем пытаться описать всё это же в рамках другого языка-посредника. другое дело, если вы не хотите знать sql, а пытаетесь вместо него использовать или изобрести некий новый апишник, который, как по волшебству, произведёт на свет правильный sql-запрос. может, произведёт, а, может, и нет. имеем аналогичную ситуацию, когда для того, чтобы общаться на иностранном языке с интересными людьми, вы не учите язык, а используете программу-переводчик. вас, конечно, поймут. но могут быть и нюансы (с) я согласен, что mysql api для php можно чуток подправить, чтобы получить запись из базы можно было одной строкой кода, при этом зная, что в случае ошибки в sql-команде (чего не должно быть никогда) или подключении (что может произойти когда угодно) эта ошибка будет правильно обработана, записана в лог и отослана по мылу. но sql запрос я бы не доверял строить машине -- уж очень много тонкостей, которые нужно контролировать самому программисту. и чем наворачивать дополнительные апишники с искусственным интеллектом, лучше устроиться на любимом диване и полистать в очередной раз главку 6 мускульного мануала.