News & Blog

CRUD – PDO – 2. rész

News & Blog

Okosítsunk

Ha még nem olvastad, olvasd el előbb ezt a bejegyzést: CRUD – PDO – 1. rész

Többé kevésbé működik már a programunk, de azért két hibája van: buta és csúnya. Ebben a részben próbáljuk egy kicsit felokosítani. Egyrészt a törlést is illene külön fájlban megvalósítani (Titkolt cél volt annak bemutatása, hogy az index.php állományra is rábízhatjuk a feladatok megvalósítását.), illetve ki tudná a törlésnél és a szerkesztésnél kitalálni, hogy mi a törlendő rekord azonosítója. Sokkal jobb lenne a törlendő rekordot egy listából kiválasztani. Ezt is megvalósítjuk. Harmadjára pedig a keresést írjuk át úgy, hogy a beírás pillanatában már frissítse a találatok listáját. Vágjunk is bele!

Lehulló lista használata

Nagyon könnyű dolgunk van a lehulló lista megvalósítására a Delete és az Edit űrlapokban, hiszen a $data változó tartalmazza már az adatbázisunk adatait (az index.php betöltésekor kérdezzük le ezeket az adatokat), és így csak ebből kell egy ciklussal kiírni a megfelelő HTML tag-eket. A későbbiekben látni fogjuk, hogy most nem itt fogjuk feldolgozni az Edit és a Delete űrlapot, így az ezekhez tartozó kódokat is töröljük. Végeredményben ilyen egyszerűen néz majd ki az index.php elején a php szakasz:

<?php
    require_once("db.php");
    $db = new DB();
    $data = $db->getData();
?>

Az új Delete és Edit űrlapunk ennek megfelelően így fog kinézni:

  <h3>Delete</h3>
  <form method="POST">
    <select name="id" id="deleteList">
       <?php foreach($data as $item) { ?>
         <option value="<?php echo $item['id'] ?>"><?php echo $item['id'] . ' - ' . $item['name'] ?></option>
       <?php } ?>
     </select>
    <input type="submit" value="Delete" name="deleteData">
  </form>
  <h3>Edit</h3>
  <form action="editdata.php" method="POST">
    <select name="id" id="deleteList">
       <?php foreach($data as $item) { ?>
         <option value="<?php echo $item['id'] ?>"><?php echo $item['id'] . ' - ' . $item['name'] ?></option>
       <?php } ?>
     </select>
    <input type="text" placeholder="Name" name="name">
    <input type="submit" value="Edit" name="editData">
  </form>

A törlés PHP állománya

A törlést megvalósító metódust már megírtuk a DB osztály definíciójában deleteData() néven, csak eddig ezt az index.php-ból hívtuk meg. Ezt a kódrészt is töröljük innen, és a törlés űrlapját kiegészítjük, hogy a deletedata.php állományt hívja meg.

<h3>Delete</h3>
  <form action="deletedata.php" method="POST">
    <select name="id" id="deleteList">

A deletedata.php állományunk kódja teljesen egyértelmű: Amennyiben a deleteData gombra kattintottak, kiemeljük a $_POST tömbből a törlendő rekord azonosítóját, létrehozzuk a DB objektumot, és meghívjuk a deleteData() metódusát. Ezek után visszatérünk az index.php állományra.

<?php
  require_once "db.php";

  if(isset($_POST['deleteData'])){
    $id = $_POST['id'];
    $db = new DB();
    $db->deleteData($id);
    header('Location: index.php');
  }
?>

Valós idejű keresés

A legnagyobb változtatást az adatok keresésében hajtjuk végre. Megvalósítjuk azt, hogy a karakterek beírása közben azonnal lekérdezzük a beírt karaktersorozatnak megfelelő adatokat az adatbázisból, vagyis nincsen szükségünk a beírt név manuális elküldésére. Először is amellett, hogy töröljük a Submit gombot a keresés űrlapjából, kiegészítjük a beviteli mezőt az onkeyup() eseménykezelővel, amelyben meghívjuk a searchNames() javascript függvényt, átadva neki a mező tartalmát. (A FORM method paraméterét is átírjuk POST-ra, de ennek itt nem lesz jelentősége.)

  <h3>Search</h3>
  <form method="POST">
    <input type="text" placeholder="Name" name="name" onkeyup="searchNames(this.value)">
  </form>

A searchNames() javascript függvényt a main.js fájlban definiáljuk. A main.js állományt a záró </body> tag előtt töltjük be az index.php állományban:

<script src="main.js"></scrip>

Definiáljuk a main.js állományban a searchNames() függvényt, és tesztelési célból annyi kódot írjunk be, hogy az átvett paramétert (amit beírtunk. beviteli mezőbe) írja ki a konzolra. Próbáljuk ki! (A beírt karakterek sorban megjelennek a konzolon.)

function searchNames(name){
  console.log(name);
}

Ha minden működik, menjünk tovább. A terv az, hogy ez a searchNames() függvény fogja meghívni a searchdata.php állományunkat, melynek feladata a bevitt adatoknak megfelelő rekordok lekérdezése. A programnak csupán az utolsó sora igényel magyarázatot. Mivel a Javascript program JSON formátumban várja a php kimenetét, ezért azt a json_encode() függvénnyel erre formátumra hozzuk.

<?php
    require_once("db.php");

    $name = $_POST["name"];
    $db = new DB();
    $data = $db->searchData($name);
    echo json_encode($data);
?>

Nézzük tovább a searchNames() függényünket. Találunk benne pár újszerű megoldást. Mivel nem tudjuk, hogy az adatbázis lekérdezése mennyi ideig tart, ezért aszinkron feldolgozást valósítunk meg. Az első lépésben a fetch() függvénnyel átadjuk a vezérlést a searchdata.php állománynak. A POST metódust használjuk, és egy URLSearchParams objektummal átadjuk a keresendő nevet. A fetch() egy promise (ígéret) objektumot ad vissza, mely a lekérdezést eredményét tartalmazza majd. Ez nem a serchdata.php kimenete JSON formátumban, hanem egy HTTP response objektum. Ezt adjuk tovább a then() metódusnak, és a kimenetet, vagyis a lekérdezett adatokat JSON formátumban a json() metódussal nyerjük ki a response objektumból. Ezt tovább adjuk a következő then() metódusnak, amely már meghívja a populateTable() függvényt, mely a HTML oldalon megjeleníti a lekérdezett adatokat egy táblázat törzsében. (Felépíti a táblázat törzsét a DOM-ban.) Amennyiben hiba történt a fetch() során, a catch() metódus hajtódik végre.

function searchNames(name) {
  fetch('searchData.php', {
    method: 'POST',
    body: new URLSearchParams('name=' + name)
  }).then(function (res) {
    return res.json();
  }).then(function (data) {
    populateTable(data);
  }).catch(function (e) {
  })
}

Érdemes megnézni a populateTable() függvény számára átadott argumentumot, így jobban fogjuk érteni a függvény működését. (A kimenetet a böngésző konzolára írtuk ki a console.log(data) függvényhívással.)

0: {id: "5", name: "Bill", email: "bill@gmail.com"}
1: {id: "9", name: "Bob", email: "bob@gmail.com"}
2: {id: "11", name: "Rob", email: "rob@gmail.com"}
3: {id: "12", name: "Bill2", email: "bill2@gmail.com"}

Ezen a tömbön lépkedünk végig, és létrehozva a HTML tábla egyes elemeit, beépítjük a DOM-ba az adatokat:

function populateTable(data) {
  table = document.querySelector(".data-table");

  table.innerHTML = "";

  for (let i = 0; i < data.length; i++) {
    const trDataContainer = document.createElement("tr");
    table.appendChild(trDataContainer);

    let newId = document.createElement("td");
    newId.innerHTML = data[i]["id"];
    trDataContainer.appendChild(newId);

    let newName = document.createElement("td");
    newName.innerHTML = data[i]["name"];
    trDataContainer.appendChild(newName);
  }
}

Már csak egyetlen dolgot kell megoldanunk: Az oldal betöltődésekor meg kellene jeleníteni az adatbázis adatait az oldalon. Ehhez a <body> tag-hez rendeljük az onload eseménykezelőt, amely meghívja egy üres karakterrel a searchNames() függvényt:

<body onload="searchNames('')">

Ennyi volt. Persze tovább okosíthatnánk a programot (például további hibakezelésekkel, stb.), de legyen ennyi elég. A következő részben próbáljuk egy kicsit kicsinosítani az oldalt. Ehhez egy kis CSS ismeretre lesz szükség.

Ha érdekelt a bejegyzés, olvasd el ezt is: CRUD – PDO – 3. rész

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük