prepared statements ZONDER WHERE STATEMENT
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
$link = mysqli_connect("localhost", "user", "", "db"); //Establishing connection to the database , this is alias of new mysqli('')
$query="SELECT * FROM profiles";
$stmt = $link->prepare($query);
//$stmt->bind_param("s",$anti_injection); // binding the parameter to it
$stmt->execute(); //Executing
$result = $stmt->get_result();
while($row = $result->fetch_array(MYSQLI_ASSOC)) // we used MYSQLI_ASSOC flag here you also can use MYSQLI_NUM or MYSQLI_BOTH
{
//Do stuff
}
$query="SELECT * FROM profiles";
$stmt = $link->prepare($query);
//$stmt->bind_param("s",$anti_injection); // binding the parameter to it
$stmt->execute(); //Executing
$result = $stmt->get_result();
while($row = $result->fetch_array(MYSQLI_ASSOC)) // we used MYSQLI_ASSOC flag here you also can use MYSQLI_NUM or MYSQLI_BOTH
{
//Do stuff
}
Ik krijg dan:
Call to a member function execute() on a non-object
Ik wil helemaal geen WHERE clause gebruiken in een query, is dat verplcith met een prepared statement?
Ik zie nergens een voorbeeld waar gewoon een query ZONDER WHERE CLAUSE gebruikt word in een prepared statement zoals:
"SELECT * FROM profiles"
Het lijkt me dan ook overbodig als je geen input waarde controleert.
Ik zie genoeg voorbeelden via google maar geen enkele zonder een WHERE statement.
UPDATE//opgelost met object connectie
Gewijzigd op 17/05/2017 17:46:19 door Daniel van Seggelen
Eerst begin je procedureel mysqi_connect() aan te roepen.
Daarna zou je $stmt = mysqli_prepare($link, $query);
kunnen gebruiken.
of je gaat direct voor
$link = new mysqli("localhost", "user", "", "db");
waarna $link wel een object is (en wat een logischer idee is, gezien je de rest van je code weer oo werkt)
Zie ook de voorbeelden op http://php.net/manual/en/mysqli.prepare.php
Alhoewel het niet aan te bevelen is om procedureel en object-georiënteerd door elkaar te gebruiken (het maakt je code niet per se beter te begrijpen) is het volledig legaal om het te doen; de PHP-documentatie noemt zelfs expliciet dat je de twee stijlen door elkaar kunt gebruiken (wat handig is als je bijvoorbeeld je code aan het omschrijven bent).
@Daniel:
De reden dat je geen codevoorbeelden zonder WHERE tegenkomt, is waarschijnlijk omdat het niet heel nuttig is om in een dergelijke situatie prepared statements te gebruiken. Ik zie overigens niet in waarom het niet zou kunnen. Zal zo eens kijken of ik e.e.a. op mijn eigen systeem kan reproduceren.
Daniel van Seggelen op 17/05/2017 11:45:36:
Call to a member function execute() on a non-object
Volg het kruimelpad terug. Ofwel het preparen gaat mis, ofwel het maken van een verbinding slaagt niet. Je controleert trouwens nergens of beide goed gaan...
Willem vp op 17/05/2017 14:37:10:
omdat het niet heel nuttig is om in een dergelijke situatie prepared statements te gebruiken.
Uniformiteit in het aanspreken van je database lijkt mij een pre.
PS en als je dan toch prepared statements wilt gebruiken dan is PDO wellicht een beter alternatief.
Gewijzigd op 17/05/2017 15:51:03 door Thomas van den Heuvel
Het maken van de verbinding gaat goed, anders zou je bij de aanroep van prepare() al een foutmelding krijgen.
Dat betekent dat de fout in de query zelf moet zitten; hoogstwaarschijnlijk een tabel die niet bestaat in de geselecteerde database.
De code die in de eerste post staat werkt bij mij in ieder geval probleemloos.
Toevoeging op 17/05/2017 16:10:04:
> Uniformiteit in het aanspreken van je database lijkt mij een pre.
Tot op zekere hoogte. Als ik een schroef moet vastdraaien kijk ik ook eerst of ik een schroevendraaier maat 1, 2 of 3 nodig heb. Ik gebruik niet steevast maat 2, omdat dat nu eenmaal uniform is. Vaak krijg je de schroef er wel mee vast, maar het geeft niet per se het optimale resultaat.
Datzelfde heb ik met prepared statements. De meeste queries kun je inderdaad prepared uitvoeren, maar dat wil niet zeggen dat prepared altijd het beste is. En om een suboptimale oplossing te gebruiken, alleen maar vanwege de uniformiteit vind ik nogal indruisen tegen mijn kwaliteitsbesef. ;-)
Bij queries die je slechts 1x uitvoert, zou je je moeten afvragen of die de overhead van het prepareren waard zijn. Wanneer je prepareert om SQL injection tegen te gaan is die overhead meestal wel te verdedigen. In dit specifieke geval is daar geen sprake van en dan vind ik het zonde om daar het prepared statement-vehikel voor te gebruiken. Ook wanneer je een paar duizend records tegelijkertijd moet inserten is een prepared statement meestal niet aan te raden, want dat is significant trager dan een multi-insert (waarbij je dan wel zelf ervoor moet zorgen dat je geen SQL injection faciliteert).
Gewijzigd op 17/05/2017 16:10:43 door Willem vp
Ik zie nu iets stoms, dat de queries een typo had in de tabelnaam bij het eerste voorbeeld, wat dus wel werkt, maar naast dat vraag ik mij af of er zonder input wel geadviseerd word om toch prepared statements te gebruiken zonder input?
Nog iets ik gebruik een class met de conn functie:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class DBD extends MySQLi
{
public $connection;
public $lang = '';
public function conn()
{
if (!$this->connection) {
$this->connection = mysqli_connect(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
mysqli_query($this->conn(),"set names 'utf8'");
mysqli_query($this->conn(),"SET CHARACTER SET 'utf8'");
}
return $this->connection;
}
}
// de connectie
$DBD = new DBD();
met dit krijg ik dezelfde fout, maar de connectie is toch een object?
$link = $DBD->conn(); //Establishing connection to the database , this is alias of new mysqli('')
$query="SELECT * FROM members";
$stmt = $link->prepare($query);
//$stmt->bind_param("s",$anti_injection); // binding the parameter to it
$stmt->execute(); //Executing
{
public $connection;
public $lang = '';
public function conn()
{
if (!$this->connection) {
$this->connection = mysqli_connect(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
mysqli_query($this->conn(),"set names 'utf8'");
mysqli_query($this->conn(),"SET CHARACTER SET 'utf8'");
}
return $this->connection;
}
}
// de connectie
$DBD = new DBD();
met dit krijg ik dezelfde fout, maar de connectie is toch een object?
$link = $DBD->conn(); //Establishing connection to the database , this is alias of new mysqli('')
$query="SELECT * FROM members";
$stmt = $link->prepare($query);
//$stmt->bind_param("s",$anti_injection); // binding the parameter to it
$stmt->execute(); //Executing
wat doe ik hier fout?
Gewijzigd op 17/05/2017 17:07:30 door Daniel van Seggelen
Willem vp op 17/05/2017 15:51:01:
Ook wanneer je een paar duizend records tegelijkertijd moet inserten is een prepared statement meestal niet aan te raden, want dat is significant trager dan een multi-insert (waarbij je dan wel zelf ervoor moet zorgen dat je geen SQL injection faciliteert).
Wut? Dat lijkt mij bij uitstek een situatie waar je prepared statements gebruikt. Maar dat is meestal niet de norm, en daarom gebruik ik standaard ook geen prepared statements omdat je geen meerwaarde hebt bij SELECT-statements.
Daniel van Seggelen op 17/05/2017 17:04:48:
Nog iets ik gebruik een class met de conn functie:
...
wat doe ik hier fout?
...
wat doe ik hier fout?
Deze class zit wel heel vreemd in elkaar. Maar wat in ieder geval niet aan te raden is is het instellen van een character encoding via SET NAMES en SET CHARACTER SET (doet dit laatste uberhaupt iets?). Hiervoor is de set_charset() methode.
Wat je je ook af zou moeten vragen is waarom je een wrapper gebruikt waarna je rechtstreeks met het gecreëerde mysqli-object gaat praten, wat is dan de meerwaarde van die class? Ook controleer je in geen van de stappen of de connectie slaagt. Op dit moment heeft heeft die class niet echt veel toegevoegde waarde, het neemt je geen werk uit handen.
Vergelijk: een class van het type Auto. In deze auto kun je een aantal zaken vervoeren, bijvoorbeeld een persoon en een krat bier.
Maar nu geef je bij de te vervoeren items ook weer een auto op....
Doe het liever zo:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
class DBD extends MySQLi
{
public $connection;
public $lang = '';
public function __construct()
{
parent::__construct(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
$this->query("set names 'utf8'");
$this->query("SET CHARACTER SET 'utf8'");
}
}
// de connectie
$DBD = new DBD();
$query="SELECT * FROM members";
$stmt = $DBD->prepare($query);
$stmt->execute(); //Executing
[/code]
$DBD is nu op dezelfde manier te gebruiken als Mysqi, maar los van de automatische connectie opbouw, kun je nog een aantal functies zelf toevoegen, waarmee deze extend pas echt nuttig kan worden.
Maak van DBD niet een doorgeefluik naar Mysqli, maar maak het tot een uitbreiding van de Mysqli-class
class DBD extends MySQLi
{
public $connection;
public $lang = '';
public function __construct()
{
parent::__construct(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
$this->query("set names 'utf8'");
$this->query("SET CHARACTER SET 'utf8'");
}
}
// de connectie
$DBD = new DBD();
$query="SELECT * FROM members";
$stmt = $DBD->prepare($query);
$stmt->execute(); //Executing
[/code]
$DBD is nu op dezelfde manier te gebruiken als Mysqi, maar los van de automatische connectie opbouw, kun je nog een aantal functies zelf toevoegen, waarmee deze extend pas echt nuttig kan worden.
Maak van DBD niet een doorgeefluik naar Mysqli, maar maak het tot een uitbreiding van de Mysqli-class
Code (php)
Je extendt objectgeoriënteerd de klasse MySQLi maar gebruikt vervolgens procedureel mysqli_connect() voor het openen van de verbinding.
MySQLi opent de verbinding bovendien al in de constructor, dus het heeft helemaal geen zin om dat nog een keer te doen met een aparte methode conn().
Wil je dat toch zo doen, dan extendt je MySQLi niet, maar doe je zoiets:
Code (php)
Gewijzigd op 18/05/2017 09:14:44 door Ward van der Put
Het komt door de persoon en een krat bier, warom ik procedureel en object georienteerd had gemixed :)
Ik heb het aangepast en werkt aan :
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
public $connection;
public $lang = '';
public function __construct()
{
parent::__construct(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
$this->query("set names 'utf8'");
$this->query("SET CHARACTER SET 'utf8'");
}
public $lang = '';
public function __construct()
{
parent::__construct(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
$this->query("set names 'utf8'");
$this->query("SET CHARACTER SET 'utf8'");
}
Toevoeging op 18/05/2017 10:16:20:
Bedankt.
Het komt door de persoon en een krat bier, warom ik procedureel en object georienteerd had gemixed :)
Ik heb het aangepast en werkt naar:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
public $connection;
public $lang = '';
public function __construct()
{
parent::__construct(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
$this->query("set names 'utf8'");
$this->query("SET CHARACTER SET 'utf8'");
}
public $lang = '';
public function __construct()
{
parent::__construct(DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME);
$this->query("set names 'utf8'");
$this->query("SET CHARACTER SET 'utf8'");
}
Als ik de tweede optie gebrui; dus
Code (php)
1
2
3
4
5
6
2
3
4
5
6
protected $Connection;
public function conn()
{
$this->Connection = new \MySQLi();
}
public function conn()
{
$this->Connection = new \MySQLi();
}
zonder de extend, welke is dan sneller? De code van een ander script die ik aanpas is nu namelijk al zo gemaakt.
Mijn vorige reactie is nog steeds van toepassing. Gebruik set_charset() in plaats van bovenstaande constructie.