Итак, вы уже достаточно давно программируете на php, работаете с БД, добавляете, редактируете, удаляете. Когда делаете это, каждый раз прописываете одни и те же действия: подключение, выбор БД, запрос, выборки и т.д.
Каждый раз Вы собираете запрос в отдельную переменную, экранируя все входные данные. непременно забывая это сделать с каким-нибудь числом, ведь кому придет в голову подать вместо ?id=123 что-нибудь вроде ?id=delete from ...
Выборка из БД это тоже великое свершение. Вы делаете запрос, получаете какой-то непонятный контекст. Это не данные, а всего лишь ссылка на них. неясно, как и где они лежат. После прочтения мануала нам предлагают запустить цикл, и каждую его итерацию получать новую строку из БД.
В цикле мы также можем выбирать данные различными способами: можем, как объект, тогда к каждому полю обращаемся так $row->id, есть функции которые возвращают ассоциативный массив, тогда обращаемся так $row['id'], а есть те которые просто возвращают массив данных.
Вы написали программу. Мои поздравления! Она работает. данные крутятся. Вам даже сообщили, что в id можно подавать любые данные, и вы исправили этот баг, в двух местах, конечно забыв про третье.
Пришло время протестировать скрипт на хостинге клиента. Страшно сказать, но он ярый противник linux и apache, купил за большие деньги windows хостинг, с IIS и MsSQL. Ну что же, переписываем пару строк, понимаем, что отличий в работе прилично, и пишем все заново...
Веселая перспектива не правда ли?
ООП с его геттерами, сеттерами,инкапсуляцией и .т.п. придумали не забавы ради. Все выходило из типичной задачи, описанной выше. Многие программисты до сих пор не могут понять почему обращаться напрямую к полю, без использования сеттера, неверно.
<?php class a{ public $b = 1; public function getB(){ return $this ->b; } } $v = new a(); echo $v ->b; // что может быть проще echo $this ->getB(); // очень длинно, к тому же нам пришлось //прописывать у класса дополнительный метод, // а это еще 3 дополнительные строчки |
На фоне такого, простого класса, использование геттера getB кажется избыточным. Предположим, что ситуация изменилась, данные нужно брать не из статики, а из файла.
<?php class a{ public $b = 1; public function getB(){ return file_get_contents ( 'b.txt' ); } } $v = new a(); echo $v ->b; // везде, где применялась эта конструкция придется переписывать код echo $this ->getB(); // в программе ничего не изменилось |
Вернемся к работе с БД. Надеюсь Вам стало очевидно, что нужно использовать класс, который, как можно меньше зависит не только от языка php и его встроенных функций, но и от самой реализации SQL
Представляю Вам, собранный мной класс для работы с mysql. Ссылка на github
<?php /** * @class db * @author leroy <skoder@ya.ru> * @site http://xdan.ru * @version 1.7 */ class db{ public $sql = '' ; public $inq = '' ; public $sqlcount = 0; public $pfx = '' ; private $connid = 0; /** * При инициализации пдключаетсяк MySQL и подключается к нужной БД * * @param $server название хоста * @param $user логин * @param $password пароль * @param $dbname название бд * @param $pfx префикс таблиц, по умолчанию pfx_, т.е. в любом запросе к названию таблиц * будет добавлятся pfx_ * @param $charset кодировка */ function __construct( $server , $user , $password , $dbname , $pfx = 'pfx_' , $charset = "utf8" ){ if ( $this ->connid = @mysql_connect( $server , $user , $password ) ){ $this ->pfx = $pfx ; if ( mysql_select_db( $dbname , $this ->connid) ){ $this ->query( "SET NAMES '" . $charset . "'" ) && $this ->query( "SET CHARSET '" . $charset . "'" ) && $this ->query( "SET CHARACTER SET '" . $charset . "'" ) && $this ->query( "SET SESSION collation_connection = '{$charset}_general_ci'" ); } } else { $this ->error(); } } /** * Выполняет SQL запрос, заменяя #_ на заданный в настройках префикс */ function query( $sql ){ $this ->sql = str_replace ( '#_' , $this ->pfx, $sql ); $this ->sqlcount++; ( $this ->inq = mysql_query( $this ->sql, $this ->connid))|| $this ->error(); return $this ->inq; } /** * Возвращает последний выполненный запрос */ function last(){ return $this ->sql; } /** * Возвращает одну запись из БД соответствующую запросу * * @param $sql SQL запрос * @param $field если не задано то возвращается вся запись, иначе возвращается значение поля $field * @example $db->getRow('select * from #_book where id=12'); // вернет array('id'=>12,'name'=>'Tolkien' ...) * @example $db->getRow('select name from #_book where id=12',name); // вернет 'Tolkien' */ function getRow( $sql , $field = '' ){ $item = mysql_fetch_array( $this ->query( $sql )); return ( $field == '' )? $item : $item [ $field ]; } /** * Перебирает все записи из запроса и передает их в callback функцию * * @param $sql SQL запрос, с префиксом #_ * @param $callback функция, вызываемая к каждой записи запроса, * в параметрах 1) массив, содержащий данные полученной записи 2)указатель на db * @return Возвращает db */ public function each( $sql , $callback ){ $this ->query( $sql ); if ( is_callable ( $callback ) ) while ( $item = mysql_fetch_array( $this ->inq)) call_user_func( $callback , $item , $this ); return $this ; } /** * Изымает лишь запись по ее идентификатору, по умолчанию id * * @param $sTable название таблицы без префикса * @param $id значение идентификатора * @param $fieldname поле по которому производится сравнение, по умолчанию id * @param $field значение поля, которое необходимо вернуть. Если не указано то возвращается вся запись * @return ассоциативный массив либо конкретное значение пи заданном $field * @example $db->getRowById('book',12); // вернет запись о книге с id=12 * @example $db->getRowById('book','Tolkien','name'); // вернет запись о книге с названием которое содержит Tolkien * @example $db->getRowById('book',12,'id','name'); // вернет название книги с id=12 */ public function getRowById( $sTable , $id , $fieldname = 'id' , $field = '' ) { return $this ->getRow( "SELECT * FROM `#_" . $sTable . "` WHERE `$fieldname` ='" . $this ->escape( $id ). "'" , $field ); } /** * Проверяет существует ли запись в таблице с таким идентификатором, если существует то возвращает идентификатор * иначе возвращает false * * @param $sTable название таблицы без префикса * @param $id значение идентификатора * @param $fieldname поле по которому производится сравнение, по умолчанию id * @param $allf дополнительные параметры запроса, обычное sql сравнение * @param $field поле которое необходимо вернуть в случае удачи, по умолчанию равно $fieldname * @return При удаче возвращает значение поля $field, иначе false * @example if( $db->exists('book',12) ) echo 'Книга существует'; * @example if( $db->exists('book','Tolkien','name')!==false ) echo 'Книга содерщащая Tolkien существует'; * @example if( $db->exists('book','Tolkien','name','active="yes" and public="12.09.2008"') ) * echo 'Книга содерщащая Tolkien опубликованная 12.09.2008 существует'; * @example if( ($name=$db->exists('book','%Tolkien%','name','','izdatel'))!==false ) * echo 'Книга содерщащая Tolkien существует ее издал '.$name; */ public function exists( $sTable , $id , $fieldname = 'id' , $allf = '' , $field = '' ){ if ( ! $field ) $field = $fieldname ; $item = $this ->getRow( 'select ' . $field . ' from ' . $this ->pfx. $sTable . ' where `' . $fieldname . '`=\'' . $this ->escape( $id ). '\' ' . $allf ); return isset( $item [ $field ])? $item [ $field ]:false; } /** * @deprecated 1.7 Используйте getRows */ function loadResults( $sql , $field = '' ){ return $this ->getRows( $sql , $field ); } /** * Выдает массив всех записей из запроса * * @param $sql SQL запрос, с префиксом #_ * @param $field если указано это поле, то результирующий массив будет состоять только из значений этого поля * @return Array */ function getRows( $sql , $field = '' ){ $inq = $this ->query( $sql ); $items = array (); while ( $item = @mysql_fetch_array( $inq )) $items [] = ( $field == '' )? $item : $item [ $field ]; return $items ; } /** * Экранирует значение */ function escape( $sql ){ return mysql_real_escape_string( $sql , $this ->connid); } /** * Вставка данных в таблицу * * @param $sTable название таблицы без префикса * @param $values либо строка вида id=12,name="Tolkien", * либо ассоциативный массив вида array('id'=>12,'name'=>'Tolkien') * в случае ассоциативного массива экранировать данные не требуется * @example $db->insert('book','id=12,name="'.$db->escape('Tolkien').'"'); * @example $db->insert('book',array('id'=>12,'name'='Tolkien')); */ function insert( $sTable , $values ){ $ret = $this ->_arrayKeysToSet( $values ); return $this ->query( 'insert into #_' . $sTable . ' set ' . $ret ); return false; } /** * Возвращает значение перичного ключа последней вставленной записи */ function insertid(){ return mysql_insert_id( $this ->connid); } /** * Обновление данных в таблице * * @param $sTable название таблицы без префикса * @param $values либо строка вида id=12,name="Tolkien", * либо ассоциативный массив вида array('id'=>12,'name'=>'Tolkien') * в случае ассоциативного массива экранировать данные не требуется * @param $sWhere условия соответсвия * @example $db->update('book','id=12,name="'.$db->escape('Tolkien').'"','id=5'); * @example $db->update('book',array('id'=>12,'name'='Tolkien'),'where name like %Tolkien%'); */ public function update( $sTable , $values , $sWhere =1 ){ $ret = $this ->_arrayKeysToSet( $values ); return $this ->query( 'update ' . $this ->pfx. $sTable . ' set ' . $ret . ' where ' . $sWhere ); } /** * Удаление данных соответствующих словию */ public function delete ( $sTable , $sWhere ){ return $this ->query( 'delete from ' . $this ->pfx. $sTable . ' where ' . $sWhere ); } private function _arrayKeysToSet( $values ){ $ret = '' ; if ( is_array ( $values ) ){ foreach ( $values as $key => $value ){ if (! empty ( $ret )) $ret .= ',' ; $ret .= "`$key`='" . $this ->escape( $value ). "'" ; } } else $ret = $values ; return $ret ; } private function error(){ $langcharset = 'utf-8' ; echo "<HTML>\n" ; echo "<HEAD>\n" ; echo "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=" . $langcharset . "\">\n" ; echo "<TITLE>MySQL Debugging</TITLE>\n" ; echo "</HEAD>\n" ; echo "<div style=\"border:1px dotted #000000; font-size:11px; font-family:tahoma,verdana,arial; background-color:#f3f3f3; color:#A73C3C; margin:5px; padding:5px;\">" ; echo "<b><font style=\"color:#666666;\">MySQL Debugging</font></b>" ; echo "<li><b>SQL.q :</b> <font style=\"color:#666666;\">" . $this ->sql. "</font></li>" ; echo "<li><b>MySQL.e :</b> <font style=\"color:#666666;\">" .mysql_error(). "</font></li>" ; echo "<li><b>MySQL.e.№ :</b> <font style=\"color:#666666;\">" .mysql_errno(). "</font></li>" ; echo "<li><b>PHP.v :</b> <font style=\"color:#666666;\">" .phpversion(). "\n</font></li>" ; echo "<li><b>Data :</b> <font style=\"color:#666666;\">" . date ( "d.m.Y H:i" ). "\n</font></li>" ; echo "<li><b>Script :</b> <font style=\"color:#666666;\">" . getenv ( "REQUEST_URI" ). "</font></li>" ; echo "<li><b>Refer :</b> <font style=\"color:#666666;\">" . getenv ( "HTTP_REFERER" ). "</li></div>" ; echo "</BODY>\n" ; echo "</HTML>" ; exit (); } } |
Как использовать
Подключение к БД
include "class.db.php" ; $db = new db( 'localhost' , 'root' , '' , 'test_bd' , '' ); |
Простой SQL запрос
$db ->query( 'update #_book set hits=hits+1 where id=12' ); |
Тоже, но менее зависимо от SQL реализации
$db ->update( 'book' , 'hits=hits+1' , 'id=12' ); |
Выборка всех записей из таблицы
$db ->getRows( 'select id from #_book' ); // вернет массив array(array('id'=>12),array('id'=>13)...) $db ->getRows( 'select id from #_book' , 'id' ); // вернет массив array(12,13,...) |
Выборка одной записи
$db ->getRow( 'select id from #_book where id=12' ); // вернет array('id'=>12) |
Вставка записи
$db ->insert( 'book' , array ( 'name' => 'пушкин' )); $db ->insert( 'book' , array ( 'name' => 'лермантов' )); $db ->insert( 'book' , 'izdatel="' . $db ->escape( 'гоголь' ). '"' ); |
Просмотр последнего SQL запроса
$db ->insert( 'book' , array ( 'name' => 'лермонтов' )); echo $db ->last(); // 'insert into pfx_book set name="лермонтов"' |
Идентификатор последней вставленной записи
$db ->insert( 'book' , array ( 'name' => 'лермонтов' )); echo $db ->insertid(); // 145 |
Сообщение об ошибке
$db ->query( 'select * from #_ebook' ); |
- SQL.q : select * from pfx_ebook
- MySQL.e : Table 'codedb.pfx_ebook' doesn't exist
- MySQL.e.№ : 1146
- PHP.v : 5.3.13
- Data : 25.03.2013 13:47
- Script : /index.php
- Refer : http://k8/
Ну и еще одна функция на грани фантастики, вызов для каждой записи из выборки callback функции:
$db ->each( 'select id from #_book' , function ( $item , $db ){ $db ->update( 'book' , 'hits=hits+id' , 'id=' . $item [ 'id' ]); }); |
Как использовать решайте сами, метод на мой взгляд, очень полезный.
Вот и все, надеюсь скрипт сделает Вашу жизнь чуть проще.
Комментарии