Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[PHP][PDO]

Pagina: 1
Acties:

  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Ik ben bezig met PDO en ben nu gestuit op een vreemd probleem zodra ik het errmode attribute instel op exception. Ik wil met onderstaande code de tabellen ophalen uit de database en vervolgens de inhoud van deze tabellen inlezen. Zolang ik de errmode attribute niet instel gaat het prima en wordt alles weergegeven. Zodra ik deze wel instel krijg ik ineens de melding dat de gewenste tabel (die juist is opgehaald dmv show tables) niet bestaat. Ik wil wel gebruik maken van exceptions voor mijn error handler. Waar kan het dus fout gaan?
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try {
    $db = new PDO($dsn, $this->config["user"], $this->config["pass"]);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $sql["tables"] = "SHOW TABLES";
    $sql["contents"] = "SELECT * FROM `:root`";
    
    $tables = $db->prepare($sql["tables"]);
    $contents = $db->prepare($sql["contents"]);
    
    $tables->execute();
    
    foreach($tables->fetchAll(PDO::FETCH_COLUMN) as $table){
        $contents->execute(Array(":root" => $table));
        print "Tabel ".$table."<br />";
        print_r($contents->fetchAll(PDO::FETCH_COLUMN));
        print "<br /><br />";
    }           
} catch(PDOException $e){
    return $this->Error("Database Error Occurred. ".$e->getMessage(), 300, SYSTEM_ERROR);
}


Dit is de melding die ik krijg met Exception ingesteld waarbij tabel 'paths' de eerste tabel is die in de lijst staat.
code:
1
Database Error Occurred. SQLSTATE[42S02]: Base table or view not found: 1146 Table 'registry.'paths'' doesn't exist (300)

telefoontoestel


  • Kwastie
  • Registratie: April 2005
  • Laatst online: 26-11 22:05

Kwastie

Awesomeness

Als ik de fout bekijk zie ik dit:
code:
1
'registry.'paths''


terwijl ik denk dat het dit moet zijn:
code:
1
'registry'.'paths'


Ik verwacht dus dat er een verkeerde waarde in $table zit op regel 13.

edit:
Probeer de `` (backticks) van regel 6 ook eens weg te halen.

edit2:

Je kunt volgens mij ook niet de comlum/tabel-namen binden met PDO.

[ Voor 24% gewijzigd door Kwastie op 08-04-2011 15:46 ]

When I get sad i stop being sad and be awesome instead


  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Ik vond dat er inderdaad ook vreemd uitzien, maar als ik de backticks uit de query weg liet dan kreeg ik daarvan een foutmelding. Is het dan een bug in PDO waardoor de query niet goed wordt geprepared of zit er een fout in mijn kant van het verhaal?

[edit]
Op het regeltje waar ik de tabel naam weer laat geven komt deze ook goed te staan zolang ik de exception uitzet. Als ik dan het uitprobeer met een normale query lukt het weer wel foutloos. Het gaat dus idd ergens mis in de prepare statement.

[ Voor 34% gewijzigd door telefoontoestel op 08-04-2011 15:49 ]

telefoontoestel


  • hostname
  • Registratie: April 2009
  • Laatst online: 26-11 23:34
Je kan geen placeholders gebruiken voor onderdelen van queries (bijvoorbeeld tabelnamen), alleen maar voor values (getallen of dingen doe je normaal tussen quotes zou zetten).

  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Hoe kan ik dan "variabele" tabel namen gebruiken? Want het is nogal omslachtig om elke keer als er een tabel bijgevoegd wordt handmatig daar weer een query voor aan te maken.

telefoontoestel


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
telefoontoestel schreef op vrijdag 08 april 2011 @ 15:50:
Hoe kan ik dan "variabele" tabel namen gebruiken? Want het is nogal omslachtig om elke keer als er een tabel bijgevoegd wordt handmatig daar weer een query voor aan te maken.
PHP:
1
2
3
$query = sprintf('select foo, bar from %s where x = @y', $tablename);
$pq = $db->prepare($query);
$pq->bindParam('@y', 'woei');

Ik ben niet intiem bekend met PDO maar zoiets lijkt me :?

[ Voor 14% gewijzigd door RobIII op 08-04-2011 15:57 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Ok. Dat was ietwat voor de handliggend. Ik hoopte eigenlijk op een prepared statement methode voor alleen de volledige tabellen, maar ik begrijp dus dat dat niet gaat lukken hiermee. Bedankt ieder geval.

[ Voor 9% gewijzigd door telefoontoestel op 08-04-2011 15:56 ]

telefoontoestel


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Let wel op dat je verdomdes goed controleert dat $tablename van buitenaf niet beïnvloedbaar is (lees: geen userinput voor accepteren); dan heb je kans op SQL injection. Voor je prepared statement parameters zit je daarna wel goed.

[ Voor 26% gewijzigd door RobIII op 08-04-2011 15:58 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Ja. Dat was dus ook juist de reden waarom ik zoveel mogelijk gebruik wil maken van de prepared statements. In dit geval kan ik dus veilig zoeken zonder prepares, maar in andere functies die ik maak zal ik dus eerst pdo::quote moeten gaan gebruiken. Bedankt voor de heads-up

telefoontoestel


Verwijderd

Wat ik altijd doe in dit soort gevallen is iets als dit:
PHP:
1
2
3
if($_GET['table'] == 'users') $table = 'users';
elseif($_GET['table'] == 'products') $table = 'products';
else $table = 'users';

Op deze manier heb je nooit input die je niet verwacht of niet wilt hebben. Indien je lijst met mogelijkheden groeit kun je een constructie maken met de in_array functie. Dit werkt goed zolang je niet met al te grote lijsten werkt

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:48

MueR

Admin Devschuur® & Discord

is niet lief

Verwijderd schreef op vrijdag 08 april 2011 @ 16:37:
Wat ik altijd doe in dit soort gevallen is iets als dit:
But why? Als je dan zo nodig de tabel wil kunnen aanpassen en niets behalve wat string comparison doet doe dan iets als hieronder. Kan je iig nog wat extra uitzonderingen maken op het te retrieven spul zonder meteen 36 if/else dingen te produceren.
PHP:
1
2
3
4
5
6
7
8
9
10
switch (trim($_GET['table']))
{
  case 'users':
  case 'products':
  // al je valid tabellen hier
    $table = trim($_GET['table']);
    break;
  default:
    throw new DikkeVingerException('Doe eens niet');
}

[ Voor 15% gewijzigd door MueR op 08-04-2011 16:43 ]

Anyone who gets in between me and my morning coffee should be insecure.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
PHP:
1
2
3
4
5
6
7
8
9
10
$table = isset($_GET['table']) ? trim($_GET['table']) : null;
switch ($table)
{
  case 'users':
  case 'products':
  // al je valid tabellen hier
    break;
  default:
    throw new DikkeVingerException('Doe eens niet');
}


:Y)

[ Voor 7% gewijzigd door RobIII op 08-04-2011 17:01 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:48

MueR

Admin Devschuur® & Discord

is niet lief

Purist :P

Anyone who gets in between me and my morning coffee should be insecure.


Verwijderd

Dan lijkt het me logischer om alle valide tabellen in een array te zetten:
PHP:
1
2
3
4
5
if(!isset($_GET['table'])) throw new Exception('No table supplied');
$table = $_GET['table'];

$valid = array('user', 'product', 'image', 'client', 'department')
if(!in_array($table, $valid)) throw new Exception('Invalid table');

Komt op hetzelfde neer maar het is toch echt korter (en leesbaarder) dan X keer een switch case.

  • fleppuhstein
  • Registratie: Januari 2002
  • Laatst online: 21-10 21:48
Verwijderd schreef op vrijdag 08 april 2011 @ 17:06:
Dan lijkt het me logischer om alle valide tabellen in een array te zetten:
PHP:
1
2
3
4
5
if(!isset($_GET['table'])) throw new Exception('No table supplied');
$table = $_GET['table'];

$valid = array('user', 'product', 'image', 'client', 'department')
if(!in_array($table, $valid)) throw new Exception('Invalid table');

Komt op hetzelfde neer maar het is toch echt korter (en leesbaarder) dan X keer een switch case.
Leesbaar ? Hoe kan jij snel zien als die regel mega lang wordt omdat er 50 tabellen in zitten ? Die case switch is veel overzichtelijker, makkelijker "maintain"-baar. Neem bijvoorbeeld bubbele tabel namen, zie je zo. Ook als je met meerdere developers werkt via een source controle systeem, een line offset los je wel op met een merge. Als iedereen op een regel gaat zitten aanpassen krijg je snel conflicten.

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:48

MueR

Admin Devschuur® & Discord

is niet lief

Verwijderd schreef op vrijdag 08 april 2011 @ 17:06:
Dan lijkt het me logischer om alle valide tabellen in een array te zetten:
.. code ..
Komt op hetzelfde neer maar het is toch echt korter (en leesbaarder) dan X keer een switch case.
Je hebt de reden die ik gaf voor een switch niet gelezen. Het staat je toe veel specifieker te zijn voor bepaalde tabellen.

Je doet schijnbaar overal SELECT * FROM TABLE. Dat is an sich al niet enorm handig, maar a la. Op sommige tabellen wil je waarschijnlijk niet eens alle columns kunnen selecteren. Password hashes bijvoorbeeld wil je altijd buiten beschouwing laten, je kan er toch niets mee (en als je dat wel kan, is het een major security issue).

Een voorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$rawTableName = (isset($_GET['table']) ? trim($_GET['table']) : null);
switch ($rawTableName)
{
  case 'users':
    $fields = 'UserId, UserName, Email';
    $tableName = $rawTableName;
    break;
  case 'never':
  case 'gonna':
  case 'give':
  case 'you':
  case 'up':
    $fields = 'Never, Gonna, Let, You, Down';
    $tableName = $rawTableName;
    break;
  default:
    throw new DikkeVingerException('Rickrolled!');
}
$sql = "SELECT {$fields} FROM {$tableName}";

Betekent wel dat je niet blind dezelfde query overal voor kan gebruiken, maar wel een stuk minder loze data in je results, vooral de data die je toch al niet wil tonen.

Anyone who gets in between me and my morning coffee should be insecure.


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

offtopic:
* NMe schopt MueR. Het is dat ik via mijn mobiel browse, anders had je nu een roze nick gehad. :/

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • ameesters
  • Registratie: Juni 2008
  • Laatst online: 05-01-2022
MueR schreef op vrijdag 08 april 2011 @ 16:42:
[...]

But why? Als je dan zo nodig de tabel wil kunnen aanpassen en niets behalve wat string comparison doet doe dan iets als hieronder. Kan je iig nog wat extra uitzonderingen maken op het te retrieven spul zonder meteen 36 if/else dingen te produceren.
PHP:
1
2
3
4
5
6
7
8
9
10
switch (trim($_GET['table']))
{
  case 'users':
  case 'products':
  // al je valid tabellen hier
    $table = trim($_GET['table']);
    break;
  default:
    throw new DikkeVingerException('Doe eens niet');
}
Wist u dat: Switches in php onefficiënt zijn, en je beter if .. else kan gebruiken.
in ieder geval in pre 5.3 versies...

Bron 1: http://www.fluffycat.com/...ance-Tuning-if-VS-switch/
Bron 2: http://www.phpbench.com/
Bron 3: Google "php switch performance" ;)

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Wist u dat: dergelijke premature micro-optimalisaties geen enkel doel dienen en het veel handiger is om makkelijker te onderhouden code te schrijven dan code die 3 microseconden sneller runt? Jouw eerste voorbeeld toont aan dat je bij 100.000 iteraties door dezelfde switch met 5 elementen een whopping 21 milliseconden sneller bent dan de equivalente if/else-structuur. Zonder loop zou dat dus theoretisch 0.21 microseconde sneller zijn. Nounou. ;)

[ Voor 41% gewijzigd door NMe op 09-04-2011 00:31 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Los daarvan, een array kun je ook gewoon per regel specificeren:
'users',
'products',
...

Ik ben zelf geen voorstander van switch statements in gedeelde source omgevingen omdat er altijd iemand een keer een break statement vergeet in mijn ervaring. Maar goed, ieder z'n eigen voorkeur :)

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:48

MueR

Admin Devschuur® & Discord

is niet lief

Ja, ik weet dat je een array over meerdere regels mag opschrijven. Je kijkt echter niet naar wat ik doe in m'n voorbeeld code.

Anyone who gets in between me and my morning coffee should be insecure.

Pagina: 1