Заявки към MySQL през PHP

Заявки към MySQL през PHP

В PHP, MySQL

За кого е предназначен този урок?

Този урок е предназначен за начинаещи програмисти, които искат да се научат да работят с бази данни и да обработват информация чрез php и mysql.

Какво ще създадем?

Нищо – ще говорим за теорията на заявките към MySQL през PHP. В този урок ще разглеждаме синтаксиса на заявките за създаване, променяне и унищожаване на бази данни, както и за извличане, записване и изтриване на информация в бази данни чрез функциите на PHP за работа с MySQL. Също така – за бази данни от гледна точка на PHP, без да разглеждаме реалната работа с myphpadmin.

Да започваме…

Връзка с базата данни

За да извършваме заявки към бази данни, независимо дали с тях ще внасяме, изтриваме или взимаме информация, трябва да установим връзка със сървъра. Това става чрез няколко вградени в php функции, но за да си спестим многократно викане на един и същ набор функции, ще създадем наша, потребителска функция, която да ни предава връзка с базата данни по начин, по който на нас ни е удобен.

localhost, username и password

Връзките с базите данни стават през потребител, на който са му зададени определени права. В реални условия всички връзки с базата данни трябва да са защитени с парола. При работа в уеб, трябва да имате готова база данни и потребител, причислен към нея. Това обикновено става в настройките на хостинга (за това ще говорим друг път). За целта на урока, ще предположим, че имаме база, която се казва user_db и за нея сме създали потребител user_dbu с парола userpass. localhost е името на сървъра, през който ще се свързваме – ако базата и приложението ни се хостват на един сървър, винаги имаме localhost.

Потребителска функция db_connect()

<?php
function db_connect()
{
	$dbname = 'user_db';
	$result = mysql_pconnect('localhost', 'user_dbu', 'userpass');
	if (!$result)
		return false;
	if (!mysql_select_db($dbname))
		return false;
	mysql_query('set names utf8');
	return $result;
}
?>;

В тази функция правим три основни неща:

  1. Установяваме постоянна връзка с mysql сървъра чрез mysql_pconnect(). Тази вградена функция в php приема аргументи име на sql сървър, име на потребител и парола. Ако установяването на връзка е невъзможно, функцията ни връща стойност false. Използваме тази функция, защото искаме постоянна връзка, която да остане отворена и след приключване на изпълнението на скрипта. Ако използваме mysql_connect(), връзката ще се затвори щом скрипта ни се изпълни.
  2. Функцията проверява дали има база данни с името, което е зададено в променливата $dbname. Ако такава база няма, функцията връща false.
  3. След това осъществяваме заявка към базата, която да я застави при всяко свързване да връща резултатите, енкодирани в utf-8. Това е много важно, защото ако не го направим, а базата ни пази информацията в друг формат, ще видим ????? или квадратчета или просто деформиран текст с някакви нечетивни символи, които трудно минават за букви.

Връзката ни е установена.

mysql_query()

Тази функция е в основата на заявките към базата данни – всичката информация, която ще предаваме на сървъра или ще изискваме от него се подава през mysql_query() под формата на низ, съдържащ команда към сървъра на базата данни.

За да работи правилно и да имаме достъп до резултата, mysql_query() трябва да бъде присвоена на променлива, най-често $result. Функцията връща ресурс, до който можем да достигнем след като го обработим с други функции за работа с mysql.

Заявка за създаване на таблица

За да създадем таблица, потребителят ни трябва да има право да създава таблици. В противен случай всеки опит на потребител без необходимите права ще води до грешка. Нашия хипотетичен потребител има пълни права, така че е способен да създава таблици.

В реална обстановка давайте пълни права на потребители, които имат изцяло административни функции. Потребителят, с който ще се дава достъп до ресурсите на базата данни на посетителите на Вашето уеб приложение не бива да има пълни права, за да се намали максимално вероятността от злоупотреба!

Заявките са низове – с други думи, текст. Те се четат като текст и от хората и от сървъра, което спомага много откриването на грешки. За да създадем таблица в нашата база данни, първо трябва да си изясним каква ще е нейната структура. Нека създадем таблица, която да пази текстовата информация, която ще разпределяме по страниците на нашето приложение. За целта, ще създадем таблица, идентична с тази, която създавахме в урока „Проектиране на линкова структура с .htaccess и mod_rewrite„:

<?php
$conn = db_connect();
if (!$conn){
     echo 'Базата данни е недостъпна, опитайте по-късно';
     die();
}
$sql = mysql_query("CREATE TABLE  `pages`.`user_db`
(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 200 ) CHARACTER SET cp1251 COLLATE cp1251_bulgarian_ci NOT NULL ,
`content` TEXT CHARACTER SET cp1251 COLLATE cp1251_bulgarian_ci NOT NULL
) ;");
?>

Този сегмент първо установява връзка с функцията ни db_connect(). Ако тя върне връзка, продължава изпълнението, ако не – печата съобщение за грешка и прекратява скрипта.

На следващия ред, на $sql се присвоява резултата от изпълнението на заявката, която ни създава таблица pages с едно ключово поле id (чиято стойност е зададена да бъде целочислен тип и да се увеличава с едно – AUTO_INCREMENT, така че всеки запис в таблицата да е с уникален идентификатор), title, което е зададено като низов тип с максимална дължина 200 символа, decription, което е описание за мета таговете на HTML-а и content, който е дефиниран като текстово поле.

За да може потребителя да разбере дали таблицата е създадена успешно, трябва да му кажем какво се е случило със заявката ни. Затова сега ще променим кода така, че да правим проверка какъв е статуса на заявката и ще накараме скрипта да реагира според различните сценарии:

<?php
$conn = db_connect();
if (!$conn){
     echo 'Базата данни е недостъпна, опитайте по-късно';
     die();
}
$sql = mysql_query("CREATE TABLE  `pages`.`user_db`
(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 200 ) CHARACTER SET cp1251 COLLATE cp1251_bulgarian_ci NOT NULL ,
`description` VARCHAR( 200 ) CHARACTER SET cp1251 COLLATE cp1251_bulgarian_ci NOT NULL ,
`content` TEXT CHARACTER SET cp1251 COLLATE cp1251_bulgarian_ci NOT NULL
) ;");
if (!$sql){
 echo 'Заявката Ви се провали. Опитайте по-късно';
 die();
}
else
 echo 'Таблицата е създадена.';
?>

Промяна на таблици в бази данни

Вече имаме таблица. Сега обаче се сещаме, че ще е добре към съдържанието ни, да има и изображение, а всъщност описанието не е толкова необходимо, тъй като можем да ползваме и content. Това означава, че трябва да добавим нова колона в таблицата, която да описва типа на данните, запаметявани в нея и името й и да изтрием съществуваща. За целта ще ползваме заявката ALTER:

<?php
$conn = db_connect();
if (!$conn){
     echo 'Базата данни е недостъпна, опитайте по-късно';
     die();
}
$sql = mysql_query("ALTER TABLE  `pages` ADD  `image` VARCHAR( 200 ) NOT NULL AFTER  `id` AND DROP `description`");
if (!$sql){
 echo 'Промяната е неуспешна. Опитайте по-късно';
 die();
}
else
 echo 'Промяната е успешна';
?>

Този фрагмент казва на сървъра, че ще променяме таблицата pages с командата ALTER TABLE. Командата ADD казва на сървъра да добави текстова колона с максимална дължина 200 символа image и чрез командата DROP казваме да изтрие колоната description. За да изтрие цялата таблица, заявката ни трябва да е:

mysql_query("DROP TABLE `pages`");

Въвеждане на запис в база данни

Така – вече имаме необходимата ни база данни с една таблица. Нека внесем в нея някаква информация. Да предположим, че сме създали html документ с форма, която е пратил с метода post до файла ни променливите:

$title   = addslashes($_POST['title']);
$content = addslashes($_POST['content']);
$image   = $_FILE['image']['name'];

Тези ни променливи приемат стойностите от форматa и са готови да бъдат приети от базата. Преди да работим с променливите и да правим с тях каквото и да е трябва да сме сигурни, че стойностите им не могат да навредят на кода ни или на базата. Затова използваме функцията addslashes(), която добавя „\“ пред всеки специален символ като кавички и апострофи. По този начин ако в стойността на променливата има кавичка или апостроф, запис от вида:

print "Променливата е".$content;

няма да доведе до грешка. След като сме се презастраховали с addslashes(), е време да пристъпим към вписване на данните в базата. Това става чрез командата INSERT INTO:

<?php
$conn = db_connect();
if (!$conn){
     echo 'Базата данни е недостъпна, опитайте по-късно';
     die();
}
$sql = mysql_query("INSERT INTO  `pages` (
`id` ,
`title` ,
`content` ,
`image`
)
VALUES (
NULL ,  '$title',  '$content', '$image')");
if (!$sql){
 echo 'Въвеждането не беше успешно. Опитайте по-късно';
 die();
}
else
 echo 'Въвеждането успешно';
?>

Командата INSERT работи с две конструкции. Както виждаме в кода по-горе – INSERT INTO иска да се посочи таблицата, в която ще се въвеждат данни и след това, оградени в скоби следват полетата, в които ще въвеждаме. След това с конструкцията VALUES () изреждаме всички стойности Тъй като цялата ни заявка е оградена с кавички можем директно да поставяме променливите без да ги ограждаме с ‘.$value.’. Синтаксисът на mysql изисква променливите да са оградени с апострофи, за да може базата да разпознава началото и края на всяка променлива.

За полето id даваме стойност NULL, защото няма как да знаем каква е тя. За разлика от другите полета, полето id се попълва от сървъра на базата, а не от потребителя и трябва да оставим сървъра да добавя стойност каквато прецени. При въвеждане на нов запис, ако id няма стойност, както сме направили в тази заявка, сървърът веднага проверява кой е най-високия номер, наличен в таблицата, увеличава го с едно и го присвоява на записа.

В случая изреждаме всички полета, но това не е задължително – ако имаме да въвеждаме информация само в content можем да кажем на базата да въвежда само в нужните ни полета кратката форма на INSERT:

<?php
$conn = db_connect();
if (!$conn){
     echo 'Базата данни е недостъпна, опитайте по-късно';
     die();
}
$sql = mysql_query("INSERT INTO  `pages` (`content`) VALUES ('$content')");
if (!$sql){
 echo 'Въвеждането не беше успешно. Опитайте по-късно';
 die();
}
else
 echo 'Въвеждането успешно';
?>

Извличане на записи от базата данни

За да разпечатаме всички записи от базата данни в списък трябва да използваме конструкцията SELECT:

$sql = "SELECT * FROM `pages` ORDER BY `id` DESC";
$db = db_connect();
if (!$db)
{
   // при несвързване с базата изкарва съобщение и прекратява скрипта
   echo 'Базата данни е временно недостъпна. Моля, опитайте по-късно.';
   break;
}
// заявка към базата
$result = mysql_query($sql);
$num_results = mysql_num_rows($result);
for ($i=0; $i < $num_results; $i++)
{
    // извеждаме резултатите
   $row = mysql_fetch_array ($result);
   echo '
   <h1><a href="article.php?id='.$row['id'].'">'.$row['title'].'</a></h1>
   <p>'.$row['content'].'</p>';
}

Ако бяхме задали

$sql = "SELECT `id`,`title` FROM `pages`";

базата щеше да ни върне стойностите само от колоните id и content.

  1. Изграждаме заявката си: SELECT * FROM `pages` казва на базата да избере всички колони от pages.
  2. Подаваме низа със заявката на mysql_query() и присвояваме резултата от заявката на променливата $result.
  3. На променливата $num_results присвояваме стойността от функцията mysql_num_rows($result). mysql_num_rows() приема за аргумент $result. Тя ни връща броя на редовете на таблицата, които са върнати от заявката. Получаваме числото на броя редове, за да знаем колко реда ще е списъка.
  4. В цикъла for() задаваме брояч $i, който ще се увеличава с едно докато не стане равен на $num_results.
  5. Променливата $row приема като стойност асоциативен масив за текущия ред, който връща функцията mysql_fetch_array($result).
  6. За всеки ред от заявката, ще се изпълнява присвояването на текущ ред на $row и печатаме html съдържанието. За да отпечатаме стойност от дадена клетка в таблицата викаме записа от асоциативния масив $row[‘име-на-колоната’].

Извличане на един конкретен ред от таблицата

Не е задължително да печатаме информацията, след като я извлечем. Този скрипт е полезен, когато искаме да обработваме всеки ред и сме сигурни, че има вероятност те да са над 1 на брой. Ако искаме да извлечем един конкретен ред от таблицата е излишно да прибавяме for(). В този случай е добре да използваме друг подход:

function get_article_data($id)
{
   $conn = db_connect();
   $query = "SELECT * FROM `pages` WHERE `id` = '$id'";
   $result = mysql_query($query);
   if (!$result)
     return false;
   $result = mysql_fetch_array($result);
   return $result;
}

Както виждаме заявката изисква един конкретен запис, тъй като id е уникално като стойност за цялата таблица. Тогава няма смисъл да търсим колко реда има резултата, защото вече знаем – 1 ред. Затова проверяваме дали имаме резултат. Ако нямаме резултат връщаме false. В противен случай директно присвояваме асоциативния масив на $result чрез mysql_fetch_array() и го обработваме, както пожелаем. В този пример го връщаме. Този код е хубав за една потребителска функция, която да приема аргумент $id и да връща информация за записа, който ни интересува.

Извличане на данни от една клетка в таблицата

Но какво ще стане ако търсим само една клетка от таблицата? Какво ще стане, ако примерно търсим заглавието на статия с id = 4? Тогава тази функция ще ни върне и съдържанието, и идентификационния номер, и изображението. А това в случая е излишно. Затова трябва да обработим заявката така, че да спести процесорно време и да ни върне само каквото ни трябва:

function get_title($id)
{
   $conn = db_connect();
   $query = "SELECT * FROM `pages` WHERE `id` = '$id'";
   $result = mysql_query($query);
   if (!$result)
   	return false;
   else
   {
   $title = mysql_result($result, 0, 'title');
   return $title;
   }
}

Тук всичко е същото, освен аргументите на mysql_result(). Те се тълкуват така: върни в $title стойността от колоната title от нулевия ред. Нулевия, защото нямаме друг, а масивите винаги почват с нулев ред.

Ако търсехме съдържанието, щяхме да зададем реда така:

$title = mysql_result($result, 0, 'content');

Така – ако продължим с размислите, функцията може да стане още по-динамична, като я преработим така:

function get_cell($id,$field)
{
   $conn = db_connect();
   $query = "SELECT * FROM `pages` WHERE `id` = '$id'";
   $result = mysql_query($query);
   if (!$result)
   	return false;
   else
   {
   $cell = mysql_result($result, 0, $field);
   return $cell;
   }
}

Така функцията ни позволява да взимаме който и да е запис, в която и да е клетка в таблицата.

Извличане на редове от таблица с условие за маскиране

А какво ще стане ако търсим запис от таблицата, който има заглавие, съдържащо буквата „о“ и в съдържанието да има думата „петък“?

Тогава ще използваме условие в заявката си. То има следната форма:

function get_query()
{
   $conn = db_connect();
   $query = "SELECT * FROM `pages` WHERE `title` LIKE '%o%' AND `content` LIKE '%петък%'";
   $result = mysql_query($query);
   if (!$result)
   	return false;
   else
   {
   $title = mysql_result($result, 0, 'title');
   return $title;
   }
}

Тази заявка търси едновременно по две условия – търси всички редове, които съдържат буквата „o“ в заглавието и думата „петък“ в съдържанието. На този принцип се изграждат търсачки.

Изтриване на запис в база данни

Ето какво ни остана – унищожаване на запис от база данни. Както сигурно се досещате – запис от базата се изтрива с DELETE. Изтриването става пак чрез заявка и тя изглежда така:

<?php
$conn = db_connect();
if (!$conn){
     echo 'Базата данни е недостъпна, опитайте по-късно';
     die();
}
$sql = mysql_query("DELETE FROM  `pages` WHERE `id` = '$id'");
if (!$sql){
 echo 'Въвеждането не беше успешно. Опитайте по-късно';
 die();
}
else
 echo 'Въвеждането успешно';
?>

Тази заявка изтрива запис с id = $id.

Това са основите в изграждането на заявки с бази данни. Естествено, съществуват още много тънкости – съединяване на таблици и т.н., но те са въпрос на време и тренировка, а този урок е за по-прости техники. Надявам се, че ви е бил полезен. 🙂

За Гергин Борисов

+359 877080887

Здравейте, аз съм Гергин Борисов, на 24 години от София и се занимавам с уеб и лого дизайн, предпечат и отскоро - с блога си. Занимавам се с дизайн от 2006та година насам, като преди това (от 2004та) работех в сферата на предпечата с баща ми, фотографът Александър Борисов.