Доступ до бази даних з мови програмування PHP
У цій останній статті з серії про Використання веб-сервера для зберігання даних із пристроїв, підключених до Інтернету речей, пояснює, як записувати в базу даних MySQL інформація, яку вузли IoT надсилають на сервер, надсилаючи запити HTTP POST. Читачі цієї статті чи всього блогу можуть бути не дуже знайомі з програмуванням у Мова PHP але звичайно так з програмуванням мікроконтролери мовами C o C + + тому, за винятком деяких деталей, таких як передування знаку долара ($) у змінних, ви зможете слідкувати за прикладами без необхідності додаткових пояснень, оскільки вони були зроблені з дотриманням дуже нейтрального стилю програмування, не специфічного для PHP.
Зберігати інформацію в базі даних
Як пояснюється в статті на Зберігання даних IoT за допомогою запитів HTTP POST до веб-сервера, у кінці заголовків тіло запиту POST містить дані, які надсилаються на сервер. Найпоширенішим способом надсилання цієї інформації на сервер є звичайний текстовий формат, оскільки його легше аналізувати навіть «вручну». Якщо дані, що надсилаються на сервер, є складними, їх буде зручно структурувати, наприклад, за допомогою формату XML o JSON. При звичайному використанні веб-сервера для керування інформацією з пристроїв, підключених до Інтернету речей, структура даних не потрібна, тому нормально надсилати їх у вигляді звичайного тексту у форматі variable=valor
.
У запиті HTTP POST наступного прикладу ресурс (зазвичай веб-сторінка) /iot/grabar_temperatura запитується з сервера polaridad.es і надсилаються три змінні: ne, tp і cr, які відповідно містять значення " 12", "10.26 » і «2.18» Також важливо пам'ятати, що існує порожній рядок, який відокремлює заголовки від даних.
1 2 3 4 | POST /iot/grabar_temperatura HTTP/1.1 Host: polaridad.es ne=12&tp=10.26&cr=2.18 |
Кінцева мета наступного коду PHP надішле на сервер бази даних MySQL наказ SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 | INSERT INTO `calefacciones` ( numero_estancia, temperatura, corriente ) VALUES ( 12, 10.26, 2.18 ); |
За допомогою якого буде створено новий запис (INSERT
)
в базі теплопостачання (INTO
)calefacciones
присвоєння полям (numero_estancia,temperatura,corriente)
значення, що відповідають запиту HTTP POST VALUES (12, 10.26, 2.18)
Підключення до бази даних здійснюється за допомогою функції mysqli_connect
за форматом: mysqli_connect($servidor,$usuario,$clave,$base_datos)
який повертає вказівник на об’єкт підключення та використовує змінні, які визначають доступ (наприклад, ім’я користувача, пароль...), і які були раніше призначені для майбутніх гіпотетичних використання в сценарії.
Щоб визначити, чи з’єднання було успішним, використовується функція mysqli_connect_errno()
який повертає номер помилки, яка могла статися, або нуль (false), якщо з’єднання встановлено правильно. Щоб сповістити про помилки, програма, яка робить запит HTTP, отримує у відповідь нульове значення, у цьому випадку програма, яка виконується в мкКл вузла IoT.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | $fin_linea=PHP_EOL; $servidor=‘localhost’; $usuario=‘pelaez’; $clave=‘1234’; $base_datos=‘base_datos_temperaturas’; $conexion=mysqli_connect($servidor,$usuario,$clave,$base_datos); if(mysqli_connect_errno()) { echo 0; // Devolver el valor 0 para indicar que se ha producido un error } else { $numero_estancia=(int)$_POST[‘ne’]; $temperatura=(float)$_POST[‘tp’]; $corriente=(float)$_POST[‘cr’]; $consulta_sql =‘INSERT INTO calefacciones (numero_estancia,temperatura,corriente) ‘; $consulta_sql.=‘VALUES (‘.$numero_estancia.‘,’.$temperatura.‘,’.$corriente.‘);’; $resultado=mysqli_query($conexion,$consulta_sql); if($resultado) // Si no se ha producido un error al realizar la consulta… { echo mysqli_insert_id($conexion); // Devolver el índice del nuevo registro (¡>0!) } else { echo 0; // Devolver el valor 0 para indicar que se ha producido un error } mysqli_close($conexion); } echo $fin_linea; |
Перед додаванням до тексту, який зберігається в $consulta_sql
з якими складається наказ SQL яка надсилається на сервер бази даних, інформація, що надійшла у змінних запиту POST, попередньо обробляється, як мінімум, щоб уникнути атаки з боку SQL ін'єкція. У попередньому прикладі відбувається примусове перетворення у відповідний тип даних (int)
(ціле) або (float)
(десяткове число з плаваючою комою), чого буде достатньо для усунення можливого зловмисного коду, доданого до даних запиту веб-сервер.
Як видно, в Мова PHP Символ крапки (.) використовується для об’єднання текстів, які утворюють порядок SQL або оператор крапки та знака рівності (.=), щоб додати текст праворуч від того, у якому вже зберігається змінна, а одинарні лапки (‘) також використовуються для включення текстових констант, а не лише символів. Хоча в цьому випадку також можна використовувати подвійні лапки («), в Мова PHP використовуються для обробки вмісту, наприклад, включаючи змінні всередині тексту у форматі $texto="Me llamo $nombre";
як альтернатива формату $texto='Me llamo '.$nombre;
також дозволяючи вам включати лапки одного типу в інший без використання символів екранування щоразу, коли подвійні символи чергуються в одиничних або одинарні в подвійних, як у призначенні $texto='esto no hay que "escaparlo" en PHP';
.
Для виконання запиту до сервера MySQL використовується функція mysqli_query
з форматом mysqli_query($conexion,$consulta_sql)
який приймає як параметри об'єкт-з'єднання з базою даних і текст із замовленням SQL що було складено.
Функція mysqli_query($conexion,$consulta_sql)
повертає об’єкт-курсор, який можна використовувати для перегляду повернутих даних, якщо це можливо, або, як у прикладі вище, для отримання інформації про операцію, зокрема, щоб дізнатися індекс, призначений новому запису, який операція створила в таблиці " нагрівачі» з функцією mysqli_insert_id($conexion)
Значення, яке повертає mysqli_query($conexion,$consulta_sql)
може отримати значення false у логічній операції, щоб визначити, що сталася помилка. У попередньому прикладі він використовується для повернення, як і у випадку помилки підключення, нуля програмі, яка робить запит POST. Таким чином, програма поверне число більше за нуль, яке представляє індекс нового запису, якщо операція правильна, або нуль, якщо операція породжує помилку.
Щоб звільнити ресурси, які були призначені підключенню до бази даних, воно "закривається" за допомогою функції mysqli_close($conexion)
Прочитати інформацію з бази даних
За винятком архітектур для туманні обчислення Більшість вузлів IoT обмежуються надсиланням інформації, отриманої їхніми датчиками, на сервер, тобто веб-сервер Він спілкується з ними лише для збереження інформації, тому в попередньому прикладі значна частина випадків, які виникнуть у цій програмі, уже вирішена. Наступним кроком може бути створення веб-сайту, який показуватиме дані, що відстежуються пристроями, підключеними до Інтернету речей. зовнішній інтерфейс що виходить за межі того, що розглядається в цій серії навчальних посібників.
Що може статися, так це те, що вузол IoT має певну інтерактивність і поводиться по-різному на основі історичних даних або передбачає можливість зміни своєї поведінки відповідно до конфігурації, яка надходить до нього з сервера, або навіть вузол є екраном, який показує графік з даними, які нещодавно відстежувалися, порівняно з даними, отриманими за попередні дати. Для всіх цих ситуацій також цікаво мати можливість читати дані з сервера MySQL через веб-сервер як показано в наступному прикладі, який імітує отримання списку дат станів тривоги, визначених моментами, коли температура перевищувала 40°C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | $fin_linea=PHP_EOL; // Fin de línea. Usar <br> para HTML si se va a mostrar la salida en algún tipo de pantalla o consola no es necesario $servidor=‘localhost’; $usuario=‘pelaez’; $clave=‘1234’; $base_datos=‘base_datos_temperaturas’; $conexion=mysqli_connect($servidor,$usuario,$clave,$base_datos); if(mysqli_connect_errno()) { echo ‘Error al conectar a la base de datos: ‘ . mysqli_connect_error(); } else { $consulta_sql=‘SELECT ‘; $consulta_sql.=‘estancia, temperatura, DAY(fecha), MONTH(fecha), YEAR(fecha), TIME(fecha) ‘; $consulta_sql.=‘FROM valor_temperaturas ‘; $consulta_sql.=‘WHERE temperatura>40.0 ‘; $consulta_sql.=‘ORDER BY fecha DESC;’; $resultado=mysqli_query($conexion,$consulta_sql); // El tercer parámetro de mysqli_query, no usado, es el modo MYSQLI_STORE_RESULT por defecto o MYSQLI_USE_RESULT para grandes cantidades de datos if($resultado) // Si no se ha producido un error al realizar la consulta { $total_resultado=mysqli_num_rows($resultado); if($total_resultado) // Si se ha encontrado algún resultado { echo ‘Se han encontrado ‘.$total_resultado.‘ estados de alarma:’.$fin_linea; for($numero_resultado=0;$numero_resultado<$total_resultado) // Recorrer los resultados { mysqli_data_seek($resultado,$numero_resultado); // Mover el cursor al registro correspondiente (no tendría por qué ser consecutivo) $registro=mysqli_fetch_row($resultado); // Almacenar en un vector los datos del registro echo ‘El ‘.$registro[2]; // Tercer campo de la consulta (día) echo ‘ del ‘.$registro[3]; // Cuarto campo de la consulta (mes) echo ‘ de ‘.$registro[4]; // Quinto campo de la consulta (año) echo ‘ a las ‘.$registro[5]; // Sexto campo de la consulta (hora) echo ‘ en la estancia “‘.$registro[0].‘”‘; // Primer campo de la consulta (estancia) echo ‘ la temperatura superó el máximo de 40°C (‘.$registro[1].‘)’; // Segundo campo de la consulta (temperatura) echo $fin_linea; } } else { echo ‘No se ha encontrado ningún estado de alarma’.$fin_linea; } mysqli_free_result($resultado); } mysqli_close($conexion); } |
У наведеному вище прикладі для запиту до бази даних використовується команда SQL SELECT
за основним форматом SELECT campos FROM tabla WHERE condición ORDER BY campo DESC
з єдиною особливістю додавання функцій у поле дати DAY
, MONTH
, YEAR
y TIME
щоб окремо отримати день, номер місяця, рік і час. Накладена умова полягає в тому, що температура перевищує 40.0 і впорядковується за допомогою поля дати від найвищої (найпоточнішої) до найнижчої (найдавнішої), вказуючи її за допомогою пункту DESC
Перебирати значення, які повертає запит із циклу for
з відомою розмірністю використовується функція mysqli_num_rows($resultado)
який вказує на кількість знайдених записів. З функцією mysqli_data_seek($resultado,$numero_resultado)
курсор результатів можна перемістити в певну позицію, виражену лічильником циклу for
, $numero_resultado
, у прикладі.
Для збереження у векторі полів запису, на які вказує курсор результату, використовується функція mysqli_fetch_row($resultado)
який присвоюється змінній $registro
які пізніше будуть використані для формування фрази з різними значеннями, доступ до них за їхніми індексами.
Після того, як усі значення пройдено, ресурси, призначені результату запиту, звільняються SQL з функцією mysqli_free_result($resultado)
Обробляти інформацію з бази даних. Порівняйте значення.
У деяких випадках зручно централізувати обробку інформації на сервері, навіть якщо це можливо зробити на вузлах IoT у стилі туманні обчислення. У наступному прикладі причинами, які симулюються для цього, є безпека; Вузол має інформацію про свій ключ (замок) і про запит (ключ), але не знає, чи доцільно поступитися комбінацією обох, тому він повинен звернутися до сервера, який приймає рішення та інформує вузол, відповідаючи нулем (щоб вказати на невдале порівняння) або одиницею (щоб вказати, що порівняння було успішним) на основі результату запиту до вашої бази даних.
За допомогою цього виправдання ви можете побачити приклад, у якому дані отримуються з пристрою, підключеного до Інтернету речей (код ключа та код блокування), повертається результат (один або нуль залежно від того, чи є результат істинним чи хибним) і виконується невелика обробка інформації, яка складається з порівняння результатів, отриманих під час звернення до бази даних, з результатами, надісланими вузлом IoT.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | $fin_linea=PHP_EOL; $servidor=‘localhost’; $usuario=‘pelaez’; $clave=‘1234’; $base_datos=‘base_datos_puertas’; $conexion=mysqli_connect($servidor,$usuario,$clave,$base_datos); if(mysqli_connect_errno()) { echo 0; // Devolver el valor 0 para indicar que la comparación no es válida o que se ha producido un error (en este caso es un error) } else { $cerradura=hexdec($_POST[“c”]); $llave=hexdec($_POST[“l”]); $consulta_sql=‘SELECT llave FROM cerraduras WHERE cerradura=”.$cerradura.“;’; $resultado=mysqli_query($conexion,$consulta_sql); if($resultado) // Si no se ha producido un error al realizar la consulta { $total_resultado=mysqli_num_rows($resultado); if($total_resultado) // Si se ha encontrado algún resultado { $numero_resultado=0; $buscando_cerradura=TRUE; while($buscando_cerradura&&$numero_resultado<$total_resultado) { mysqli_data_seek($resultado,$numero_resultado); $registro=mysqli_fetch_row($resultado); if($registro[0]==$llave) { $buscando_cerradura=FALSE; } else { $numero_resultado++; } } // echo !$buscando_cerradura; if($buscando_cerradura) { echo 0; // Devolver el valor 0 para indicar que la comparación no es válida (o que se ha producido un error; y aquuí no es el caso) } else { echo 1; // Devolver el valor 1 para indicar que la comparación SÍ es válida } } else { echo 0; // Devolver el valor 0 para indicar que la comparación no es válida o que se ha producido un error } } else { echo 0; // Devolver el valor 0 para indicar que la comparación no es válida o que se ha producido un error } mysqli_close($conexion); } echo $fin_linea; |
У попередньому прикладі функція hexdec використовується для отримання десяткового числа з тексту, який представляє шістнадцяткове число, яке надсилає пристрій IoT. Додатковою перевагою використання цієї функції є уникнення, як пояснювалося раніше, атаки шляхом додавання коду SQL шкідливий для даних запиту POST.
Дати коментар