Foreach loop verliest waarde vanaf 2e run !?
Ik krijg via een formulier met selectie vakjes een Array binnen met waardes. Vervolgens ga ik binnen een Foreach loop, gegevens uit 2 databases halen, en met die gegevens een mail genereren en versturen.
Ik krijg netjes de gegevens van de Array binnen. Zodra ik de Foreach loop start, stuurt hij alleen bij de eerste $value een mail. Zodra de volgende 'ronde' gelopen moet worden, dan kan hij de $value niet gebruiken bij de query op mijn databases, terwijl de $value wel gevuld is met een waarde die hij kan gebruiken om de gegevens op te halen uit de database.
Kan iemand mij uitleggen waarom dit gebeurt ?
Hieronder de code :
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
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
<?php
// Submit button clicked check, if so send e-mail
if(isset($_POST['submit'])) {
// Check if some actions are selected
if (isset($_REQUEST["list"])) {
$selected = $_REQUEST["list"];
foreach($selected as $value) {
require_once("../includes/connection.php");
// Get CRF info
$crf_result = mysql_query("SELECT * FROM crf WHERE link_pfc_id = '$value'",$connection);
$crf_info=mysql_fetch_object($crf_result);
$crf_id = $crf_info->crf_id;
// Who is the Manager
$pfc_result = mysql_query("SELECT * FROM pfc WHERE pfc_id = '$value'",$connection);
$manager_info=mysql_fetch_object($pfc_result);
$manager = $manager_info->pfc_first_analyst;
// connect to database
require_once("../includes/connection_intra.php");
$result_manager = mysql_query("SELECT * FROM directory WHERE username = '$manager'",$connection_intra);
$manager_info=mysql_fetch_object($result_manager);
$email = $manager_info->email;
// Generating and sending email
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: PFC / CRF administratie <[email protected]>' . "\r\n";
$to = $email;
$subject = "Er staat nog een actie te wachten !";
$body = "Geachte ".$manager.",<BR><BR>Er staat nog een actie te wachten voor PFC ".$value." / CRF ".$crf_id." ,welke door u afgehandeld dient te worden.<BR>Wilt u zo vriendelijk zijn om deze z.s.m. af te handelen ?<BR><BR>Vriendelijk bedankt.";
if (mail($to, $subject, $body, $headers)) {
echo("<p>Email successfully sent!</p>");
} else {
$error= "Can't send the E-mail ! ";
echo "<SCRIPT>location.href='../includes/error.php?error='".$error."'</SCRIPT>";
}
}
}
} else {
// Nothing selected while submit button pressed
}
?>
// Submit button clicked check, if so send e-mail
if(isset($_POST['submit'])) {
// Check if some actions are selected
if (isset($_REQUEST["list"])) {
$selected = $_REQUEST["list"];
foreach($selected as $value) {
require_once("../includes/connection.php");
// Get CRF info
$crf_result = mysql_query("SELECT * FROM crf WHERE link_pfc_id = '$value'",$connection);
$crf_info=mysql_fetch_object($crf_result);
$crf_id = $crf_info->crf_id;
// Who is the Manager
$pfc_result = mysql_query("SELECT * FROM pfc WHERE pfc_id = '$value'",$connection);
$manager_info=mysql_fetch_object($pfc_result);
$manager = $manager_info->pfc_first_analyst;
// connect to database
require_once("../includes/connection_intra.php");
$result_manager = mysql_query("SELECT * FROM directory WHERE username = '$manager'",$connection_intra);
$manager_info=mysql_fetch_object($result_manager);
$email = $manager_info->email;
// Generating and sending email
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: PFC / CRF administratie <[email protected]>' . "\r\n";
$to = $email;
$subject = "Er staat nog een actie te wachten !";
$body = "Geachte ".$manager.",<BR><BR>Er staat nog een actie te wachten voor PFC ".$value." / CRF ".$crf_id." ,welke door u afgehandeld dient te worden.<BR>Wilt u zo vriendelijk zijn om deze z.s.m. af te handelen ?<BR><BR>Vriendelijk bedankt.";
if (mail($to, $subject, $body, $headers)) {
echo("<p>Email successfully sent!</p>");
} else {
$error= "Can't send the E-mail ! ";
echo "<SCRIPT>location.href='../includes/error.php?error='".$error."'</SCRIPT>";
}
}
}
} else {
// Nothing selected while submit button pressed
}
?>
Als ik een vardump doe, zie ik dit waarbij de string overeenkomt met de ID van de geselecteerde vakjes :
array
0 => string '140042' (length=6)
1 => string '140044' (length=6)
Alvast bedankt voor de reactie(s).
- Aar -:
Gelieve in het vervolg bij code de [code][/code]-tags gebruiken.
Hier kan je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Hier kan je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Gewijzigd op 07/11/2014 10:22:59 door - Ariën -
De query's zijn niet beveiligd.
Iemand een idee waarom dit niet werkt ?
Je gebruikt $value in je SQL statements binnen single quotes (') en dat werkt volgens mij niet.
Je zou
kunnen gebruiken, zoals je ook op regel 47 doet.
Ja heb ik gedaan, en die waardes komen ook overeen met de geselecteerde selectie vakjes op de vorige pagina.
Ik heb het inmiddels opgelost.
Ik haal waardes uit 2 verschillende Db's. Tijdens de 2e run in de Foreach loop, probeerde hij te connecten m.b.v. de aanmeld gegevens van de andere Db. Waarom dit gebeurt weet ik niet, want geef duidelijk aan welke connectie vars hij moet gebruiken voor de query.
Ik heb het opgelost door de queries (inclusief de connectie vars) op beide Db's in een apart bestand te zetten en deze te includen op de plek waar nu de queries staan.
Dit werkt blijkbaar wel ...
Dat werkt prima, want de single quotes zijn niet van PHP, maar onderdeel van het SQL-statement. Dit is basiskennis PHP en ik zit me elke keer weer te verbazen dat mensen dat niet weten. Slaat iedereen de eerste drie bladzijden van het boek over of zo?
[terug on topic]
> Ik heb het inmiddels opgelost.
Nee, dat heb je niet. Dat denk je maar. ;-) Zie hieronder.
> Tijdens de 2e run in de Foreach loop, probeerde hij te connecten m.b.v. de aanmeld gegevens van de andere Db.
> Waarom dit gebeurt weet ik niet
Ik ook niet, maar dat zal voor een deel te maken hebben met een onvolledige probleembeschrijving. Zo lees ik: "dan kan hij de $value niet gebruiken bij de query op mijn databases, terwijl de $value wel gevuld is met een waarde die hij kan gebruiken". Bij mij roept dat vragen op:
- Waaruit blijkt dat $value niet gebruikt kan worden? Krijg je een foutmelding? Geeft het script output met onverwachte waardes? Wordt de tweede iteratie van de foreach overgeslagen?
- Hoe weet je dat $value is gevuld met een waarde die hij kan gebruiken? Heb je de waarde van $value geprint? Wat wás de waarde die $value had en welke waarde had hij moeten hebben? Inmiddels heb je in een latere post gezegd dat de waardes kloppen. Maar een van de eerste dingen die je moet leren over foutoplossen is dat je nóóit moet vertrouwen op de ogen van een ander. Ik wil dus niet horen "dat het klopt" maar ik wil zien wat er aan de hand is. (Overigens geldt dat ook buiten PHP; ik heb het wel eens gehad dat een doktersassistente zei dat de laboratoriumresultaten 'in orde' waren (want binnen de normale marge), maar dat bij doorvragen bleek dat de waardes tegen het randje waren en in combinatie met andere symptomen betekenden dat er juist wél een probleem was. Maar dat terzijde.)
Even verderop staat er: "Als ik een vardump doe, zie ik dit". De output die je daar geeft zegt niets zonder context:
- Welke variabele heb je geprint? Dat kan niet $value zijn; ik vermoed $selected, maar dat blijkt verder nergens uit.
- Wáár heb je die vardump gedaan? In principe zou een vardump op regel 7, 9 en 11 drie verschillende resultaten kunnen opleveren.
Verder, zoals SanThe al zei: haal die requires uit je foreach-loop. Hij vindt het onlogisch, ik vind het zelfs ronduit fout. Sowieso vind ik die _once-functies al niet iets om al te frivool te gebruiken, aangezien je daarmee flow-problemen in je code kan maskeren, maar in dit geval horen ze gewoon ergens bovenin je code. Zeker met foutzoeken. Je geeft namelijk niet de code die in de ge-include bestanden staat. Het zou dus zomaar kunnen dat in een van die connection*.php-bestanden de waarde van $select of $value wordt veranderd. Of misschien zelfs wel $connection. Dit soort side-effects kun je eenvoudig uitsluiten door al je requires en includes meteen aan het begin van je code te zetten.
Je denk nu dat je het opgelost door de queries in een ander bestand te zetten en dat te includen. Ik vind dat geen oplossing als je geen idee hebt waarom het nu wel werkt. Ik vind het zelfs eng, want blijkbaar is je code dan niet voorspelbaar.
Nog meer tips/ideeën:
- Leer jezelf het gebruik van "select *" af, zeker als je maar 1 veld wilt ophalen. Benoem gewoon expliciet elk veld dat je ophaalt. Dat geeft duidelijkheid in je code waar je later veel plezier van hebt. Bovendien is het beter voor de performance van je queries.
- Gebruik de mysqli-functies in plaats van de mysql-functies. De oude mysql-functies worden niet meer doorontwikkeld, op termijn zullen ze niet meer beschikbaar zijn in PHP en je mist vooral een heleboel functionaliteit die wel in mysqli zit.
- Bouw foutafhandeling in bij je queries. Ik neem aan dat ik niet hoef uit te leggen waarom. ;-)
- Gebruik nooit gebruikers-input (in dit geval $_REQUEST) rechtstreeks in je query. Als je een hobbyist tegenkomt die de post-data verandert, kunnen er ineens erg gekke dingen in je database gebeuren. Als je overstapt op de mysqli-functies, kun je dat ook oplossen door prepared statements te gebruiken.
- Ik vind je dapper dat je een blijkbaar numerieke waarde als string behandelt in een loosely typed taal als PHP. Op het moment dat je een value krijgt als '001234' zou het namelijk zomaar kunnen dat die waarde in je query ineens '1234' is geworden omdat PHP denkt/vindt dat het een integer is. En dat gaat niet matchen met een database-key '001234'. Zijn leuke dingen waar je úúúren naar kunt zoeken.
- Je gebruikt nu 2 select-statements voor iets wat je ook in 1 statement af kunt handelen. Vooral aangezien je dat in een foreach-loop doet, kan dat best veel performance schelen. Je kunt die regels eenvoudig samennemen:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$value = is_numeric($value) ? $value : '000000'; # Beveiliging tegen ongeldige invoer
$sql = "SELECT crf.crf_id, pfc.pfc_first_analyst
FROM crf, pfc
WHERE crf.link_pfc_id = '$value'
AND crf.link_pfc_id = pfc.pfc_id";
$result = mysql_query($sql, $connection) or trigger_error(mysql_error());
$row = mysql_fetch_object($result);
$crf_id = $row->crf_id;
$manager = $row->pfc_first_analyst;
?>
$value = is_numeric($value) ? $value : '000000'; # Beveiliging tegen ongeldige invoer
$sql = "SELECT crf.crf_id, pfc.pfc_first_analyst
FROM crf, pfc
WHERE crf.link_pfc_id = '$value'
AND crf.link_pfc_id = pfc.pfc_id";
$result = mysql_query($sql, $connection) or trigger_error(mysql_error());
$row = mysql_fetch_object($result);
$crf_id = $row->crf_id;
$manager = $row->pfc_first_analyst;
?>
Ik heb in dit geval de query in een aparte string gezet. Dat is op zich niet verplicht, maar ik vind het de leesbaarheid ten goede komen als er niet een hele lap tekst als parameter aan mysql_query wordt meegegeven.
Pff... wat je al niet kan zeggen over 15 regels code. ;-)
Gewijzigd op 11/11/2014 00:56:16 door Willem vp
Dank je Willem vp, ik weet weer waar ik sta ;-)
Als je het dan helemaal goed wilt doen moet ook geen 20e eeuw SQL syntax gebruiken:
is niet volgens de huidige SQL standaard
wel, en dat is ook veel overzichterlijker
Weer een boel geleerd ...
Niks ten nadele van dit forum ( of welk forum dan ook ), maar het blijft lastig om precies aan te geven wat je precies wilt bereiken met je code, en wat het probleem is waar je tegenaan loopt. Je probeert het zo duidelijk mogelijk te vertellen en m.b.v. de code duidelijk te maken.
Daarnaast is het natuurlijk lastig voor de mensen die het forum lezen in te schatten wat het niveau van iemand is die een bericht geplaatst heeft, en mogelijk daardoor niet meteen aangenomen wordt wat hij/zij aangeeft.
In dit voorbeeld de inhoud van $value. Ik geef aan dat de waardes kloppen, terwijl jij dit meteen in twijfel trekt en ervan uitgaat dat ik dit niet gecontroleerd heb. Dit bedoel ik niet negatief naar jou, maar in het algemeen --:}
Uiteindelijk is het volgens mij de bedoeling dat men elkaar helpt en dat iedereen hiervan kan leren. En nee, ik ben zeker geen 'die hard' PHP-er, en leer nog elke dag bij en probeer met de kennis die ik heb, dingen te maken.
Bijdrages zoals jij die geeft zijn voor mij ( en hopelijk ) voor meer mensen een stimulans om elke keer weer de lat een stukje hoger te leggen, en verder te kijken dan je neus lang is.
Erwin van Brink op 11/11/2014 19:52:13:
Niks ten nadele van dit forum ( of welk forum dan ook ), maar het blijft lastig om precies aan te geven wat je precies wilt bereiken met je code, en wat het probleem is waar je tegenaan loopt. Je probeert het zo duidelijk mogelijk te vertellen en m.b.v. de code duidelijk te maken.
Goed formuleren van een probleem is een kunst/techniek op zich. Maar als je programmeert wel een heel belangrijke. Dat zag je hier al: jij denkt/hoopt dat je iets duidelijk formuleert en bij mij roept het meteen vier nieuwe vragen op. ;-)
Quote:
Daarnaast is het natuurlijk lastig voor de mensen die het forum lezen in te schatten wat het niveau van iemand is die een bericht geplaatst heeft, en mogelijk daardoor niet meteen aangenomen wordt wat hij/zij aangeeft.
In dit voorbeeld de inhoud van $value. Ik geef aan dat de waardes kloppen, terwijl jij dit meteen in twijfel trekt en ervan uitgaat dat ik dit niet gecontroleerd heb.
In dit voorbeeld de inhoud van $value. Ik geef aan dat de waardes kloppen, terwijl jij dit meteen in twijfel trekt en ervan uitgaat dat ik dit niet gecontroleerd heb.
Ik kan je gerust stellen: dat heeft niets te maken met je niveau. Als mijn collega zo'n opmerking maakt ('de waarde is goed') moet hij snel bukken, anders heeft 'ie een klap voor zijn hoofd te pakken. Goed en fout zijn namelijk geen universele begrippen, maar altijd afhankelijk van een context. Daarom wil ik altijd exacte waardes hebben, zodat ik zelf kan bepalen of een waarde -met mijn kennis van de situatie- correct is. Dat heeft overigens niets te maken met 'in twijfel trekken'. Zoals ik in het (overigens waar gebeurde) voorbeeld van de doktersassistente al aangaf: een waarde kan objectief goed zijn, maar in een groter geheel gezien toch fout. Dat is alleen te beoordelen door naar exacte waardes te kijken.
Quote:
En nee, ik ben zeker geen 'die hard' PHP-er
De grap is: ik ook niet. ;-) Ik programmeer nauwelijks in PHP (maar dat dan wel al meer dan 10 jaar). Eigenlijk zit ik hier vooral voor de gezelligheid.
@Ger:
Je hebt gelijk dat het oude syntax is. Die zit er bij mij echter dusdanig ingebakken (ik stam nog uit het tijdperk SQL-86 op Ingres v4) dat ik het niet noodzakelijkerwijs slechter leesbaar vind dan de nieuwe syntax, zeker bij eenvoudige queries.
En aangezien de oude syntax niet deprecated is, en het er ook niet naar uitziet dat hij binnen 15 jaar deprecated zal worden verklaard, vind ik er zelfs nog wat voor te zeggen om zo hier en daar de oude syntax te blijven gebruiken, zodat de jongere generatie niet meteen heel erg eiïg staat te kijken als ze een keer een old-fashioned query tegenkomen. ;-)