MySQL/PHP eendelig formulier

Moderators: jkien, Xilvo

Berichten: 41

MySQL/PHP eendelig formulier

Goedemiddag,

Ik zit al een week achter dit stukje code. Het lukt me maar niet om het goed werkende te krijgen.
Ik probeer een simpel eendelig formulier te maken dat bij het verzenden van de informatie, de informatie gelijk invoert in mijn database. In de huidige staat van de code krijg ik de foutmelding:
Notice: Undefined variable: message in D:\PHP MYSQL\Xampp\htdocs\Projects\MysqliFormFunction.php on line 78
Wanneer ik de laatste if statement buiten het geheel laat vallen, wordt de variabele $message wel gevonden en getoond op het scherm alleen wordt de input dan niet verwerkt wanneer ik het wil verzenden.

Graag hulp want ik weet oprecht niet waar ik hier de fout in ben gegaan.

Code: Selecteer alles

<?php
if (isset($_POST['submit']) && $_POST['submit'] == 'Submit') 
	{

	if (!isset($_POST['email']) || $_POST['email'] == "" || strlen($_POST['email'] > 30)) {
	$message = '<P>There is a problem. Did you enter an email address?</P>';
}

	
else {
	//Open connection to database
	include 'Login.php';
	$conn = mysqli_connect($servername, $username, $password);
	if (!$conn) {
		die("Connection failed: " . mysqli_connect_error());
	}
	$database = mysqli_select_db($conn, "Email");
	if (!$database) {
		die("Connection to database failed: " . mysqli_connect_error());
	}
	//Insert email address
	$as_email = mysqli_real_escape_string($conn, $_POST['email']);
	$tr_email = trim($as_email);
	$query = "INSERT INTO address (MailID, email)
				VALUES('NULL', ('$tr_email'),
				'www.example.com/newsletter_signup.html')
				";
	$result = mysqli_query($conn, $query);
	if (mysqli_affected_rows($conn) == 1) {
		$message = '<P>Your information has been recorded.</P>';
	$noform_var = 1;
	}
		else {
			error_log(mysqli_error());
			$message = '<P>Something went wrong with your signup attempt. </P>';
		}


}
//Show the form in every case except successful submission
if(!isset($noform_var))
	{

	$thisfile = "MysqliFormFunction.php";
	$message  = '<P>Enter your email address and we will send you our weekly newsletter.</P>
	<FORM METHOD="POST" ACTION="'.$thisfile.'">
	<LABEL for="email"></LABEL>
	<INPUT TYPE="text" SIZE=25 NAME="email"><BR>
	<BR>
	<INPUT TYPE="submit" NAME="submit" value="submit">
	</FORM>
	';
	}
}


?>
<!DOCTYPE HTML>
<HTML>
<HEAD>
<META CHARSET="utf-8">

<STYLE TYPE ="text/css">

BODY, P {color: black; font-family: verdana;
fontsize: 10 pt}
H1 {color: black; font-family: arial; font-size: 12 pt}

</STYLE>
</HEAD>
<BODY>
<TABLE BORDER=0 CELLPADDING=10 WIDTH=100%>
<TR>
<TD BGCOLOR="#F0F8FF" ALIGN=CENTER VALIGN=TOP WIDTH=17%>
</TD>
<TD BGCOLOR="#FFFFFF" ALIGN=CENTER VALIGN=TOP WIDTH=80%>
<H1>Student sign-up form</H1>
<?php echo $message; ?>

</TD>
</TR>
</TABLE>
</BODY>
</HTML>

Berichten: 12.263

Re: MySQL/PHP eendelig formulier

Ik weet niet wat regel 78 is, maar notices kun je in de regel negeren. Eventueel error reporting anders instellen zodat notices niet in de pagina weergegeven worden.

Berichten: 41

Re: MySQL/PHP eendelig formulier

Regel 78 is de regel waar ik de $message echo op het einde, dit zou in eerste instantie het formulier moeten laten zien en na het verzenden zou er niks weergegeven moeten worden tenzij het mailadres te lang is.

Bedankt voor de tip trouwens, helaas heb ik nu echt die $message nodig om mijn pagina goed weer te geven.

Gebruikersavatar
Technicus
Berichten: 17.383

Re: MySQL/PHP eendelig formulier

Notices negeren is geen goede gewoonte, want ze zijn er niet voor niets.

Beter kun je beginnen door te zorgen dat je altijd een message hebt, bijvoorbeeld door bovenaan het script te definiëren als een lege string:

Code: Selecteer alles

$message='';
"Knowledge speaks, but wisdom listens."
- Jimi Hendrix -

Berichten: 12.263

Re: MySQL/PHP eendelig formulier

Dat werkt juist averechts: De notice geeft je een indicatie dat je iets vergeten bent, of wellicht de naam van de variabele verkeerd gespeld hebt oid waardoor deze undefined is op een moment dat deze wel defined moet zijn.

Er is geen reden om in php variabelen te initialiseren: het is geen strong typecased taal, en sinds pakweg php 4 worden variabelen ook niet meer uit de global scope gevuld.

Bovendien kan het problemen geven als je niet weet wat je precies wilt:

$message='';

geeft $message een (zwakke) typecast naar het string type. Dat geeft weer te denken wat er moet gebeuren als je dit doet:

$message='';
$message++;
echo $message;

ik vermoed dat het resultaat '1' zal zijn, maar als je dat bedoelde zou je beter $message=0; kunnen gebruiken als je het per se moest initialiseren.

Voor int's, strings, floats en dergelijke werkt dat allemaal probleemloos. Het enige dat -wel- handig is om specifiek te initialiseren zijn arrays... en objecten als je voor oop gaat (doe het niet ;) )

Berichten: 41

Re: MySQL/PHP eendelig formulier

Wanneer ik $message bij voorbaat initialiseer als string maakt dit geen verschil voor het uiteindelijke resultaat.

$message komt meerdere keren voor met verschillende strings/forms en ergens in de lus lijkt het dat $message niet goed geïnitialiseerd wordt.

Het lijkt wel alsof $message een NULL waarde bevat de eerste keer dat ik hem aanroep hier:

Code: Selecteer alles

//Show the form in every case except successful submission
if(!isset($noform_var))
	{

	$thisfile = "MysqliFormFunction.php";
	$message  = '<P>Enter your email address and we will send you our weekly newsletter.</P>
	<FORM METHOD="POST" ACTION="'.$thisfile.'">
	<LABEL for="email"></LABEL>
	<INPUT TYPE="text" SIZE=25 NAME="email"><BR>
	<BR>
	<INPUT TYPE="submit" NAME="submit" value="submit">
	</FORM>
	';
	}
Hier zou natuurlijk eigenlijk een formulier getoond moeten worden die ingevuld kan worden en waaruit de informatie via het script direct wordt ingevoerd in de database.

Berichten: 12.263

Re: MySQL/PHP eendelig formulier

Voordat je er iets aan toewijst zal het een NULL zijn, of gewoon een niet gedeclareerde variabele waarvan de waarde als NULL gezien wordt bij gebrek aan iets anders... maar de declaratie hierboven ziet er goed uit, dus ik zou niet weten waarom bovenstaand stukje code een notice zou moeten opleveren.

Gebruikersavatar
Technicus
Berichten: 17.383

Re: MySQL/PHP eendelig formulier

Benm schreef:
za 14 dec 2019, 02:05
Dat werkt juist averechts: De notice geeft je een indicatie dat je iets vergeten bent, of wellicht de naam van de variabele verkeerd gespeld hebt oid waardoor deze undefined is op een moment dat deze wel defined moet zijn.
En daarom moet je notices juist aan laten staan zodat je erop gewezen wordt dat je iets verkeerd hebt gedaan.

Verder wil je niet dat je applicatie allemaal zut in de logs aan het schrijven is, dat vertraagd en vertroebelt je zicht op de echte problemen.
Er is geen reden om in php variabelen te initialiseren: het is geen strong typecased taal, en sinds pakweg php 4 worden variabelen ook niet meer uit de global scope gevuld.

Bovendien kan het problemen geven als je niet weet wat je precies wilt:

$message='';

geeft $message een (zwakke) typecast naar het string type. Dat geeft weer te denken wat er moet gebeuren als je dit doet:

$message='';
$message++;
echo $message;

ik vermoed dat het resultaat '1' zal zijn, maar als je dat bedoelde zou je beter $message=0; kunnen gebruiken als je het per se moest initialiseren.
Je weet als het goed is waarvoor je een variabele gaat gebruiken. In dit geval een string die je in ieder geval altijd wil hebben.
Die string wordt ALTIJD aangeroepen in het HTML gedeelte. Als die niet bestaat, dan komt er een terechte notice. Dat zijn nodeloze CPU cycles en levert ook geen schone code en dus geen overzicht.
Natuurlijk is het niet verplicht om de variabele dan te initialiseren, maar dan moet je n.m.m. op de een of andere manier afvangen wat je wil als de variabele die je ALTIJD gebruikt, NIET bestaat.
Voor int's, strings, floats en dergelijke werkt dat allemaal probleemloos. Het enige dat -wel- handig is om specifiek te initialiseren zijn arrays... en objecten als je voor oop gaat (doe het niet ;) )
Om niet te ver off topic te gaan volsta ik even met de melding dat ik dit niet met je eens ben.

@N00b:Je strcuctuur wijkt al af. Dat laatste blok code in je laatste bericht valt binnen deze if:

Code: Selecteer alles

if (isset($_POST['submit']) && $_POST['submit'] == 'Submit') 
En standaard is dat dus niet het geval.

Ik heb je code even in Netbeans geplakt en autoformatting toegepast (zodat de structuur met inspringen, accolades, etc. automatisch goed staat) zodat ik het gemakkelijker zie. Vervolgens heb ik de reikwijdte van bovenstaande regel aangepast en kom ik hierop:

Code: Selecteer alles

<?php
if (isset($_POST['submit']) && $_POST['submit'] == 'Submit') {

    if (!isset($_POST['email']) || $_POST['email'] == "" || strlen($_POST['email'] > 30)) {
        $message = '<P>There is a problem. Did you enter an email address?</P>';
    } else {
        //Open connection to database
        include 'Login.php';
        $conn = mysqli_connect($servername, $username, $password);
        if (!$conn) {
            die("Connection failed: " . mysqli_connect_error());
        }
        $database = mysqli_select_db($conn, "Email");
        if (!$database) {
            die("Connection to database failed: " . mysqli_connect_error());
        }
        //Insert email address
        $as_email = mysqli_real_escape_string($conn, $_POST['email']);
        $tr_email = trim($as_email);
        $query = "INSERT INTO address (MailID, email)
				VALUES('NULL', ('$tr_email'),
				'www.example.com/newsletter_signup.html')
				";
        $result = mysqli_query($conn, $query);
        if (mysqli_affected_rows($conn) == 1) {
            $message = '<P>Your information has been recorded.</P>';
            $noform_var = 1;
        } else {
            error_log(mysqli_error());
            $message = '<P>Something went wrong with your signup attempt. </P>';
        }
    }
}
//Show the form in every case except successful submission
if (!isset($noform_var)) {

    $thisfile = "MysqliFormFunction.php";
    $message = '<P>Enter your email address and we will send you our weekly newsletter.</P>
	<FORM METHOD="POST" ACTION="' . $thisfile . '">
	<LABEL for="email"></LABEL>
	<INPUT TYPE="text" SIZE=25 NAME="email"><BR>
	<BR>
	<INPUT TYPE="submit" NAME="submit" value="submit">
	</FORM>
	';
}
?>
<!DOCTYPE HTML>
<HTML>
    <HEAD>
        <META CHARSET="utf-8">

        <STYLE TYPE ="text/css">

            BODY, P {color: black; font-family: verdana;
                     fontsize: 10 pt}
            H1 {color: black; font-family: arial; font-size: 12 pt}

        </STYLE>
    </HEAD>
    <BODY>
        <TABLE BORDER=0 CELLPADDING=10 WIDTH=100%>
            <TR>
                <TD BGCOLOR="#F0F8FF" ALIGN=CENTER VALIGN=TOP WIDTH=17%>
                </TD>
                <TD BGCOLOR="#FFFFFF" ALIGN=CENTER VALIGN=TOP WIDTH=80%>
                    <H1>Student sign-up form</H1>
                    <?php echo $message; ?>

                </TD>
            </TR>
        </TABLE>
    </BODY>
</HTML>
Volgens mij doet dit wat je verwacht.

PS: als je dit online gooit raad ik je sterk aan om je in te lezen in SQL injectie. Verplichte "Bobby Tables":
Afbeelding
"Knowledge speaks, but wisdom listens."
- Jimi Hendrix -

Berichten: 12.263

Re: MySQL/PHP eendelig formulier

Wat het laatste betreft: mysqli_real_escape_string() zou daar toch een heel stuk bij moeten werken.

Wel vreemd: waarom voer je MailID in met een NULL waarde? als het een auto-incrementing index is kun je het hele veld weglaten en nummert het zichzelf. Bovendien snap ik niet waarom je 'www.example.com/newsletter_signup.html' in de insert query hebt staan - dat lijkt me nogal onlogisch, en dit gaat zo ook niet werken gezien je nu 2 velden en 3 values probeert te inserten.

Gebruikersavatar
Technicus
Berichten: 17.383

Re: MySQL/PHP eendelig formulier

mysqli_real_escape_string() kent zijn beperkingen (denk alleen al aan charset issues). Aangezien je al weet dat het een valide emailadres moet zijn (anders wil je het niet eens opslaan) kun je eerst filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) toepassen. Vervolgens kun je elke injectie voorkomen door een perpared statement te gebruiken. Injectie is in dat geval (zolang je te template niet door user input laat bepalen) geen issue meer.
"Knowledge speaks, but wisdom listens."
- Jimi Hendrix -

Berichten: 12.263

Re: MySQL/PHP eendelig formulier

Voor een mailadres kan dat natuurlijk, maar als je arbitraire content wilt opslaan is er weinig te filteren (zeker als je ook bijzondere karakters etc wilt gebruiken).

Charset issues: daar kun je zeker last mee krijgen, tenzij je het gewoon consequent instelt (alles utf-8). Doe je dat correct dan is er voor zover ik weet momenteel geen exploit om un-escaped ' in de query te krijgen bij recente php en mysql versies.

De kans op een 'bobby tables' lijkt me niet zo groot. Wellicht is er wel een of ander lek waarmee je met een heel vernuftig request alsnog wat kunt uitvreten, als zou het me verbazen als dat betrouwbaar/voorspelbaar werkt: dat maakt het halve internet kwetsbaar voor injectie aanvallen.

Prepared statements zijn wellicht nog veiliger, maar ook nogal bewerkelijk.

Berichten: 41

Re: MySQL/PHP eendelig formulier

@N00b:Je strcuctuur wijkt al af. Dat laatste blok code in je laatste bericht valt binnen deze if:

Code: Selecteer alles

if (isset($_POST['submit']) && $_POST['submit'] == 'Submit') 
En standaard is dat dus niet het geval.

Ik heb je code even in Netbeans geplakt en autoformatting toegepast (zodat de structuur met inspringen, accolades, etc. automatisch goed staat) zodat ik het gemakkelijker zie. Vervolgens heb ik de reikwijdte van bovenstaande regel aangepast en kom ik hierop:

Code: Selecteer alles

<?php
if (isset($_POST['submit']) && $_POST['submit'] == 'Submit') {

    if (!isset($_POST['email']) || $_POST['email'] == "" || strlen($_POST['email'] > 30)) {
        $message = '<P>There is a problem. Did you enter an email address?</P>';
    } else {
        //Open connection to database
        include 'Login.php';
        $conn = mysqli_connect($servername, $username, $password);
        if (!$conn) {
            die("Connection failed: " . mysqli_connect_error());
        }
        $database = mysqli_select_db($conn, "Email");
        if (!$database) {
            die("Connection to database failed: " . mysqli_connect_error());
        }
        //Insert email address
        $as_email = mysqli_real_escape_string($conn, $_POST['email']);
        $tr_email = trim($as_email);
        $query = "INSERT INTO address (MailID, email)
				VALUES('NULL', ('$tr_email'),
				'www.example.com/newsletter_signup.html')
				";
        $result = mysqli_query($conn, $query);
        if (mysqli_affected_rows($conn) == 1) {
            $message = '<P>Your information has been recorded.</P>';
            $noform_var = 1;
        } else {
            error_log(mysqli_error());
            $message = '<P>Something went wrong with your signup attempt. </P>';
        }
    }
}
//Show the form in every case except successful submission
if (!isset($noform_var)) {

    $thisfile = "MysqliFormFunction.php";
    $message = '<P>Enter your email address and we will send you our weekly newsletter.</P>
	<FORM METHOD="POST" ACTION="' . $thisfile . '">
	<LABEL for="email"></LABEL>
	<INPUT TYPE="text" SIZE=25 NAME="email"><BR>
	<BR>
	<INPUT TYPE="submit" NAME="submit" value="submit">
	</FORM>
	';
}
?>
<!DOCTYPE HTML>
<HTML>
    <HEAD>
        <META CHARSET="utf-8">

        <STYLE TYPE ="text/css">

            BODY, P {color: black; font-family: verdana;
                     fontsize: 10 pt}
            H1 {color: black; font-family: arial; font-size: 12 pt}

        </STYLE>
    </HEAD>
    <BODY>
        <TABLE BORDER=0 CELLPADDING=10 WIDTH=100%>
            <TR>
                <TD BGCOLOR="#F0F8FF" ALIGN=CENTER VALIGN=TOP WIDTH=17%>
                </TD>
                <TD BGCOLOR="#FFFFFF" ALIGN=CENTER VALIGN=TOP WIDTH=80%>
                    <H1>Student sign-up form</H1>
                    <?php echo $message; ?>

                </TD>
            </TR>
        </TABLE>
    </BODY>
</HTML>
Volgens mij doet dit wat je verwacht.

PS: als je dit online gooit raad ik je sterk aan om je in te lezen in SQL injectie. Verplichte "Bobby Tables":
Afbeelding

Dit werkt inderdaad en had ik toevallig ook al geprobeerd dan loop ik tegen het probleem aan dat de variabele niet gevonden kan worden na het inzenden van het formulier terwijl er dan juist een "succes message" moet worden getoond. De database bestaat namelijk echt als een testdatabase zodat ik kan zien of de query goed uitgevoerd is en $message zou daar een extra bevestiging van moeten geven

Het voorbeeld wat ik gebruik vanuit mijn Wiley Bible geeft aan dat het binnen die if moet staat maar het zou natuurlijk ook zo kunnen.

En ik ben toevallig net begonnen met me inlezen in SQL injection en de methodes om dit te omzeilen alleen pas ik dit momenteel nog niet toe(wel doe ik er al wat proefjes mee). Laten we eerst maar even op redelijk niveau komen met het definiëren van variabelen binnen bepaalde lussen hahaha.

Hartstikke bedankt anyways!

Berichten: 12.263

Re: MySQL/PHP eendelig formulier

Kijk wel even wat dingen doen, bijvoorbeeld:

if (isset($_POST['submit']) && $_POST['submit'] == 'Submit')

is dat werkelijk van enig nut boven domweg

if ($_POST['submit'] == 'Submit')

? Misschien levert je het een notice op (undefined index) als er geen post variable is die submit heet, maar functioneel doet het niet zoveel. Equivalente logisch code zou zijn:

if ($_POST['submit'] == 'Submit' && isset($_POST['submit']) )

maar dat zou je wel weer de notice opleveren gezien de linkerkant eerst geevalueerd wordt. Qua logica is het identiek, maar je voorkomt de notice doordat het if statement 'breekt' op de isset() ipv op de vergelijking.

Overigens kan een geldig mailadres best langer zijn dan 30 tekens, dus dat is ook een vreemde check - geldige adressen kunnen 254 tekens of zelfs 320 tekens lang zijn afhankelijk van wie je het vraagt. Langer dan 30 komt in de praktijk nog best wel eens voor.

Gebruikersavatar
Technicus
Berichten: 17.383

Re: MySQL/PHP eendelig formulier

@Benm, het helpt als je code-tags gebruikt, maakt je code een stuk overzichtelijker.

@Noob: Er zitten nog wat foutjes in je code waar ik eerder overheen keek.

Je submit button heeft als value submit. Vervolgens check jij dit:

Code: Selecteer alles

$_POST['submit'] == 'Submit'
Spot de hoofdletter ;)
Hoofdletter en kleine letters zijn 2 verschillende tekens, dus is het niet hetzelfde.

Verder klopt je query niet; Benm wees je hier al op. Je specificeert 2 kolommen (MailID, email) en 3 waarden om in die 2 kolommen te zetten. Dat past niet, dus krijg je een MySQL error.
Die MySQL error log je dan weer niet goed aangezien je daar de parameter $conn aan vergeten bent mee te geven.
"Knowledge speaks, but wisdom listens."
- Jimi Hendrix -

Berichten: 41

Re: MySQL/PHP eendelig formulier

Code: Selecteer alles

if (isset($_POST['submit']) && $_POST['submit'] == 'submit')	{

    if (!isset($_POST['email']) || $_POST['email'] == "" || strlen($_POST['email'] > 30)) {
        $message = '<P>There is a problem. Did you enter an email address?</P>';
    } else {
        //Open connection to database
        include 'Login.php';
        $conn = mysqli_connect($servername, $username, $password);
        if (!$conn) {
            die("Connection failed: " . mysqli_connect_error());
        }
        $database = mysqli_select_db($conn, "Email");
        if (!$database) {
            die("Connection to database failed: " . mysqli_connect_error());
        }
        //Insert email address
        $as_email = mysqli_real_escape_string($conn, $_POST['email']);
        $tr_email = trim($as_email);
        $query = 'INSERT INTO address (email, MailID)
           		VALUES("$tr_email")
				';
        $result = mysqli_query($conn, $query);
        if (mysqli_affected_rows($conn) == 1) {
            $message = '<P>Your information has been recorded.</P>';
            $noform_var = 1;
        } else {
            error_log(mysqli_error($conn));
            $message = '<P>Something went wrong with your signup attempt. </P>';
        }
    }
}
Ik heb de code wat aangepast momenteel naar de bovenstaande tips, dit is de aangepaste syntax.

Ik loop nog wel tegen het probleem aan dat er na het indienen van het formulier geen bevestigende $message komt en de query wordt nog steeds niet daadwerkelijk uitgevoerd in mijn database.

Ik hoop hier zelf met wat debuggen uit te komen, hartstikke bedankt voor de hulp anyways!

Reageer