Autor | Zpráva | ||
---|---|---|---|
Jirik1 Profil * |
Ahoj, zkouším spustit insert pomoci PDO a nechce se mi to rozjet. Za pomoc budu moc rád.
Chybové hlášení: Notice: Undefined property: Insert::$pdo in C:\wamp64\www\oop\pdo.php on line 32 Fatal error: Uncaught Error: Call to a member function prepare() on null in C:\wamp64\www\oop\pdo.php on line 32 Error: Call to a member function prepare() on null in C:\wamp64\www\oop\pdo.php on line 32 Kód: <?php class Dbi { private $pdo; public function __construct() { define('SQL_HOST', 'localhost'); define('SQL_DBNAME', 'database'); define('SQL_USERNAME', 'root'); define('SQL_PASSWORD', ''); $dsn = 'mysql:dbname=' . SQL_DBNAME . ';host=' . SQL_HOST . ''; $user = SQL_USERNAME; $password = SQL_PASSWORD; try { $this->pdo = new PDO($dsn, $user, $password); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die('Spatne databazove spojeni: ' . $e->getMessage()); } } } class Insert extends Dbi { public function vloz() { $dotaz = $this->pdo->prepare("INSERT into uzivatele (id, jmeno, heslo, akce) VALUES(?, ?, ?, ?)"); $vysledek = $dotaz->execute(array(NULL, '1', '1', '1')); } } $connect = new Insert; $connect->vloz(); Když vložím: $dotaz = $this->pdo->prepare("INSERT into uzivatele (id, jmeno, heslo, akce) VALUES(?, ?, ?, ?)"); $vysledek = $dotaz->execute(array(NULL, '1', '1', '1')); Moc díky. Už to mám, chyba byla v tom private pdo. |
||
Joker Profil |
#2 · Zasláno: 17. 11. 2018, 00:01:41
Jirik1:
Problém je celkem zřejmý z chybové hlášky, ve třídě Insert metoda vloz používá nedefinovaný atribut pdo. Atribut stejného jména sice je na rodičovské třídě Dbi, nicméně je private, takže pro třídu Insert není přístupný. Mimo téma mi nepřijde moc praktické mít přihlašovací údaje natvrdo uvnitř databázové třídy (čímž pak ta třída nejde vzít a použít pro připojení k jiné databázi). |
||
Jirik1 Profil * |
#3 · Zasláno: 17. 11. 2018, 00:54:50
Joker:
Ok, přepsal jsem to: <?php class DataDatabaseUzivatele { public function __construct() { define('SQL_HOST', 'localhost'); define('SQL_DBNAME', 'database'); define('SQL_USERNAME', 'root'); define('SQL_PASSWORD', ''); } } class Dbi extends DataDatabaseUzivatele { protected $pdo; public function __construct() { parent::__construct(); $dsn = 'mysql:dbname=' . SQL_DBNAME . ';host=' . SQL_HOST . ''; $user = SQL_USERNAME; $password = SQL_PASSWORD; try { $this->pdo = new PDO($dsn, $user, $password); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die('Spatne databazove spojeni: ' . $e->getMessage()); } } } |
||
Joker Profil |
#4 · Zasláno: 17. 11. 2018, 19:15:10
Jirik1:
To má dva problémy: 1. To o čem jsem psal to neřeší. Třída Dbi pořád nejde beze změny vzít a použít pro jiné připojení. Závislost se sice přesunula do rodičovské třídy (resp. ne tak docela, ale asi byl takový úmysl), jenže pak bych na změnu údajů třídě Dbi potřeboval změnit rodiče, což nejde jednoduše udělat. 2. Ta třída DataDatabaseUzivatele je zbytečná. Stačilo by ty define vyhodit před ní a zbytek smazat (včetně odkazů v Dbi). Definice konstant má globální platnost. Pak by to i trochu fungovalo, třídu Dbi by šlo beze změny použít i s jinými údaji: Okolní kód by prostě definoval jiné hodnoty těch konstant. Ještě pár tipů: • Objekty by měly být uzavřené, dá se říci „samonosné“. Vnitřek objektu by neměl záviset na okolním kódu a veškerá komunikace mezi objektem a okolí by se měla odehrávat přes volání metod nebo práci s atributy. • Z předchozího bodu vyplývá, že není ideální uvnitř objektu používat globální konstanty. (Protože se nabourává hranice mezi objektem a okolím, funkčnost objektu závisí na okolním kódu.) • Dál z toho vyplývá, že nejlepší cesta pro předání nějakých informací do objektu jsou parametry metod. Čili lepší řešení by bylo definovat __construct($dsn, $user, $password) a pak můžu objekt používat s libovolnými údaji, které mu jednoduše předám ve volání konstruktoru. • Kromě toho bych si položil otázku, jaký účel ten objekt má, resp. co je jeho odpovědnost. • Přitom existuje tzv. „single responsibility principle“, tj. princip jedné odpovědnosti: Každý objekt má být odpovědný za právě jednu věc. Dá se to poznat právě tím, že si zkusíte jednou větou říct, jakou odpovědnost ten objekt, má, co má na starosti, potažmo „co ten objekt vlastně dělá“. Odpověď třeba: „Tenhle objekt slouží jako repozitář uživatelů, má na starosti získání objektů požadovaných uživatelů a případně ukládání změn“ vypadá vcelku dobře. Jakmile to začne být „Tenhle objekt převezme požadavek od uživatele a dohledává data v databázi a zobrazuje nějaký výsledek a taky loguje chybové hlášky a ještě mi vaří kafe“, zjevně ten objekt toho má na starosti příliš. • Na druhé straně když přidělíte konkrétní třídě konkrétní odpovědnost, je pak fajn se na tu třídu podívat, jestli skutečně dělá jen tu svou práci a „nefušuje“ i do jiných odpovědností. Například řeknete, že tenhle objekt je repozitář uživatelů, a pak zjistíte, že kromě toho ještě prezentuje údaje uživateli, zpracovává případné chyby, atd. • Čili bych si položil otázku, co má mít na starosti ta třída Dbi. Přitom „obecné rozhraní pro komunikaci s databází“ není dobrá odpověď, protože na to už tam je ta třída PDO, tak k čemu další? |
||
Methez Profil * |
#5 · Zasláno: 18. 11. 2018, 13:18:21
Hlavně tam na začátku chybí use PDO;
|
||
Joker Profil |
#6 · Zasláno: 18. 11. 2018, 14:11:28
Methez:
Podle mě to zdaleka není hlavní problém toho kódu a dokud nezačne používat jmenné prostory (namespaces), je to celkem zbytečné. |
||
Methez Profil * |
#7 · Zasláno: 18. 11. 2018, 14:53:18
Joker:
Souhlas :) Jirik1: Stáhni si hotovou PDO knihovnu. Vše je tam již pořešené a hlavně bezpečně. Nemá cenu znovu vynalézat kolo :) |
||
Jirik1 Profil * |
#8 · Zasláno: 19. 11. 2018, 20:11:50
Hoši, máte pravdu. Musel jsem se nad sebou zamyslet. Celé jsem to přepsal a teď to dává i smysl :-). Ještě to piluji.
Soubor dbi.php: <?php class Dbi { protected $pdo; public function __construct($sqlDbname, $sqlHost, $sqlUserName, $sqlPassword) { $dsn = 'mysql:dbname=' . $this->sqlDbname . ';host=' . $this->sqlHost . ''; $user = $this->sqlUserName; $password = $this->sqlPassword; try { $this->pdo = new PDO($dsn, $user, $password); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die('Spatne databazove spojeni: ' . $e->getMessage()); } } } <?php require_once 'dbi.php'; class DataDatabaseUzivatele extends Dbi { protected $sqlHost = 'localhost'; protected $sqlDbname = 'database'; protected $sqlUserName = 'root'; protected $sqlPassword = ''; public function __construct() { parent::__construct($this->sqlHost, $this->sqlDbname, $this->sqlUserName, $this->sqlPassword); } } <?php require_once 'lPDatabase.php'; class Insert extends DataDatabaseUzivatele { public function vloz($jmeno, $heslo, $akce) { if ($this->pdo) { $dotaz = $this->pdo->prepare("INSERT into uzivatele (id, jmeno, heslo, akce) VALUES(?, ?, ?, ?)"); $dotaz->execute(array(NULL, $jmeno, $heslo, $akce)); echo 'Zaznam byl vlozen.'; } else { echo 'Zaznam nebyl vlozen.'; } } } |
||
Časová prodleva: 5 let
|
0