Diskuze: RS - hledání stránky hází fatal error Uncaught PDOException
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.


public function dotazNaStranku($url)
{
Db::dotaz('SELECT FROM `stranky` WHERE url = ?', array($url));
}
Chybi ti tam, co chces vybrat. Zkus to takhle.
public function dotazNaStranku($url)
{
Db::dotaz('SELECT * FROM `stranky` WHERE url = ?', array($url));
}
mat.masar:29.9.2018 22:03
Ano už to neháže chybu, ale rovnou se to přesměruje na "chyba", z toho vyplývá, že to vyhodnotilo, že dotaz zda existuje stránka s daným url neexistuje, ale přitom ano. V čem je tedy chyba?
Edit: musím mít v souboru SmerovacKontroler (fce zpracuj)
$SpravceStranek = new SpravceStranek();
a potom
if (file_exists('kontrolery/' . $tridaKontroleru . '.php'))
$this->kontroler = new $tridaKontroleru;
elseif ($SpravceStranek->dotazNaStranku($naparsovanaURL)>0)
$this->kontroler = StrankyKontroler;
else
$this->presmeruj('chyba');
Nebo jak to funguje? Toto je něco co mě hodně mate.
Jan Lupčík:30.9.2018 0:26
Ahoj,
myslím, že tvoje metoda dotazNaStranku
by měla něco vracet.
Teď pouze něco volá, avšak její návratová hodnota je void
.
Stačí tedy přidat jen kouzelné slovíčko return
a mělo by to
fungovat.
mat.masar:1.10.2018 21:02
Ahoj, jsem moc vděčný za tvůj příspěvek, zase jsem se posunul o něco
dál
public function dotazNaStranku($url)
{
Db::dotaz('SELECT * FROM `stranky` WHERE url = ?', array($url));
return $url;
}
Nyní to vyhazuje jen, že probíhá konverze array na string v této fci
public static function dotaz($dotaz, $parametry = array())
{
$navrat = self::$spojeni->prepare($dotaz);
$navrat->execute($parametry);
return $navrat->rowCount();
}
Což ano je chyba, ale jelikož to zřejmě není tak závažné, tak bych to
nechal na později.
Spíš mě teď trápí to, proč když zadám localhost/onas
tak se mi vypíše seznam stránek(místo samotného článku) a je tam vypsaná
stránka O nás (ze které vede odkaz na url onas) i se svým
popiskem...když na ten odkaz kliknu tak se vlastně nic nestane, protože mě
to hodí zpět na tuto stránku.
Nevím jestli to může být způsobené tou chybou konverze, ale je pro mě strašně divné, proč se pod url adresou onas vypišou všechny stránky(toto má nastat, pokud url adresa neexistuje(do budou to smažu a nahradím 404, ale pro teď je to dobrý pokrok)) a ne rovnou daná stránka.
Jan Lupčík:2.10.2018 11:58
Ahoj,
je to závažné, vracíš jen URL. Zřejmě máš ve třídě Db
i
jiné metody, které by ti mohly něco vracet. Něco jako vyber
...
nevím, jak to může být v češtině.
To použij místo dotazu a rovnou to vrať (tedy tu hodnotu, co ti vrátí daná
metoda). Poté by to už mělo fungovat.
'Nyní to vyhazuje jen, že probíhá konverze array na string v této
fci'
Chybova hlaska ti pise konkretni cislo radku.
Pres var_dump si vypis promenne. Obvykle to zapisuji:
var_dump('url=', $url); // vypise napr url=string(22) ht...
Kdyz mas tech dumpu v kodu vic a zapomenes nektery zakomentovat, tak se da vyhledat podle "var_dump('url=".
'zadám localhost/onas tak se mi vypíše seznam stránek(místo samotného
článku)'
Pak mas nekde spatne logiku nebo se nenasla stranka.
Kazdopadne, Db::dotaz ti navraci rowCount(); misto dat. Takze z toho musis
vycucat jeste nekde data.
echo Db::dotaz('SELECT * FROM `stranky` WHERE url = ?', array($url)); // ti vypise treba 0, 1 nebo 23.
mat.masar:3.10.2018 19:34
Jestli jsem to tedy pochopil správně, tak to momentálně nic nedělá skrz toto?
Notice: Array to string conversion in C:\xampp\htdocs\Modely\Db.php on line 23
Db.php ->fce dotazJeden(změnil jsem to pouze z dotaz na dotazJeden)
public static function dotazJeden($dotaz, $parametry = array())
{
$navrat = self::$spojeni->prepare($dotaz);
$navrat->execute($parametry);
return $navrat->fetch();
}
Každopádně chyba je stále stejná.
Já jsem měl tento dotaz z důvodu zjištění, zda daná stránka existuje,
proto jsem měl jenom dotaz na rowcount a porovnával jsem to s nulou.
$tridaKontroleru = $this->pomlckyDoVelbloudiNotace(array_shift($naparsovanaURL)) . 'Kontroler';
if (file_exists('kontrolery/' . $tridaKontroleru . '.php'))
$this->kontroler = new $tridaKontroleru;
elseif (SpravceStranek::dotazNaStranku($naparsovanaURL)>0)
$this->kontroler = new StrankyKontroler();
Zjištoval jsem, zda daná stránka existuje, pokud ano tak kontroler = StrankyKontroler a ne StrankyKontroler(nebo resp. $tridaKontroler), abych zajistil, že to nepřejde na 404(chyba), ale přejde to na StrankyKontroler.
Kde jsem to chtěl zpracovat
if(!empty($parametry[0]))
{
//Získání stránky podle url
$stranka = $spravceStranek->vratStranku($parametry[0]);
A myslel jsem si, že v $parametry[0] bude v tomto případě "onas".
public function vratStranku($url)
{
return Db::dotazJeden('SELECT `stranka_id`, `titulek`, `obsah`, `url`, `popisek`, `klicova_slova` FROM `stranky` WHERE `url` = ? ', array($url));
}
A načte se tedy stránka onas.
Ta chyba s konverzí array na string je podle mě způsobena tím, že $naparsovanaUrl je string, protože:
public function zpracuj($parametry)
{
$naparsovanaURL = $this->parsujURL($parametry[0]);
if(empty($naparsovanaURL[0]))
$this->presmeruj('clanek/uvod');
// kontroler je 1. parametr URL
$tridaKontroleru = $this->pomlckyDoVelbloudiNotace(array_shift($naparsovanaURL)) . 'Kontroler';
if (file_exists('kontrolery/' . $tridaKontroleru . '.php'))
$this->kontroler = new $tridaKontroleru;
elseif (SpravceStranek::dotazNaStranku($naparsovanaURL)>0)
$this->kontroler = new StrankyKontroler();
else
$this->presmeruj('chyba');
//Volání kontroleru
$this->kontroler->zpracuj($naparsovanaURL);
Peter Mlich napsal jsi víceméně to stejné.
Trošku bych se chtěl omluvit, že to tu natahuji, ale pořád mi to není jasné, kde vlastně dělám chybu. Myslel jsem si, že to bude banální....(jako pro Vás)
Jan Lupčík:3.10.2018 20:55
Ahoj,
hlavně bych rád viděl celou tu chybu, zřejmě mi teď něco uniká, ale
nevím, kde může být chyba. Můžeš nám poslat trochu ucelenější kód i
přímo s řádkem, kde je ta chyba?
Taky si zjisti, jestli ti vratStranku($url)
vrací opravdu to, co
ty chceš. A to třeba tak, jak zmínil kolega výše, akorát tam také
přidáš volání té metody pro získání jejího výsledku.
mat.masar:3.10.2018 21:20
Možná to bude mým vyjadřováním. Zkusím poslat ucelenější kus kódu + screeny.
Chyba - fotka "localhost-onas", tabulka v db - phpmyadmin-stranky (nevím teda, jestli vidíš názvy fotek, které jsem přiložil).
Soubor db.php, řádek 20-25 (23 je $navrat->execute)
public static function dotazJeden($dotaz, $parametry = array())
{
$navrat = self::$spojeni->prepare($dotaz);
$navrat->execute($parametry);
return $navrat->fetch();
}
Soubor SpravceStranek.php, fce pro vracení stránky
public function vratStranku($url)
{
return Db::dotazJeden('SELECT `stranka_id`, `titulek`, `obsah`, `url`, `popisek`, `klicova_slova` FROM `stranky` WHERE `url` = ? ', array($url));
}
Soubor StrankyKontroler.php celá fce zpracuj
public function zpracuj($parametry)
{
// Vytvoření instance modelu, který nám umožní pracovat se stránkami
$spravceStranek = new SpravceStranek();
$spravceUzivatelu = new SpravceUzivatelu();
$uzivatel = $spravceUzivatelu->vratUzivatele();
$this->data['admin'] = $uzivatel && $uzivatel['admin'];
//Je zadáno url stránky ke smazání
if(!empty($parametry[1]) && $parametry[1] == 'odstranit')
{
$this->overUzivatele(true);
$spravceStranek->odstranStranku($parametry[0]);
$this->pridejZpravu('Stránka byla úspěšně smazaná');
$this->presmeruj('stranka');
}
//Je zadáno url stránky
if(!empty($parametry[0]))
{
//Získání stránky podle url
$stranka = $spravceStranek->vratStranku($parametry[0]);
//pokud nebyla stránka nalezena, přesměrovani na ChybaKontroler
if(!$stranka)
$this->presmeruj('chyba');
// Hlavička stránky
$this->hlavicka = array('titulek' => $stranka['titulek'], 'klicova_slova' => $stranka['klicova_slova'], 'popis' => $stranka['popisek']);
//Promměnné pro šablonu
$this->data['titulek'] = $stranka['titulek'];
$this->data['obsah'] = $stranka['obsah'];
//Nastavení šablony
$this->pohled = 'stranka';
}
else
//Není zadáno url stránky, vypíšeme všechny
{
$stranky = $spravceStranek->vratStranky();
$this->data['stranky'] = $stranky;
$this->pohled = 'stranky';
}
}
Soubor SmerovacKontroler.php (rozřazovač, jak název napovídá ) fce zpracuj
public function zpracuj($parametry)
{
$naparsovanaURL = $this->parsujURL($parametry[0]);
if(empty($naparsovanaURL[0]))
$this->presmeruj('clanek/uvod');
// kontroler je 1. parametr URL
$tridaKontroleru = $this->pomlckyDoVelbloudiNotace(array_shift($naparsovanaURL)) . 'Kontroler';
if (file_exists('kontrolery/' . $tridaKontroleru . '.php'))
$this->kontroler = new $tridaKontroleru;
elseif (SpravceStranek::dotazNaStranku($naparsovanaURL)>0)
$this->kontroler = new StrankyKontroler();
else
$this->presmeruj('chyba');
//Volání kontroleru
$this->kontroler->zpracuj($naparsovanaURL);
//Nastavení proměnných do šablon
$this->data['titulek'] = $this->kontroler->hlavicka['titulek'];
$this->data['popis'] = $this->kontroler->hlavicka['popis'];
$this->data['klicova_slova'] = $this->kontroler->hlavicka['klicova_slova'];
//Nastavení hlavní šablony
$this->pohled = 'rozlozeni';
//Uložení zpráv do dat šablony
$this->data['zpravy'] = $this->vratZpravy();
}
Je to zřejmě trochu přehnané, ale doufám, že to pomůže nejvíc
Edit:
Počítejme s tím, že seznam stránek nemá žádnou přidanou hodnotu.
Momentálně to slouží jen jako "mezikrok" Celé jsem toto "postavil" na
principu článků, které mi fungují a akorát jsem přepsal proměnné a
další části...
Pokud je radek 23-25 to, co pises, pak bych si tam dal pred
echo '<br>'; var_dump('dotaz=', $dotaz);
echo '<br>'; var_dump('parametry=', $parametry);
$navrat = self::$spojeni->prepare($dotaz);
Myslim si, ze ten dotazJeden asi pouzivas jeste nekde jinde na neco, kde
misto array (do parametry) mu tam das string.
Jeste muzes zkusit to, ze pred volanim dotazu si tam das echo. (ctrl+f si najdes
vsechno, kde ho pouzijes dotazJeden)
echo 'volani 1'; // 2,, 3
Db::dotazJeden(...)
Pak budes vedet, odkud jsi jej zavolal. Ale to se da poznat i z toho vypisu
sql dotazu.
Myslim, ze jsem mel vic ukecanejsi php, vypise i vsechny predchozi kroky.
Takovou tabulku to vypisovalo
https://i.stack.imgur.com/MVjTH.png
Nechapu, proc vysledek dotazu preskladavas do jine array. Indexy se lisi jen v
popis vs popisek.
$this->hlavicka = array('titulek' => $stranka['titulek'],
'klicova_slova' => $stranka['klicova_slova'], 'popis' =>
$stranka['popisek']);
mat.masar:7.10.2018 15:21
S tím dumpem to vypisuje:
string(6) "dotaz=" string(37) "SELECT * FROM
stranky
WHERE url = ?"
string(10) "parametry=" array(1) { [0]=> array(0) { } }
Notice: Array to string conversion in C:\xampp\htdocs\Modely\Db.php on line 25
s připsáním echa
Volani 4
string(6) "dotaz=" string(37) "SELECT * FROMstranky
WHERE url = ?"
string(10) "parametry=" array(1) { [0]=> array(0) { } }
Notice: Array to string conversion in C:\xampp\htdocs\Modely\Db.php on line 25
A volani 4 je tady:
public function dotazNaStranku($url)
{
echo "Volani 4";
Db::dotazJeden('SELECT * FROM `stranky` WHERE url = ?', array($url));
return $url;
}
A tuto funkci volám na ověření, zda daná stránka existuje ve SmerovacKontroler ...
public function zpracuj($parametry)
{
$naparsovanaURL = $this->parsujURL($parametry[0]);
...
if (file_exists('kontrolery/' . $tridaKontroleru . '.php'))
$this->kontroler = new $tridaKontroleru;
elseif (SpravceStranek::dotazNaStranku($naparsovanaURL)>0)
$this->kontroler = new StrankyKontroler();
...
}
A $naparsovanaURL se bere z funce parsujURL
private function parsujURL($url)
{
$naparsovanaURL = parse_url($url);
$naparsovanaURL["path"] = ltrim($naparsovanaURL["path"], "/");
$naparsovanaURL["path"] = trim($naparsovanaURL["path"]);
$rozdelenaCesta = explode("/", $naparsovanaURL["path"]);
return $rozdelenaCesta;
}
Z čehož vyplývá, že $naparsovanaURL je string, co jiného tam mám ale vložit, aby to bylo pole a zároveň se z toho přebrala url na vyhledání = plnilo by to svou funkci.
Přeskládávat...no nevím co tím myslíš, dává se to do "hlavicka", protože ta se potom předává dál na výpisu konkrétní stránky...
'Z čehož vyplývá, že $naparsovanaURL je string'
parsujURL($url) ... $rozdelenaCesta = explode("/", $naparsovanaURL["path"]);
return $rozdelenaCesta; -- vystup funkce -- array
Vystup funkce je array.
$x = array(123); // tve: $naparsovanaURL = $this->parsujURL($parametry[0]);
$y = array($x); // vysledkem je array(array(123)) // tve: array($url)
$navrat->execute($parametry);
Co ti na to mam rici? Pres funkci parsujURL vytvoris array a zabalis ji do
dalsi array, prikaz dotazJeden('SELECT * FROM stranky
WHERE url =
?', array($url));. Jedno arrayovani tam byt nema.
Navic nemas osetrene explode. Pokud mu das string bez lomitka,
tak ti vrati false, podle dokumentace http://php.net/explode , nadpis Return Values . A false neni
array.
Ostatne, var_dump ti to take pise
string(10) "parametry=" array(1) { [0]=> array(0) { } }
$parametry = array( 0 => array() ); // v php bys to vytvoril takto
var_dump($parametry) // array(1) { [0]=> array(0) { } }
mat.masar:8.10.2018 20:25
Já se moc omlouvám, ale já se v tom strašně ztrácím...možná víc a víc...
Odstranil jsem to další zabalování ->
public function dotazNaStranku($url)
{
return Db::dotazJeden('SELECT `stranka_id`, `titulek`, `obsah`, `url`, `popisek`, `klicova_slova` FROM `stranky` WHERE url = ?', $url);
}
Ale teď mi to hází zase chybu
Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2031 in -> C:\xampp\htdocs\Modely\Db.php:23 Stack trace: #0 C:\xampp\htdocs\Modely\Db.php(23): PDOStatement-> >execute(Array) #1 C:\xampp\htdocs\Modely\SpravceStranek.php(43): Db::dotazJeden('SELECT `stranka...', > Array) #2 C:\xampp\htdocs\Kontrolery\SmerovacKontroler.php(38): SpravceStranek::dotazNaStranku(Array) #3 > C:\xampp\htdocs\index.php(21): SmerovacKontroler->zpracuj(Array) #4 {main} thrown in > C:\xampp\htdocs\Modely\Db.php on line 23
Což zase odkazuje sem na řádek $navrat->execute($parametry)
public static function dotazJeden($dotaz, $parametry = array())
{
$navrat = self::$spojeni->prepare($dotaz);
$navrat->execute($parametry);
return $navrat->fetch();
}
S tím explodem jsi na něco narazil, zkoušel jsem to a když zadám localhost/onas vyskočí výše zmíněná chyba.. když zadám localhost/onas/ tak se to přesměruje na chybu a když zadám localhost/onas/onas tak to vypíše tu stránku kterou jsem chtěl....Jediné co vlastně teď chci, aby to vypisovalo správnou stránku (jako v pripade /onas/onas) jenom při zadání /onas...
A to explode jsi uz osetril? Nebo cekas na nejaky zazrak?
mat.masar:9.10.2018 18:01
Jediné co mě napadlo bylo toto:
private function parsujURL($url)
{
$naparsovanaURL = parse_url($url);
$naparsovanaURL["path"] = ltrim($naparsovanaURL["path"], "/");
$naparsovanaURL["path"] = trim($naparsovanaURL["path"]);
if (strpos($naparsovanaURL["path"], "/") !== false)
$rozdelenaCesta = explode("/", $naparsovanaURL["path"]);
else
$rozdelenaCesta = array($naparsovanaURL["path"]);
return $rozdelenaCesta;
}
"Odladil" jsem to i podle toho, že mi to vypisovalo chybu že výsledkem mám string $rozdelenaCesta = $naparsovanaURL["path"];, tak jsem to obalil array(), podle příkladu, který jsi psal výše...Nyní to už nevypisuje chybu ohledně nově přidaného kódu, ale jinak se nic nezměnilo...
Znamená to, že to stále není ošetřené? Jinak by to fungovalo? Nebo proč to pořád háže chybu? (uncaught exception).
Proc tam nepouzijes treba $a = $naparsovanaURL["path"] a dal pracujes jen s
$a?
To ostatni netusim. Fakt, kdyz clovek nema pred sebou cely program, tak se to
resi dost tezko. Jakoze, stale se te na neco vyptavat, co s tim treba vubec
nesouvisi....
Rikal jsi snad, ze ti to v nejake kombinaci fungovalo?
Zkus ten dotaz napsat primo, jako string, zda ti funguje.
Pak pouzi tu svou verzi a dej si tam vypis konecneho dotazu, zda se shoduji,
pripadne, v cem je rozdil. Nevim, zda to vubec jde, vypsat dotaz, kdyz je tam
prikaz execute (coz normalne znamena spustit, provest), pdo takhle nepouzivam.
Jsem zvykly poskladat si dotaz jako string. Ne mu davat parametry. V tomhle by
ti spis poradil Kit (z forka programujte.com) nebo google.
mat.masar:11.10.2018 16:47
Nikdy mi to právě nefungovalo...Což je ten hlavní problém...
Zkusím napsat Kitovi.
Díky
Jasne. No, ale zkusil jsi poslat do pdo primo sql dotaz? Cisty, primy, bez tech serepeticek jako parseurl a pod?
jo, a jeste muzes zkusit tenhle kod na pdo
https://www.itnetwork.cz/…ba1bdafb5b8f#…
+20 Zkušeností

mat.masar:28.10.2018 19:41
Problém byl v tomto:
$tridaKontroleru = $this->pomlckyDoVelbloudiNotace(array_shift($naparsovanaURL)) . 'Kontroler';
array_shift měnil url, ikdyz vsechno bylo vpořádku.
Výsledek
public function zpracuj($parametry)
{
$naparsovanaURL = $this->parsujURL($parametry[0]);
$naparsovanaURL2 = $naparsovanaURL;
if(empty($naparsovanaURL[0]))
$this->presmeruj('clanek/uvod');
// kontroler je 1. parametr URL
$tridaKontroleru = $this->pomlckyDoVelbloudiNotace(array_shift($naparsovanaURL2)) . 'Kontroler';
if (file_exists('kontrolery/' . $tridaKontroleru . '.php')){
$this->kontroler = new $tridaKontroleru;
$naparsovanaURL = $naparsovanaURL2;
}
elseif (SpravceStranek::dotazNaStranku($naparsovanaURL)>0) {
$this->kontroler = new StrankyKontroler();
Peter Mlich:29.10.2018 8:37
Aha. Ano. Ta funkce uklada zpet do pole. V tomto pripade je to to nevyhoda a chyba, ktera se dost obtizne hleda.
Nejspis to bylo vymyslene tak kvuli uspore mista v pameti a casu. Treba pri
sortovani obriho pole je vyhodnejsi delat to v nem nez si cele pole duplicitne
vykopirovat (treba 100G , ikdyz
dnes je to spis otazka blik, tusim nejnovejsi ssd nebo pameti maji zapis kolem
5G/S ).
Kdybys nekdy podobnou vlastnost chtel zamerne vyuzit, je to &. (pri rozsahlejsich projektech je treba uvolnovat pamet a setrit, kde se da)
function xxx(&$prom) {$prom = 2;}
$a = 1;
xxx($a);
echo $a;
Zobrazeno 21 zpráv z 21.