Classes intro
Voor een introductie in classes / OOP moet ik ervaring opdoen met classes.
Opdracht: classes maken voor ophalen, toevoegen, updaten, verwijderen van gegevens uit de verschillende database tabellen.
mijn idee was:
Eerst een database class maken voor connectie, simpel beginnen.
Dit gedaan en geprint, komt een keurig object uit. daarentegen snap ik nog niet hoe ik dit toepas.
Heb simpelweg de file gerequired en de code aangepast maar krijg nu 3 foutmeldingen:
mysqli_query() expects parameter 1 to be mysqli, object given in C:\wamp64\www\formulier.php on line 120
Undefined variable: sql3 in C:\wamp64\www\formulier.php on line 139
mysqli_error() expects parameter 1 to be mysqli, object given in C:\wamp64\www\formulier.php on line 139
ik heb nog gebrek aan inzicht mbt het toepassen van mijn class, maar dat de $sql3 niet goed zou zijn vind ik erg raar.. wat ben ik vergeten/doe ik fout?
class:
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
class database {
var $db_connection = FALSE;
var $db_host = "localhost";
var $db_username = "root";
var $db_pass = "root";
var $db_name = "opdracht";
function __construct (){
$this->createConnection();
}
function createConnection() {
$this->db_connection = mysqli_connect($this->db_host,$this->db_username,$this->db_pass,$this->db_name);
}
function getConnection() {
return $this->db_connection;
}
}
$connection = new database();
?>
class database {
var $db_connection = FALSE;
var $db_host = "localhost";
var $db_username = "root";
var $db_pass = "root";
var $db_name = "opdracht";
function __construct (){
$this->createConnection();
}
function createConnection() {
$this->db_connection = mysqli_connect($this->db_host,$this->db_username,$this->db_pass,$this->db_name);
}
function getConnection() {
return $this->db_connection;
}
}
$connection = new database();
?>
formulier.php:
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<?php
include_once('header.php');
require ('test2.php');
//todo: include class met databasefuncties
// zodra submit wordt gedrukt, stop input in variabelen voor verificatie en verzending naar database
if(isset($_POST['submit'])){
$voornaam = ($_POST["Voornaam"]);
$achternaam = ($_POST["Achternaam"]);
$straat = ($_POST["Straat"]);
$plaats = ($_POST["Plaats"]);
$email = ($_POST["Email"]);
$telefoon = ($_POST["Telefoon"]);
// todo: bestandsnaam /&bestand
//define test input functie voor validatie, 3 soorten type input verwacht (varchar-tekst, varchar-email, int-telefoon
function test_input($var,$soort){
if ($soort == 'tekst'){
if(preg_match("/^[a-zA-Z -]*$/",$var) == FALSE)
return FALSE;
}elseif ($soort == 'email'){
if(filter_var($var, FILTER_VALIDATE_EMAIL) == FALSE){
return FALSE;
}
}
elseif($soort == 'telefoon'){
if(preg_match('/^[0-9]{10}$/',$var) == FALSE)
return FALSE;
}
else {
return TRUE;
}
}
//?todo: validatie bestandtype, overzichtelijk of toch in aparte upload file?
// create error voor als leeg, validatie ja, validatie nee, voor elke variabele.
// todo: toevoegen errors voor bestandsvariabelen, tododo: vervangen in array voor overzichtelijkheid
$error = FALSE;
if (empty($voornaam)) {
$voornaamerr = "<li>Voornaam is verplicht</li>";
$error = TRUE;
}
elseif (test_input($voornaam, 'tekst') === FALSE) {
$voornaamerr = "<li>Voornaam ongeldig</li>";
$error = TRUE;
}
else {
$voornaamerr = "";
}
if (empty($achternaam)) {
$achternaamerr = "<li>Achternaam is verplicht</li>";
$error = TRUE;
}
elseif (test_input($achternaam, 'tekst') === FALSE) {
$achternaamerr = "<li>Achternaam is ongeldig</li>";
$error = TRUE;
}
else {
$achternaamerr = "";
}
if (empty($straat)) {
$straaterr = "<li>Straat is verplicht</li>";
$error = TRUE;
}
elseif (test_input($straat, 'tekst') === FALSE) {
$straaterr = "<li>Straatnaam is ongeldig</li>";
$error = TRUE;
}
else {
$straaterr = "";
}
if (empty($plaats)) {
$plaatserr = "<li>Plaats is verplicht</li>";
$error = TRUE;
}
elseif (test_input($plaats, 'tekst') === FALSE) {
$plaatserr = "<li>Plaatsnaam is ongeldig</li>";
$error = TRUE;
}
else {
$plaatserr = "";
}
if (empty($email)) {
$emailerr = "<li>Email is verplicht</li>";
$error = TRUE;
}
elseif (test_input($email, 'email') === FALSE) {
$emailerr = "<li>Email is ongeldig</li>";
$error = TRUE;
}
else {
$emailerr = "";
}
if (empty($telefoon)) {
$telefoonerr = "<li>Telefoonnummer is verplicht</li>";
$error = TRUE;
}
elseif (test_input($telefoon, 'telefoon') === FALSE) {
$telefoonerr = "<li>Telefoonnummer is ongeldig</li>";
$error = TRUE;
}
else {
$telefoonerr = "";
}
// wanneer error niet aanwezig, verwerk gegevens in database, wanneer wel, creeer error en geef deze weer via errormelding
if(!$error){
//todo: Doe de post shit naar database via class
// oude/huidige sql: insert query in losse variabelen stoppen, per databasetabel dmv loop
$sql1 = "INSERT INTO persoonsgegevens(voornaam,achternaam) VALUES('$voornaam','$achternaam')";
if (mysqli_query($connection, $sql1)) {
$user_id = mysqli_insert_id($connection);
$sql2 = "INSERT INTO contactgegevens (email,telefoon,user_id) VALUES('$email','$telefoon','$user_id')";
//vraagje: kan de $user_id declaratie beter bij persoonsgegevens query weergeven ofniet?
if (mysqli_query($connection, $sql2)) {
$sql3 = "INSERT INTO adresgegevens (straat,plaats,user_id) VALUES('$straat','$plaats','$user_id')";
if (mysqli_query($connection, $sql3)) {
echo '<p style="width:100%; padding:10px; background-color:#32beeb;color:#000000;text-align:center;">Gelukt!</p>';
header ("Refresh: 3 url=overzicht.php");
} else {
echo "Error: " . $sql1 . "<br>" . mysqli_error($connection);
}
} else {
echo "Error: " . $sql2 . "<br>" . mysqli_error($connection);
}
} else {
echo "Error: " . $sql3 . "<br>" . mysqli_error($connection);
}
}else{
// create 1 errormelding voor implementatie, combineer losse errors van elke variabele string (.=) om zo en kleine, overzichtelijke PHP code in de HTML shell te krijgen
$errormelding = '<ul>';
if(isset($voornaamerr) && !empty($voornaamerr)){
$errormelding .= $voornaamerr;
}
if(isset($achternaamerr) && !empty($achternaamerr)){
$errormelding .= $achternaamerr;
}
if(isset($straaterr) && !empty($straaterr)){
$errormelding .= $straaterr;
}
if(isset($plaatserr) && !empty($plaatserr)){
$errormelding .= $plaatserr;
}
if(isset($emailerr) && !empty($emailerr)){
$errormelding .= $emailerr;
}
if(isset($telefoonerr) && !empty($telefoonerr)){
$errormelding .= $telefoonerr;
}
$errormelding .= '</ul>';
}
}
?>
include_once('header.php');
require ('test2.php');
//todo: include class met databasefuncties
// zodra submit wordt gedrukt, stop input in variabelen voor verificatie en verzending naar database
if(isset($_POST['submit'])){
$voornaam = ($_POST["Voornaam"]);
$achternaam = ($_POST["Achternaam"]);
$straat = ($_POST["Straat"]);
$plaats = ($_POST["Plaats"]);
$email = ($_POST["Email"]);
$telefoon = ($_POST["Telefoon"]);
// todo: bestandsnaam /&bestand
//define test input functie voor validatie, 3 soorten type input verwacht (varchar-tekst, varchar-email, int-telefoon
function test_input($var,$soort){
if ($soort == 'tekst'){
if(preg_match("/^[a-zA-Z -]*$/",$var) == FALSE)
return FALSE;
}elseif ($soort == 'email'){
if(filter_var($var, FILTER_VALIDATE_EMAIL) == FALSE){
return FALSE;
}
}
elseif($soort == 'telefoon'){
if(preg_match('/^[0-9]{10}$/',$var) == FALSE)
return FALSE;
}
else {
return TRUE;
}
}
//?todo: validatie bestandtype, overzichtelijk of toch in aparte upload file?
// create error voor als leeg, validatie ja, validatie nee, voor elke variabele.
// todo: toevoegen errors voor bestandsvariabelen, tododo: vervangen in array voor overzichtelijkheid
$error = FALSE;
if (empty($voornaam)) {
$voornaamerr = "<li>Voornaam is verplicht</li>";
$error = TRUE;
}
elseif (test_input($voornaam, 'tekst') === FALSE) {
$voornaamerr = "<li>Voornaam ongeldig</li>";
$error = TRUE;
}
else {
$voornaamerr = "";
}
if (empty($achternaam)) {
$achternaamerr = "<li>Achternaam is verplicht</li>";
$error = TRUE;
}
elseif (test_input($achternaam, 'tekst') === FALSE) {
$achternaamerr = "<li>Achternaam is ongeldig</li>";
$error = TRUE;
}
else {
$achternaamerr = "";
}
if (empty($straat)) {
$straaterr = "<li>Straat is verplicht</li>";
$error = TRUE;
}
elseif (test_input($straat, 'tekst') === FALSE) {
$straaterr = "<li>Straatnaam is ongeldig</li>";
$error = TRUE;
}
else {
$straaterr = "";
}
if (empty($plaats)) {
$plaatserr = "<li>Plaats is verplicht</li>";
$error = TRUE;
}
elseif (test_input($plaats, 'tekst') === FALSE) {
$plaatserr = "<li>Plaatsnaam is ongeldig</li>";
$error = TRUE;
}
else {
$plaatserr = "";
}
if (empty($email)) {
$emailerr = "<li>Email is verplicht</li>";
$error = TRUE;
}
elseif (test_input($email, 'email') === FALSE) {
$emailerr = "<li>Email is ongeldig</li>";
$error = TRUE;
}
else {
$emailerr = "";
}
if (empty($telefoon)) {
$telefoonerr = "<li>Telefoonnummer is verplicht</li>";
$error = TRUE;
}
elseif (test_input($telefoon, 'telefoon') === FALSE) {
$telefoonerr = "<li>Telefoonnummer is ongeldig</li>";
$error = TRUE;
}
else {
$telefoonerr = "";
}
// wanneer error niet aanwezig, verwerk gegevens in database, wanneer wel, creeer error en geef deze weer via errormelding
if(!$error){
//todo: Doe de post shit naar database via class
// oude/huidige sql: insert query in losse variabelen stoppen, per databasetabel dmv loop
$sql1 = "INSERT INTO persoonsgegevens(voornaam,achternaam) VALUES('$voornaam','$achternaam')";
if (mysqli_query($connection, $sql1)) {
$user_id = mysqli_insert_id($connection);
$sql2 = "INSERT INTO contactgegevens (email,telefoon,user_id) VALUES('$email','$telefoon','$user_id')";
//vraagje: kan de $user_id declaratie beter bij persoonsgegevens query weergeven ofniet?
if (mysqli_query($connection, $sql2)) {
$sql3 = "INSERT INTO adresgegevens (straat,plaats,user_id) VALUES('$straat','$plaats','$user_id')";
if (mysqli_query($connection, $sql3)) {
echo '<p style="width:100%; padding:10px; background-color:#32beeb;color:#000000;text-align:center;">Gelukt!</p>';
header ("Refresh: 3 url=overzicht.php");
} else {
echo "Error: " . $sql1 . "<br>" . mysqli_error($connection);
}
} else {
echo "Error: " . $sql2 . "<br>" . mysqli_error($connection);
}
} else {
echo "Error: " . $sql3 . "<br>" . mysqli_error($connection);
}
}else{
// create 1 errormelding voor implementatie, combineer losse errors van elke variabele string (.=) om zo en kleine, overzichtelijke PHP code in de HTML shell te krijgen
$errormelding = '<ul>';
if(isset($voornaamerr) && !empty($voornaamerr)){
$errormelding .= $voornaamerr;
}
if(isset($achternaamerr) && !empty($achternaamerr)){
$errormelding .= $achternaamerr;
}
if(isset($straaterr) && !empty($straaterr)){
$errormelding .= $straaterr;
}
if(isset($plaatserr) && !empty($plaatserr)){
$errormelding .= $plaatserr;
}
if(isset($emailerr) && !empty($emailerr)){
$errormelding .= $emailerr;
}
if(isset($telefoonerr) && !empty($telefoonerr)){
$errormelding .= $telefoonerr;
}
$errormelding .= '</ul>';
}
}
?>
Wat je normaal echter met zo'n 'wrapper' class probeert te doen is zoveel mogelijk recht-toe-recht-aan ellende uit je code te krijgen. Je zou dus een functie $connection->query() kunnen maken:
scheelt je steeds wat typewerk.
Of bijvoorbeeld nog abstracter: $connection->insert('tabel',['veld1' => 'waarde1', ...]);
O: 'var' is niet meer van deze tijd. Gebruik public of private of protected.
O2: zoek eens op SQL-injectie, of vul anders een keer 's Hertogenbosch als plaatsnaam in.
O3: als je deze class vaker wilt gaan gebruiken moet je de connection details (user, pass, enz) niet in de class zelf opslaan maar juist als params meegeven in de __construct. Kun je elke keer wat anders meegeven.
Toevoeging op 22/09/2017 07:22:26:
O4: je 'else error' constructie staan in omgekeerde volgorde van de aanroep. Op regel 132 moet je dus de foutmelding geven van $sql3, enz. Nu gaat het meteen al fout op regel 119 met $sql1, en dan kom je dus in de error melding op regel 138 uit. Daar tover je dan ineens $sql3 uit de hoge hoed. Die had je nog niet aangemaakt (want zover kwam je code niet), en dus krijg je een PHP foutmelding.
Rob Doemaarwat op 22/09/2017 07:12:55:
Ben hiermee aan de slag geweest. Wat ik nog niet snap is het verplaatsen van mijn querycode naar een nieuwe class. ik ben begonnen met een class voor mijn eerste tabel: persoonsgegevens. Deze had ik alsvolgt uitgedacht:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
class persoonsgegevens extends database {
public $sql = "INSERT INTO persoonsgegevens(voornaam,achternaam) VALUES('$voornaam','$achternaam')";
public $firstName = ($_POST["Voornaam"]);
public $lastName = ($_POST["Achternaam"]);
public $userID = mysqli_insert_id($connection->db_connection);
function query($sql){
return mysqli_query ($this->db_connection,$sql);
}
?>
class persoonsgegevens extends database {
public $sql = "INSERT INTO persoonsgegevens(voornaam,achternaam) VALUES('$voornaam','$achternaam')";
public $firstName = ($_POST["Voornaam"]);
public $lastName = ($_POST["Achternaam"]);
public $userID = mysqli_insert_id($connection->db_connection);
function query($sql){
return mysqli_query ($this->db_connection,$sql);
}
?>
De bedoeling is dat de input van de gebruiker via de class bij de juiste kolommen en tabellen uitkomt, beginnend dus met de tabel persoonsgegevens. en dan moet dit uiteindelijk voor zowel een INSERT, UPDATE, SELECT als DELETE..
Gewijzigd op 22/09/2017 14:51:18 door Dennis Achternaam
Persoonsgegevens zijn immers geen database.
Mijn advies zou zijn deze class uit te breiden. Je kunt dan direct je vertrouwde mysqli methods gebruiken maar je kunt de class uitbreiden met custom methods mocht je daar ineens behoefte aan hebben. Leer je zelf overigens aan om classnames te beginnen met een hoofdletter.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class Database extends mysqli // <== You see?
{
public function __construct($host, $username, $passwd, $dbname) {
parent::__construct($host, $username, $passwd, $dbname);
}
/*
* custom methods
*/
}
$db = new Database('localhost', 'user', 'pass', 'database');
$result = $db->query('SELECT * FROM table');
// etc
?>
class Database extends mysqli // <== You see?
{
public function __construct($host, $username, $passwd, $dbname) {
parent::__construct($host, $username, $passwd, $dbname);
}
/*
* custom methods
*/
}
$db = new Database('localhost', 'user', 'pass', 'database');
$result = $db->query('SELECT * FROM table');
// etc
?>
Daarnaast kun je de database class ook in andere classes gebruiken
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
27
28
29
30
31
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
27
28
29
30
31
<?php
class UserMapper
{
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function getAllUsers() {
$result = $this->db->query("SELECT * FROM users");
if(!$result)
return NULL;
return $result->fetch_all(MYSQLI_ASSOC);
}
}
$db = new Database('localhost', 'user', 'pass', 'database');
$userMapper = new UserMapper($db);
$users = $userMapper->getAllUsers();
if($users) {
foreach($users as $user) {
// ...
}
}
?>
class UserMapper
{
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function getAllUsers() {
$result = $this->db->query("SELECT * FROM users");
if(!$result)
return NULL;
return $result->fetch_all(MYSQLI_ASSOC);
}
}
$db = new Database('localhost', 'user', 'pass', 'database');
$userMapper = new UserMapper($db);
$users = $userMapper->getAllUsers();
if($users) {
foreach($users as $user) {
// ...
}
}
?>
Gewijzigd op 22/09/2017 15:31:17 door Frank Nietbelangrijk
Wat je eigenlijk nodig hebt, is een klasse met persoonsgegevens (of een persoon) enerzijds en een tweede klasse die de persoonsgegevens opslaat. Ik gebruik daarvoor meestal een data mapper of een data access object.