CodeIgniter modell réteg az adatbázissal és a Hello, World!

Programozóknak ugyan nem kell bemutatni Hello, World! fogalmát, de most kell hogy beszéljünk róla. A mai fejezetben szeretnénk létrehozni az adatbázist MySQL-ben, legyártani a modell réteget, majd adattal feltölteni, és a weben megjelentíteni. Mindezt mind saját kézzel írt kóddal, lehetőleg kevés kódsorban megvalósítva! Ez a Hello, World! – Helló, Világ! példánkban.

https://en.wikipedia.org/wiki/%22Hello,_World!%22_program

Hozzunk létre egy adatbázist a MySQL szerverünkön a https://wlammpp.wordpress.com/2019/10/04/i-resz-wordpress-webfejlesztes-a-wordpress-telepitese korábbi fejezetben ismertetett módon. Van egy adatbázis dump-om, ezt kell “bejátszani”.

-- MySQL dump 10.13 Distrib 5.7.29, for Linux (x86_64)
-- Host: localhost Database: evaap_devel

-- Server version 5.7.29
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table apartments
DROP TABLE IF EXISTS apartments;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE apartments (
id bigint(20) NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
address varchar(255) DEFAULT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table apartments
LOCK TABLES apartments WRITE;
/*!40000 ALTER TABLE apartments DISABLE KEYS */;
INSERT INTO apartments VALUES (1,'Budapest I','VII. kerulet','2020-03-20 00:26:35','2020-03-20 00:26:35');
/*!40000 ALTER TABLE apartments ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table reservations
DROP TABLE IF EXISTS reservations;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE reservations (
id bigint(20) NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
email varchar(255) DEFAULT NULL,
phone varchar(255) DEFAULT NULL,
checkin date DEFAULT NULL,
checkout date DEFAULT NULL,
message text,
approved tinyint(1) DEFAULT NULL,
apartment_id int(11) DEFAULT NULL,
locale varchar(255) DEFAULT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table users
DROP TABLE IF EXISTS users;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE users (
id bigint(20) NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
email varchar(255) DEFAULT NULL,
password varchar(255) DEFAULT NULL,
is_admin tinyint(1) DEFAULT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table users
LOCK TABLES users WRITE;
/*!40000 ALTER TABLE users DISABLE KEYS */;
INSERT INTO users VALUES (1,'admin','gvamosi@linux.hu','manager',1,'2020-03-19 00:00:00','2020-03-19 00:00:00');
/*!40000 ALTER TABLE users ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-04-07 14:05:14

Az alábbi módon:

gvamosi@gergo1:/var/www/html/apartman$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 50
Server version: 5.7.29 MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATE DATABASE apartman_devel CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.01 sec)
mysql> CREATE USER 'apartman'@'localhost' IDENTIFIED BY 'apartman1';
Query OK, 0 rows affected (0.02 sec)
mysql> GRANT ALL PRIVILEGES ON apartman_devel.* TO 'apartman'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
mysql> \q
Bye
gvamosi@gergo1:/var/www/html/apartman$ mysql -u apartman -p apartman_devel < db/create_and_insert_tables.sql
Enter password:
gvamosi@gergo1:/var/www/html/apartman$

Hozzuk létre az alkalmazás modell rétegét! Ehhez először be kell konfigurálnunk az adatbázist.

gvamosi@gergo1:/var/www/html/apartman/application$ vi config/database.php

$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost',
'username' => 'apartman',
'password' => 'apartman1',
'database' => 'apartman_devel',
'dbdriver' => 'mysqli',
'dbprefix' => '',
'pconnect' => FALSE,
'db_debug' => (ENVIRONMENT !== 'production'),
'cache_on' => FALSE,
'cachedir' => '',
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
'failover' => array(),
'save_queries' => TRUE
);

Ez eddig 3 string (karakterlánc)! 🙂 Aztán meg kell írnunk az Apartments_model.php file-t!

gvamosi@gergo1:/var/www/html/apartman/application$ vi models/Apartments_model.php

<?php
class Apartments_model extends CI_Model {
public function get_last_ten_entries()
{
$query = $this->db->get('apartments', 10);
return $query->result();
}
}

Ez 8 sor. 🙂 Most írjuk meg a controller-t!

gvamosi@gergo1:/var/www/html/apartman/application$ vi controllers/Apartments_controller.php
<?php
class Apartments_controller extends CI_Controller {
public function index() {
echo 'Helló, Világ!!';
$this->load->model('apartments_model');
$data['query'] = $this->apartments_model->get_last_ten_entries();
$this->load->view('apartments', $data);
}
}

Ez újabb 9 sor! Nem sok ez egy listáért? És akkor írjuk meg a view-t is!

gvamosi@gergo1:/var/www/html/apartman/application/views$ vi apartments.php

<ul>
<?php foreach ($query as $item):?>
<li><?php echo $item->address;?></li>
<?php endforeach;?>
</ul>

Ez húzós 5 sor! 🙂 Állítsuk be az útvonalakat, az autoload-ot (még két sor :)), majd hívjuk meg a következő módon a böngészőnkből az “oldalunkat”!

gvamosi@gergo1:/var/www/html/apartman/application$ vi config/routes.php
$route['apartmanok'] = 'apartments_controller/index';

gvamosi@gergo1:/var/www/html/apartman/application$ vi config/autoload.php
$autoload['libraries'] = array('database','session');

http://localhost/apartman/index.php/apartmanok

Listázza az egy darab apartmanunk címét, Budapesten. Siker! 🙂

A WordPress – és ami mögötte van: adatbázis és DbVisualizer

Tehát már van egy honlap-vázunk WordPress-ben. De mi köze ennek az adatbázishoz? Ennek járunk ma utána. 🙂 A DbVisualizer egy JAVA-ban írt adatbázis-feltérképező szoftver. Van Debian “.deb” csomagban is, az alábbi linkről telepíthetjük.

https://www.dbvis.com/download

Installálni igen egyszerű.

root@gergo1:~# dpkg -i dbvis_linux_10_0_22.deb

Ezután jöhet a konfiguráció – új kapcsolat varázsló – pár lépésben. A DbVisualizer ún. JDBC-n (Java Database Connectivity) keresztül kapcsolódik a MySQL adatbázisunkhoz. Esetünkben reverse engineering-re fogjuk használni a szoftvert, azaz a kész adatbázisból nyerjük ki a “tervet”. 🙂

Megfelelő konfiguráció után a DbVisualizer gombnyomásra felrajzolja nekünk mind a 12 adatbázistáblát a “wordpress2019” sémában. Az alábbi ábra egy ún. ER-diagram (Entity-Relationship), magyarul EK-diagram (egyed-kapcsolat). A táblák közti kapcsolatok ugyan nincsenek jelölve, azonban indirekten léteznek. Ennyi az egész WordPress! 🙂

Egy adatbázison (sémán) belül az adatok táblákba vannak rendezve, azon belül mezők vannak, és sorokban adatok, hasonlóan egy fejléccel ellátott Excel-táblázathoz. Az adatbázisunk táblái (entitásai, egyedei) rendre:

  • wp_commentmeta
  • wp_comments
  • wp_links
  • wp_options
  • wp_postmeta
  • wp_posts
  • wp_term_relationships
  • wp_term_taxonomy
  • wp_termmeta
  • wp_terms
  • wp_usermeta
  • wp_users

Talán hihetetlenül hangzik, de a fenti 12 táblában minden WordPress oldal, blog bejegyzés (post), felhasználó (user), beállítás, megjegyzés és metaadatok – tehát minden elfér. Ha ügyesek vagyunk, megnézhetjük az egyes táblák mezőit is. Látható, hogy minden táblában van ID, azaz egyedi azonosító vagy elsődleges kulcs – lásd pl. wp_users tábla, bizonyos táblákban pedig hivatkozásként szerepelnek az egyedi azonosítók, ún. idegen kulcsként – lásd wp_usermeta. (Ezek volnának az indirekt kapcsolatok.) Nézzük meg e két tábla mezőit.

Ez az adatszerkezet egy gyakori “trükk” SQL alapú adatbázisoknál. Tetszőleges kulcsokkal (meta_key) tetszőleges értékeket, azaz meta adatokat (meta_value) tárolhatunk el egy felhasználóhoz. A “wp_usermeta” tábla értékeit a “user_id” mezőben lévő kulcsérték köti a “wp_users” táblához, miközben “umeta_id” néven egyedi azonosítója is van minden táblabejegyzésnek, azaz “sornak”. Később látni fogjuk, hogy miért jó dolog egyedi azonosítót adni minden adatbázis táblának. 🙂

Hogy mi az az SQL (Structured Query Language)? Egész röviden: önálló programnyelv; a séma és az adatbázis objektumok (pl. táblák) definiálása – DDL (Data Definition Language), az adatok lekérdezése (SELECT) – DQL (Data Query Language), az adatok változtatása (INSERT, UPDATE, DELETE) – DML (Data Manipulation Language), továbbá a DCL(Data Control Language) illetve a TCL (Transaction Control Language). Ennyi nagyjából. Bővebben az alábbi linken olvashatunk róla, magyarul.

https://hu.wikipedia.org/wiki/SQL

A legtöbb webes alkalmazásnak az ún. CRUD felépítésnek kell megfelelnie. Ez pedig a Create (létrehoz), Read (olvas), Update (módosít) és Delete (töröl). A terminológia a perzisztens adattárolás alapja. Így tárolhatunk adatokat akár webes környezetben, ún. webes form-ok, azaz űrlapok segítségével. A CRUD-ot könnyen párosíthatjuk az SQL INSERT, SELECT, UPDATE és DELETE parancsokkal vagy akár a HTTP protokollal (bemutatása később). Részletek alább – sajna csak angolul.

https://en.wikipedia.org/wiki/Create,_read,_update_and_delete

És egy jó tanács a végére. Ne próbáljunk meg kézzel belejavítani a tábla-adatokba! Dobhat tőle egy hátast az egész WordPress rendszerünk. Elégedjünk meg az architekturális betekintéssel és mérnöki feltárással! 😀

I. rész – WordPress webfejlesztés – A WordPress telepítése

Hogy miért választottam a WordPress-t? Mivel itt gyakorlatilag nem is kell programozni; ezt a rendszert elég testreszabni és feltölteni tartalommal. A beállítások nagy része programozási ismeretek nélkül is elvégezhető. 🙂

A telepítés előtt győződjünk meg róla, hogy a szerveren rendelkezésre áll-e adatbázis szerver (MySQL vagy MariaDB), Apache vagy nginx webszerver és telepítve van-e a PHP aktuális verziója. Ezekre ugyanis mind szükségünk lesz a saját és ingyenes WordPress oldalunk elindításához. Hogy hogyan győződhetünk meg arról, hogy minden szükséges rendszer telepítve van, és készen áll? Jó megoldás a phpinfo() parancs meghívása a következő módon.

gvamosi@gergo1:/var/www/html$ cat info.php
<?php
phpinfo();
?>

Ezt a file-t ne hagyjuk később “kint’ a szerveren, mert ha valaki véletlenül megtalálja, akkor mindent kideríthet a szerverünk beállításairól! (A webszerver általában a “.php” kiterjesztésű file-okat értelmezi kódként, ezért pl. átnevezhetjük “.akarmi” kiterjesztésűre vagy törölhetjük is.) Nézzünk pár részletet a kimenetéből, ha megnyitjuk böngészőben a http://localhost/info.php cím alatt.

PHP Version 7.0.33-0+deb9u3
Apache Version Apache/2.4.38 (Debian)
MysqlI Support enabled
mysqli.default_port 3306 3306
Client API version mysqlnd 5.0.12-dev - 20150407 - $Id: b5c5906d452ec590732a93b051f3827e02749b83 $

Ezek az adatok úgy vélem magukról beszélnek. 🙂

A MySQL szerverhez unix domain socket-en keresztül és port alapon (3306) tudunk csatlakozni. A portot jól tesszük, ha kizárólag localhost-on engedélyezzük a tűzfalunkban – ez egyébként alapbeállítás -, a socket (mysqld.sock) pedig úgyis csak filerendszerben van – így kizárjuk az adatbázis közvetlen külső elérhetőségét, ezzel is növelve szerverünk biztonságát. 🙂

gvamosi@gergo1:~$ l /var/run/mysqld/
total 8
-rw-r----- 1 mysql mysql 6 Oct 5 01:11 mysqld.pid
srwxrwxrwx 1 mysql mysql 0 Oct 5 01:11 mysqld.sock
-rw------- 1 mysql mysql 6 Oct 5 01:11 mysqld.sock.lock

Ha tárhelyet bérlünk valahol, akkor általában gombnyomásra működik a WordPress telepítése. Én most a hagyományos megoldást mutatnám be röviden terminál használatával. A letöltéshez információkat az alábbi honlapon találunk.

https://hu.wordpress.org/download/

A WordPress telepítése tényleg egyszerű. Legelőször is szükségünk lesz egy új MySQL adatbázisra, felhasználóval és jelszóval – ez tárhelybérlésnél gombnyomásra történik. Egy (MySQL) adatbázis kapcsolathoz négy fontos adatra lesz szükségünk: adatbázis neve, felhasználó neve és jelszava, illetve a hoszt neve. Konzolból az alábbi módon – SQL parancsok használatával – tudunk MySQL adatbázist létrehozni.

gvamosi@gergo1:~$ mysql -u root -p
mysql> CREATE DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
-- minden jog hozzárendelése az adatbázishoz a felhasználónknak
mysql> GRANT ALL PRIVILEGES ON dbname.* TO 'user'@'localhost';
mysql> FLUSH PRIVILEGES;

Ezután csupán ki kell bontanunk a letöltött állományt a megfelelő helyre, mint “gyökérbe”.

gvamosi@gergo1:/var/www/html/hegypasztor$ wget https://hu.wordpress.org/latest-hu_HU.tar.gz
..
gvamosi@gergo1:/var/www/html/hegypasztor$ tar xzvf latest-hu_HU.tar.gz
..
gvamosi@gergo1:/var/www/html/hegypasztor$ mv wordpress/* .

Eközben a következő – WordPress webes telepítés előtti – képernyő fogad bennünket a http://localhost/hegypasztor/ webcím alatt.

Ezután a wp-config-sample.php állományt át kell másolnunk a wp-config.php állományba, majd kitöltenünk az adatbázis-hozzáférést és a titkos kulcsokat – ahogy a magyar nyelvű dokumentáció írja – pl. egy vi editorral.

gvamosi@gergo1:/var/www/html/hegypasztor$ cp wp-config-sample.php wp-config.php
gvamosi@gergo1:/var/www/html/hegypasztor$ vi wp-config.php

Mihelyst elkészülünk a wp-config.php file kitöltésével, és megnyomtuk a “Rajta!” gombot, az alábbi képernyőt láthatjuk.

Ezután a webes felületen pár mező (honlapnév, webes adminisztrátor felhasználó neve és jelszava) kitöltésével gombnyomásra települ a WordPress honlapunk.

És máris az első bejelentkezésünknél tartunk.

Ezután vethetünk egy pillantást az alap honlapunkra. Ez a kiindulási pontunk a fejlesztéshez! Mivel be vagyunk jelentkezve adminisztrátorként, ezért a képernyő tetején egy menüsort találunk.

Illetve megnézhetjük az adminisztrátori képernyőt, a vezérlőpulttal. 🙂

Mit értünk webprogramozás, webfejlesztés alatt

A 21. századra rárobbant az információs kor. A World Wide Web, azaz a WWW kora, az Internet multimédia-tartalommal bíró kommunikációs csatornája, a kiszolgáló oldali (web)szerverek – ez volna az Apache vagy az nginx -, és a kliens oldali böngészők – Chrome, Firefox, Edge – kommunikációjaként előálló interakció. Az egész Internet lényegében tekinthető egy online adatfeldolgozó, -tároló és -továbbító rendszernek. Ezért fontos beszélni az adatok tárolására és feldolgozására szolgáló többnyire SQL alapú adatbázis szerverekről is – ezek a MySQL vagy a MariaDB -, illetve a szerver oldali adatfeldolgozó script-ekről, azaz webszerverbe ágyazott szoftverrendszerekről is, melyek sok esetben Perl és PHP nyelveken íródnak. Fontos még említeni a kliens oldal legütősebb script-nyelvét, a JavaScript-et. Legismertebb képviselője a széles körben elterjedt JavaScript könyvtár, a jQuery (https://jquery.com). Az adatok továbbítása valójában a hálózaton keresztül valósul meg, mindig kliens-szerver kommunikációban – lévén ugyanis a szerver egyszerre több klienst is kiszolgál, továbbá a szerverek egymással is tudnak beszélgetni, de adott esetben egy kliens is egyszerre több szerverhez kapcsolódhat. 🙂 Jelen írás a fentiekben leírtak bemutatásával szeretne foglalkozni.

A webfejlesztés tehát minden esetben egy szoftver-rendszerben történik. Egy jó kiindulási szoftver környezet található az alábbi linken.

https://www.apachefriends.org/hu/index.html

Ebben az írásomban szeretném az operációs rendszer, az adatbázis szerver, a webszerver és a kliens oldal összhangját három esettanulmányon keresztül bemutatni. Egyébként a fenti link alatt található XAMPP-ot hívják még LAMP-nak is. Szinte mindegy, hogy melyik variánst vesszük, ugyanaz az eredmény. 🙂 Ez az architektúra (szoftverépítészeti megoldás) igen elterjedt és nagy népszerűségnek örvend, többek között a nem enterprise (nem nagyvállalati vagy nagy volumenű üzleti) felhasználási területen.

https://hu.wikipedia.org/wiki/LAMP_(szoftvercsomag)

Megjegyezném, hogy ezen technológiák ismerete enterprise megoldások kiindulási pontja lehet, illetve hogy nagy dolgokat is meg lehet a segítségükkel valósítani. 🙂

A három esettanulmány – három rész – rendre a következők lesznek:

  1. A nyílt forráskódú, PHP-ban írt WordPress (https://hu.wordpress.org/), weboldalak, blogok és egyéb webes alkalmazások motorjának bemutatása egy webalkalmazáson keresztül.
  2. A nyílt forráskódú CodeIgniter (http://codeigniter.hu/) PHP keretrendszer megismertetése egy webalkalmazáson keresztül. Ez a keretrendszer a letisztult MVC (Model – View – Controller) programtervezési mintát (Design Patterns) követi.
  3. Harmadikként pedig a 30 éve folyamatosan fejlesztett Perl nyelven fogunk webalkalmazást, azon belül is klasszikus CGI-t (Common Gateway Interface https://hu.wikipedia.org/wiki/Common_Gateway_Interface) illetve FastCGI-t írni. 🙂

Végül lássuk egy szemléltető diagramon az MVC pattern-t. A lényege, hogy mindent a Controller (vezérlő) végez, a modellváltoztatást is, és a felhasználó nézetének változtatását is. 🙂