Přístup k databázi z webové aplikace v PHP. Martin Klíma



Podobné dokumenty
Tvorba webu 1. Přístup k databázi Martin Klíma. Tvorba Webu 1 1

X36WWW. Přístup k databázi Martin Klíma. Tvorba Webu 2 1

Návrh a tvorba WWW stránek 1/14. PHP a databáze

Západočeská univerzita v Plzni Katedra informatiky a výpočetní techniky. 9. června krovacek@students.zcu.cz

Informační systémy 2008/2009. Radim Farana. Obsah. Jazyk SQL

2. blok část B Základní syntaxe příkazů SELECT, INSERT, UPDATE, DELETE

George J. Klir. State University of New York (SUNY) Binghamton, New York 13902, USA

Databázové systémy II. KIV/DB2 LS 2007/2008. Zadání semestrální práce

Obchodní akademie a Jazyková škola s právem státní jazykové zkoušky Jihlava

PL/SQL. Jazyk SQL je jazykem deklarativním, který neobsahuje procedurální příkazy jako jsou cykly, podmínky, procedury, funkce, atd.

Verzování a publikace dat na webu za pomoci PostgreSQL

InnoDB transakce, cizí klíče, neumí fulltext (a nebo už ano?) CSV v textovém souboru ve formátu hodnot oddělených čárkou

Databázové systémy trocha teorie

Použití databází na Webu

Úvod do databázových systémů

Jazyk SQL databáze SQLite. připravil ing. petr polách

Kurz Databáze. Obsah. Dotazy. Zpracování dat. Doc. Ing. Radim Farana, CSc.

Třídy a objekty. Třídy a objekty. Vytvoření instance třídy. Přístup k atributům a metodám objektu. $z = new Zlomek(3, 5);

Databázové systémy. - SQL * definice dat * aktualizace * pohledy. Tomáš Skopal

7. Integrita a bezpečnost dat v DBS

7. Integrita a bezpečnost dat v DBS

Příklady a návody. Databázová vrstva

Univerzita Pardubice. Centrální správa dokumentů

Semestrální práce z DAS2 a WWW

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Semináˇr Java X JDBC Semináˇr Java X p.1/25

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 10.4.

SQL. strukturovaný dotazovací jazyk. Structured Query Language (SQL)

Databáze II. 1. přednáška. Helena Palovská

4IT218 Databáze. 4IT218 Databáze

Databázové systémy a SQL

5. POČÍTAČOVÉ CVIČENÍ

Databázové systémy úvod

Sada 1 - PHP. 14. Úvod do jazyka SQL

Inovace a zkvalitnění výuky prostřednictvím ICT Databázové systémy MySQL základní pojmy, motivace Ing. Kotásek Jaroslav

J z a yk y PH P P P p o p k o r k.

8.2 Používání a tvorba databází

Databázové a informační systémy

MySQL sežere vaše data

MySQLi (objektově) Příklad vytvoření instance třídy včetně parametrů pro připojení: $mysqli = new mysqli('localhost', 'login', 'heslo', 'databaze');

Databázové systémy. Cvičení 6: SQL

Michal Krátký, Miroslav Beneš

2. přednáška. Databázový přístup k datům (SŘBD) Možnost počítání v dekadické aritmetice - potřeba přesných výpočtů, např.

SQL v14. 4D Developer konference. 4D Developer conference 2015 Prague, CZ Celebrating 30 years

Tabulka fotbalové ligy

Vzorové příklady SQL. Tabulka: Kniha CREATE TABLE kniha (id INTEGER, název VARCHAR(50), PRIMARY KEY (id))

B0M33BDT Technologie pro velká data. Supercvičení SQL, Python, Linux

4. lekce Přístup k databázi z vyššího programovacího jazyka

Optimalizace dotazů a databázové transakce v Oracle

Databázové systémy Cvičení 5.2

Databáze I. Přednáška 4

Nasazení Object Relation Mapping nástrojů nad legacy datovým modelem

OBJECT DEFINITION LANGUAGE. Jonáš Klimeš NDBI001 Dotazovací Jazyky I 2013

Marian Kamenický. Syntea software group a.s. marian.kamenicky. MFFUK Praha 2012/13


PG 9.5 novinky ve vývoji aplikací

KIV/ZIS cvičení 6. Tomáš Potužák

Databáze I. Přednáška 7

Databáze SQL SELECT. David Hoksza

Bezpečnost a bezpečné programování

Inovace a zkvalitnění výuky prostřednictvím ICT. Základní seznámení s MySQL Ing. Kotásek Jaroslav

Informační systémy 2008/2009. Radim Farana. Obsah. Dotazy přes více tabulek

Databázové systémy, MS Access. Autor: Ing. Jan Nožička SOŠ a SOU Česká Lípa VY_32_INOVACE_1130_Databázové systémy, MS Access_PWP

16. února 2015, Brno Připravil: David Procházka

Databáze 2011/2012 SQL DDL (CREATE/ALTER/DROP TABLE), DML (INSERT/UPDATE/DELETE) RNDr.David Hoksza, Ph.D.

SQL. relační databázový systém. v úvodní kurz jazyka SQL

Konceptuální modelování a SQL

6. SQL složitější dotazy, QBE

Úvod do databázových systémů

DJ2 rekurze v SQL. slajdy k přednášce NDBI001. Jaroslav Pokorný

RELAČNÍ DATABÁZOVÉ SYSTÉMY

Maturitní témata z předmětu PROGRAMOVÉ VYBAVENÍ pro šk. rok 2012/2013

Databázové systémy I

Object-relational mapping (JPA, Hibernate)

Plánování a vývoj základního frameworku

public static void main(string[] args) { System.out.println(new Main().getClass().getAnnotation(Greet.class).text());

KIV/ZIS cvičení 5. Tomáš Potužák

Databázové systémy I. 1. přednáška

Jazyk SQL 3 - DML, DDL, TCL, DCL

PostgreSQL. Podpora dědičnosti Rozšiřitelnost vlastní datové typy. Univerzální nasazení ve vědecké sféře

RMI Remote Method Invocation

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 26.3.

Platforma Java. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. Petr Krajča (UP) KMI/PJA: Seminář V. 27. říjen, / 15

Uložené procedury Úvod ulehčit správu zabezpečení rychleji

Úvod do databází. Modelování v řízení. Ing. Petr Kalčev

Administrace Oracle Práva a role, audit. Kukhar Maria

SQL injection princip a ochrana

Informační systémy 2008/2009. Radim Farana. Obsah. Skripty a dávky. Nastavení aktuální databáze. USE DatabaseName

DUM 12 téma: Příkazy pro tvorbu databáze

Čipové karty Lekařská informatika


Obsah přednášky. Představení webu ASP.NET frameworky Relační databáze Objektově-relační mapování Entity framework

Zápisování dat do databáze

Základy informatiky. 08 Databázové systémy. Daniela Szturcová

PHP a Large Objecty v PostgreSQL

Klíčová slova: dynamické internetové stránky, HTML, CSS, PHP, SQL, MySQL,

Úvod do databázových systémů

1. Relační databázový model

Typ 2 - připojení prostřednictvím kódu nativního klienta pro přístup k síti

Databáze 2011/2012 T-SQL - kurzory, funkce. RNDr.David Hoksza, Ph.D.

Transkript:

Přístup k databázi z webové aplikace v PHP Martin Klíma

DATABÁZE ÚVOD

Relační databáze - pojmy Databázový systém program pro práci a správu DB Databáze souhrn datových struktur obsahující data Tabulky databáze se skládá z tabulek, tabulka má sloupce a řádky Sloupec popis vlastnosti objektu Řádek, záznam konkrétní data uložená v tabulce Primární klíč množina sloupců, které jednoznačně identifikují záznam Relace vztah mezi objekty v databázi

Databáze - relace Relace 1:1 ID_Objednavky Mnozstvi Produkt 1 10 Okurky 2 15 Papriky ID_Transakce ID_Objednavky Datum 33 1 1.1.2005 34 2 5.1.2005 Relace 1:N ID_Objednavky Mnozstvi Produkt ID_Zakaz nika 1 10 Okurky 102 2 15 Papriky 102 ID_Zakaznika Jmeno 102 Novák 103 Omáčka

Databáze - relace Relace M:N ID_reky Jmeno 1 Labe 2 Vltava ID_Zeme Nazev 102 CR 103 Nemecko Převod na 1:N ID_reky Jmeno 1 Labe 2 Vltava ID_reky 1 102 1 103 2 102 ID_Zeme ID_Zeme Nazev 102 CR 103 Nemecko

Manipulace s databází Jazyk SQL (Structured Query Language) DDL = Data Definition Language DML = Data Manipulation Language DDL Create Alter Drop DML Select INSERT Update Delete

Příklad použití databáze Databáze zboží Kategorie zboží Kategorie může mít N podkategorií Kazdá podkategorie patří do jedné kategorie (strom) Každé zboží může patřit do více kategorií

DB - příklad zbozi ID Jmeno Cena 1 Jablka č. 35 2 Jablka z. 38 kategorie ID Nazev Nadkategorie 1 Ovoce null 2 Zelenina null 3 Okurky 103 zbozi_kategorie 4 Potraviny null ID IDZbozi IDKategorie 1 1 1 2 2 1 3 1 4 4 2 4

MYSQL

MySQL Velice úspěšný RDBMS systém Open source Poskytovaný skoro všude Vlastnosti několik různých engine rychlé i pomalé transakční i netransakční podpora různých kódování uložené procedury kninovny, PHP podpora od vzniku PHP

Databázové enginy MyISAM InnoDB MERGE MEMORY EXAMPLE FEDERATED ARCHIVE NDB Zjistit aktuálně instalované enginy můžeme takto: SHOW ENGINES\G

MyISAM Engine Velmi rychlý Není transakční (proto je také rychlý) Nepodporuje ref. integritu Syntakticky ano, fakticky ne Každá tabulka je v samostatném souboru soubor se jmenuje podle jména tabulky

Innodb engine - přehled vlastností Plně transakční zpracování ACID kompatibilní = commit, rollback, zotavení Zamykání záznamů (po řádcích) Podporuje cizí klíče (FOREIGN KEY) Je součástí základní distribuce Rychlý engine, ale ne tak rychlý jako MyISAM GNU GPL License Version 2

Innodb vlastnosti Tabulky jsou uloženy ve společném souboru (souborech) a to včetně indexů Tabulky mohou být uloženy ve více souborech i na více různých discích Tabulky mohou být uloženy i separátně, každá v jednom souboru pozor, chová se to jinak než MyISAM nelze jen tak kopírovat

Připojení k MySQL Pomocí klienta PHP Pomocí řádkového klienta v adresáři bin/mysql Pomocí klienta třetí strany mysql h localhost u xklima p xklima Host, default je localhost jméno uživatele budu zadávat heslo interaktivně jméno databáze, kterou otevírám

PHP A DATABÁZE

PHP a DB PHP má nativní podporu pro většinu existujících DB MySQL v první řadě Čtyři způsoby, jak může DB podporovat 1. Nativní podpora pomocí dynamické knihovny např. mysql.dll, mysqli.dll 2. Nativní podpora v jádře PHP je nutné zkompilovat 3. Pomocí ODBC je nutné mít podporu ODBC 4. Pomocí abstraktní vrstvy, např. PDO

Naše DB CREATE TABLE `zbozi` ( `ID` int(11) NOT NULL auto_increment, `Nazev` varchar(100) NOT NULL, `Popis` text, `ObrazekURL` varchar(50) default NULL, `Cena` double NOT NULL default '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci; GRANT ALL PRIVILEGES ON x36www.* TO x36www_user@localhost IDENTIFIED BY "x36heslo"; FLUSH PRIVILEGES; set names utf8; insert into `zbozi` (`ID`,`Nazev`,`Popis`,`ObrazekURL`,`Cena`) values (1,'Myš','Počítačová myš','mys.jpg',100), (2,'HDD 500','Harddisk s kapacitou 500GB','hdd1.jpg',1200), (3,'HDD 750','Harddisk s kapacitou 750 GB','hdd2.jpg',1400), (4,'Monitor 1','Monitor s rozlišením 1024x768','monitor1.jpg',1000);

Nutné kroky při práci s DB 1. Připojení k databázovému stroji URL databáze ověření uživatele 2. Výběr databáze body 1 a 2 lze sloučit 3. Sestavení a poslání dotazu 4. Čtení resultsetu (pokud ho daný dotaz vrací) 5. Uvolnění resultsetu 6. Uzavření spojení Pozor!!! Každá operace může skončit chybou, musím na to správně reagovat

Implementace define ("DB_HOST", "localhost"); define ("DB_NAME", "x36www"); define ("DB_USER", "x36www_user"); define ("DB_PASSWD", "x36heslo"); // pokusim se pripojit k DB stroji $link = mysqli_connect(db_host, DB_USER, DB_PASSWD); if (!$link) { echo "Nepodařilo se spojit s DB.<br>"; echo mysqli_connect_error(); exit(); // pokusim se vybrat si spravnou databazi $success = mysqli_select_db($link, DB_NAME); if (!$success) { echo "Nepodařilo se přepnout na správnou databázi"; exit();

Implementace // sestavim si dotaz $sql = "SELECT * FROM zbozi WHERE zbozi.cena <=100 ORDER BY zbozi.cena, zbozi.nazev"; // provedu dotaz $result = mysqli_query($link, $sql); if ($result) { // iteruj vysledek a vypis ho na obrazovku while ($row = mysqli_fetch_assoc($result)) { echo "\n<div>"; echo htmlspecialchars($row['nazev']); echo ": "; echo $row['cena']; echo "</div>"; // uvoni resultset mysqli_free_result($result); // uzavri spojeni s db mysqli_close($link);

Co vrací mysqli_query Pro dotazy SELECT, SHOW, DESCRIBE a EXPLAIN vrací mysqli_query() výsledek (objekt s tabulkou dat), který musí být zpracován dalšími funkcemi. Pro UPDATE, INSERT, DELETE, DROP a další dotazy pro manipulaci s DB vrací mysqli_query() hodnotu typu boolean.

Zpracování výsledku z mysqli_query Mnoho funkcí na zpracování $result mysqli_fetch_array Fetch a result row as an associative, a numeric array, or both mysqli_fetch_assoc Fetch a result row as an associative array mysqli_fetch_field_direct Fetch meta-data for a single field mysqli_fetch_field Returns the next field in the result set mysqli_fetch_fields Returns an array of objects representing the fields in a result set mysqli_fetch_lengths Returns the lengths of the columns of the current row in the result set mysqli_fetch_object Returns the current row of a result set as an object mysqli_fetch_row Get a result row as an enumerated array

SQL injection Často sestavujeme dotaz z parametrů zadaných uživatelem. Musíme počítat s tím, že uživatel nemusí zadat "pěkná" data. Uživatel může zničit sql dotaz. Uživatel může pozměnit dotaz tak, že vrátí jiný výsledek.

SQL Injection zkuste url: sql_injection.php?max=aaa // sestavim sql dotaz z $_GET parametru // predpokladam, ze uzivatel ve formulari zadal max cenu zbozi // parametr max // spatne sestaveny sql dotaz $sql_spatne = "SELECT * FROM zbozi WHERE Cena <= ".$_GET['max']." ORDER BY Nazev"; $cena_max = intval($_get['max']); $sql_spravne = "SELECT * FROM zbozi WHERE Cena <= ".$cena_max." ORDER BY Nazev"; echo htmlspecialchars("spatne: ".$sql_spatne); echo "<br/>"; echo htmlspecialchars("spravne: ".$sql_spravne); echo "<br/>";

SQL Injection zkuste URL: sql_injection.php?search=dd'%20or%20true%20or%20nazev%20like% 20'% // predpokladam, ze uzivatel zadal vyhledavaci retezec nazvu // param search // rekneme, ze v systemu jsou dve role: 1: admin, 2: obyc uzivatel $sql_spatne2 = "SELECT * FROM zbozi WHERE Priv = 2 AND Nazev like '%".$_GET['search']."'"; $search = mysql_real_escape_string($_get['search']); $sql_spravne2 = "SELECT * FROM zbozi WHERE Priv = 2 AND Nazev like '%".$search."'"; echo htmlspecialchars("spatne 2: ".$sql_spatne2); echo "<br/>"; echo htmlspecialchars("spravne 2: ".$sql_spravne2);

Veškeré skripty musí být ošetřeny na SQL Injection..je to zápočtová podmínka

PDO

Co to jepdo PDO je rozšíření PHP modulu o databázovou vrstvu Abstraktní přístup k DB Implementace pro nejběžnější DB (mysql, oracle, pg, ) Podpora transakcí Objektový přístup

<?php $user = "x36www_user"; $pass = "x36heslo"; try { $dbh = new PDO('mysql:host=localhost;dbname=x36www', $user, $pass, array( PDO::ATTR_PERSISTENT => true )); $dbh->begintransaction(); $dbh->exec("insert into zbozi (Nazev, Popis, ObrazekURL, Cena) values ('Podložka', 'Podložka pod myš', 'podlozka.jpg', '46')"); $dbh->commit(); catch (Exception $e) { $dbh->rollback(); echo "Failed: ". $e->getmessage();?>

PREPARED STATEMENTS

Zpracování dotazu databází Typické fáze zpracování Cache lookup Parse Check access rights. Optimize Execute Query Cache Náročná fáze, znovupoužitelý výsledek PreparedStatement provádí optimalizaci jednou, dále posílá data do fáze execute

$dbh->begintransaction(); $stmt = $dbh->prepare("insert INTO zbozi (Nazev, Popis, ObrazekURL, Cena) VALUES (:nazev, :popis, :url, :cena)"); $stmt->bindparam(':nazev', $nazev); $stmt->bindparam(':popis', $popis); $stmt->bindparam(':url', $url); $stmt->bindparam(':cena', $cena); // vloz jeden zaznam $nazev = 'DVD mechanika'; $popis = 'DVD vypalovačka'; $url = 'dvdobrazek.jpg'; $cena = '350'; $stmt->execute(); // vloz dalsi zaznam $nazev = 'DVD mechanika 2'; $popis = 'DVD vypalovačka 2'; $url = 'dvdobrazek2.jpg'; $cena = 190; $stmt->execute(); $dbh->commit();

$dbh->begintransaction(); $stmt = $dbh->prepare("insert INTO zbozi (Nazev, Popis, ObrazekURL, Cena) VALUES (?,?,?,?)"); $stmt->bindparam(1, $nazev); $stmt->bindparam(2, $popis); $stmt->bindparam(3, $url); $stmt->bindparam(4, $cena); // vloz jeden zaznam $nazev = 'DVD mechanika'; $popis = 'DVD vypalovačka'; $url = 'dvdobrazek.jpg'; $cena = '350'; $stmt->execute(); $dbh->commit();

Doctrine ORM

www.doctrine-project.org

Cíl mapování objektového modelu a ER Objekový model Relační model

Ukázka navázání spojení bootstrap require_once('../doctrine/branches/1.2/lib/doctrine.php'); spl_autoload_register(array('doctrine', 'autoload')); $dsn = 'mysql:dbname=testdb;host=127.0.0.1'; $user = 'dbuser'; $password = 'dbpass'; $dbh = new PDO($dsn, $user, $password); $conn = Doctrine_Manager::connection($dbh); Lazy verze // At this point no actual connection to the database is created $conn = Doctrine_Manager::connection('mysql://username:password@localhost/test'); // The first time the connection is needed, it is instantiated // This query triggers the connection to be created $conn->execute('show TABLES');

Ukázka použití $conn->export->createtable('test', array('name' => array('type' => 'string'))); $conn->execute('insert INTO test (name) VALUES (?)', array('martin')); $stmt = $conn->prepare('select * FROM test'); $stmt->execute(); $results = $stmt->fetchall(); print_r($results); Výsledek Array ( [0] => Array ( [name] => Martin [0] => Martin ) )

Definice dat Model // models/book.php class Book extends Doctrine_Record { public function settabledefinition() { $this->hascolumn('booktitle as title', 'string'); Použití // test.php //... $book = new Book(); $book->title = 'Some book'; $book->save();

Relační závislosti Forum_Board 1 N Forum_Thread Model Forum_Board // models/forum_boadr.php class Forum_Board extends Doctrine_Record { public function settabledefinition() { $this->hascolumn('name', 'string', 100); $this->hascolumn('description', 'string', 5000); public function setup() { $this->hasmany('forum_thread as Threads', array( 'local' => 'id', 'foreign' => 'board_id' ) ); Model Forum_Thread // models/forum_thread.php class Forum_Thread extends Doctrine_Record { public function settabledefinition() { $this->hascolumn('user_id', 'integer'); $this->hascolumn('board_id', 'integer'); $this->hascolumn('title', 'string', 200); $this->hascolumn('updated', 'integer', 10); $this->hascolumn('closed', 'integer', 1); public function setup() { $this->hasone('forum_board as Board', array( 'local' => 'board_id', 'foreign' => 'id' ) ); $this->hasone('user', array( 'local' => 'user_id', 'foreign' => 'id' ) ); User definován jinde

Ukázka použítí $board = new Forum_Board(); $board->name = 'Some board'; $board->threads[0]->title = 'new thread 1'; $board->threads[1]->title = 'new thread 2'; $user = new User(); $user->username = 'jwage'; $board->threads[0]->user = $user; $board->threads[1]->user = $user; $board->save();

Práce s modelem // test.php $user = new User(); $user['username'] = 'jwage'; $user['password'] = 'changeme'; $email = $user->email; $email = $user->get('email'); $email = $user['email']; Ekvivalentní Ekvivalentní $user->save();

Dotazování a další operace // select pres primarni klic $user = Doctrine_Core::getTable('User')->find(1); echo $user->email['address']; echo $user->phonenumbers[0]->phonenumber; // query $q = Doctrine_Query::create() ->from('user u') ->leftjoin('u.email e') ->leftjoin('u.phonenumbers p') ->where('u.id =?', 1); $user = $q->fetchone(); echo $user->email['address']; echo $user->phonenumbers[0]['phonenumber']; // test.php // update $user->email['address'] = 'koskenkorva@drinkmore.info'; $user->phonenumbers[0]['phonenumber'] = '123123'; $user->save(); // smazani $user->email->delete();

DB A OBJEKTOVÉ PROG. VZORY

Abstrakce Aplikační logika DB abstraktní vrstva MySQL PosgreSQL Oracle Sybase...

Vzor Factory Abstraktní vrstva DBLayer connect($param) query($sql) Implementace X Implements Implementace Y PGDBLayer connect($param) query($sql) MYSQLDBLayer connect($param) query($sql) kuk kosik_objektovy1.5.php

Vzor Factory Používá se tehdy, když chceme získat instanci nějakého objektu, ale nechceme se starat o to, jak tento objekt vytvořit Příklad: chceme přistupovat k databázi databází je ale mnoho různých druhů (mysql, oracle, ) všechny db implementují stejné rozhraní

Vzor Factory Impl 1/2 interface DBLayer { public function connect($param); public function query($sql); class MySQLDBLayer implements DBLayer { public function connect($params) { // mysql_connect(...) public function query($sql) { // mysql_query(...) class PGDBLayer implements DBLayer { public function connect($params) { //pg_connect(...) public function query($sql) { // pg_query(...)

Vzor Factory Impl 2/2 // vzor factory = tovarna na objekty class DBFactory { // zde to prijde! // vim, ze vratim rozhrani typu DBLayer public static function getdblayer($type){ switch ($type) { case "MySQL": return new MySQLDBLayer(); break; case "PG": return new PGDBLayer(); break; default: return new MySQLDBLayer(); Poznámka: často se setkáme s implementací factory bez parametru. Ten je potom zjištěn v těle metody například z nějakého konfirugračního souboru. Rozhodnutí o použíté DB udělá uživatel při instalaci systému.

Jen jedno připojení k databázi Vzor Singleton pro připojení k DB Připojení je obecně drahá záležitost Nepřipojuji se tehdy, když uz spojením mám

// jedina trida, ktera umi vsechno s DB class DB { private static $instance = null; private $db_link = null; private $result = null; private function construct() { public static function getinstance() { if (self::$instance == null) { self::$instance = new DB(); self::$instance->connect(); return self::$instance; public function connect() { if ($this->db_link == null) { $link = mysqli_connect(db_host, DB_USER, DB_PASSWD, DB_NAME); if (!$link) { throw new DBException(mysqli_errno($link)); mysqli_select_db($link,db_name); $this->db_link = $link; return $this->db_link;

// pokračování public function query($sql) { $this->connect(); $this->result = mysqli_query($this->db_link,$sql); if (mysqli) if (!$this->result) { throw new DBException(mysqli_error($this->db_link), $sql); return $this->result;

Martin Klíma DĚKUJI ZA POZORNOST