Meerdere velden invullen met Ajax en PHP

Door Dorgaldir op vrijdag 5 april 2013 13:40 - Reacties (12)
Categorieën: Ajax, IT, Jquery, PHP, Views: 2.251

Met de standaard ajax scriptjes die ik tot hiertoe geschreven heb heb was het doel telkens maar in één html tag iets toe te voegen. Een <div>, een <p>, en dergelijke,...
Nu moest ik vandaag een textarea en een input text veld van inhoud laten veranderen vanuit één ajax call. Het heeft me even geduurd maar ik heb een oplossing gevonden en wilde die graag delen voor het geval andere mensen met dit probleem zitten.

Wat er gebeurd is eigenlijk simpel, zoals bij elke ajax call verzamel je je gegevens en die worden doorgestuurd naar je gekozen script, aldaar verwerk je ze zoals je gewoon bent maar voor het einde moet je je gegevens in een array zetten en de headers verzetten naar json
code:
1
header('Content-type: application/json');

en als je dan encodeerd als json dan kan je de json variabele gewoon gebruiken in je basisscript om de velden apart in te vullen.

Het is wat duidelijker met enkele lapjes code.


PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<select id="sloganchoise" name="sloganchoise" onchange="getslogan()" required>
<?php
  $ar_cat[1] = "cat 1";
  $ar_cat[2] = "cat 2";
  Foreach($ar_cat as $key => $value){
    if($key == $cat){
      echo "<option value=\"$key\" selected>$value</option>";
    }
    else{
      echo "<option value=\"$key\">$value</option>";
     }  
  }
?>
</select>

<textarea id="slogan" name="slogan" required rows="4" cols="45"><?php echo $slogan;?></textarea>

<input type="text" id="sloganurl" name="sloganurl" value="<?php echo $url;?>"/>



en die roept volgend script aan:


JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
function getslogan(){
            var cat = "cat=" + $('#sloganchoise option:selected').val();
            $.ajax({  
                type: "POST",
                url: 'get_slogan.php',  
                dataType: 'json',  
                data: cat,  
                success: function(response){  
                   $('#slogan').val(response['slogan']);
                   $('#sloganurl').val(response['url']);
                }
            });
        }




en als volgt heb je get_slogan.php

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php  
//Get records from DB matching $_POST['cat']; 

//Iterate results: 
$results = array(); 
if($resultset->num_rows > 0) {  
    while($row = $resultset->fetch_assoc()) {  
       array_push($results, $row); 
    }  
}  

// Return JSON result 
header('Content-type: application/json');  
echo json_encode(results);



Mocht mijn uitleg niet duidelijk zijn dan stel je maar vragen in de reacties en zal ik proberen mijn tekst te verduidelijken. ;)

edit:
1: Heb wegens opmerkingen in de reacties de sql-injection beveiliging toegevoegd.

edit:
2: heb code snippet vervangen door de versie van RobIII

Volgende: De gewone groene mens II: Herbruikbare luiers 05-'11 De gewone groene mens II: Herbruikbare luiers

Reacties


Door Tweakers user Creepy, vrijdag 5 april 2013 13:58

Zie ik je nu echt direct $_REQUEST['cat'] 1 op 1 doorzetten in een query?

Ik snap dat je wilt bloggen, maar wil je dan er wel voor zorgen dat je informatie gewoon goed is? Als je dit gaat doen dan heb je een flink beveiligingsprobleem: een SQL injectie. Aangezien je toch al mysqli gebruikt, gebruik dan AUB de geparametriseerde queries (zie bijv http://www.php.net/manual/en/mysqli-stmt.bind-param.php)

Door Tweakers user Dorgaldir, vrijdag 5 april 2013 14:02

Creepy schreef op vrijdag 05 april 2013 @ 13:58:
Zie ik je nu echt direct $_REQUEST['cat'] 1 op 1 doorzetten in een query?

Ik snap dat je wilt bloggen, maar wil je dan er wel voor zorgen dat je informatie gewoon goed is? Als je dit gaat doen dan heb je een flink beveiligingsprobleem: een SQL injectie. Aangezien je toch al mysqli gebruikt, gebruik dan AUB de geparametriseerde queries (zie bijv http://www.php.net/manual/en/mysqli-stmt.bind-param.php)
Of ik heb gewoon mijn script ingekort waardoor enkele nuances verloren gaan, en ik heb idd nog geen sql injectie opgevangen omdat dit een scriptje is dat achter een wachtwoord beveiligde directory zit en maar door 2 hoogstens 3 mensen gebruikt zal worden dus ik daar geen tijd in wou steken op deze moment.
Verder heb je wel gelijk uiteraard.

Door Tweakers user RobIII, vrijdag 5 april 2013 14:10

Galen schreef op vrijdag 05 april 2013 @ 14:02:
dus ik daar geen tijd in wou steken op deze moment.
Ik zou in lijn met The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) eens een keer een "The Absolute Minimum Every Software Developer Absolutely, Positively Must Do When Processing User Input (No Excuses!)"* moeten bloggen om daar voortaan naar toe te kunnen linken :X
Zelfs voor 'brevity' laat je dit gewoonweg niet achterwege; er zijn hordes eppo's die dit soort zaken 1-op-1 copy/pasten naar hun eigen projecten.

Oh, en het is sloganchoice, niet sloganchoise ;) :P

offtopic:
* En dan de serie completeren met, o.a. een "The Absolute Minimum Every Software Developer Absolutely, Positively Must Take Care Of When Processing Passwords (No Excuses!)", "The Absolute List Of Bullshit Excuses Every Software Developer Absolutely, Positively Never Ever Should Use (No Excuses!)" e.v.a.

[Reactie gewijzigd op vrijdag 5 april 2013 14:13]


Door Tweakers user Gtoniser, vrijdag 5 april 2013 14:15

Galen schreef op vrijdag 05 april 2013 @ 14:02:
[...]


Of ik heb gewoon mijn script ingekort waardoor enkele nuances verloren gaan, en ik heb idd nog geen sql injectie opgevangen omdat dit een scriptje is dat achter een wachtwoord beveiligde directory zit en maar door 2 hoogstens 3 mensen gebruikt zal worden dus ik daar geen tijd in wou steken op deze moment.
Verder heb je wel gelijk uiteraard.
No offence, maar dit is dus precies wat er mis is met veel PHP tutorials.
Stel dat een PHP beginner deze tutorial vind en jouw code gaat gebruiken, dan weet hij echt niet dat je ook op SQL injecties moet letten.
Een developer die zulke dingen op z'n duimpje weet heeft deze tutorial waarschijnlijk niet nodig.
De meeste PHP tutorials zijn helaas op deze manier dus al verkeerd, waardoor veel beveiligingsproblemen ontstaan. Het kost weinig moeite om de extra regel beveiliging erbij te zetten en dan leer je ook de beginners het gelijk goed aan.

Door Tweakers user jbdeiman, vrijdag 5 april 2013 14:29

Overigens zou ik nog 1 ding aanraden:
- Gebruikt geen $_REQUEST, maar maak een keuze voor OF post, OF get, (post is vaak handiger en kent minder beperkingen) niet beiden ondersteunen met $_REQUEST.

In je Ajax call geef je keurig aan dat het gepost moet worden, alleen de pagina die je met je AJAX call aanroept zal ook keurig reageren als die wordt aangeroepen met een JSON string in de GET key: cat. Ook dat is onveiliger, omdat je dan de controle voor een deel kwijt bent.

Door Tweakers user RobIII, vrijdag 5 april 2013 14:30

Daarbij: als je dan toch mysqli gebruikt: waarom dan nog rommelen met de mysqli_really_really_yes_i_am_sure_escape_string i.p.v. gewoon Parametrized Queries te gebruiken? (Zie o.a. hier)

[Reactie gewijzigd op vrijdag 5 april 2013 14:32]


Door Tweakers user Dorgaldir, vrijdag 5 april 2013 14:31

Gtoniser schreef op vrijdag 05 april 2013 @ 14:15:
[...]
No offence, maar dit is dus precies wat er mis is met veel PHP tutorials.
Stel dat een PHP beginner deze tutorial vind en jouw code gaat gebruiken, dan weet hij echt niet dat je ook op SQL injecties moet letten.
Een developer die zulke dingen op z'n duimpje weet heeft deze tutorial waarschijnlijk niet nodig.
De meeste PHP tutorials zijn helaas op deze manier dus al verkeerd, waardoor veel beveiligingsproblemen ontstaan. Het kost weinig moeite om de extra regel beveiliging erbij te zetten en dan leer je ook de beginners het gelijk goed aan.
Ik heb het lijntje toegevoegd, hoewel ik van mening ben dat je nooit zomaar code uit een tutorial of voorbeeld mag overnemen en graag mijn tutorials zo beknopt mogelijk heb om enkel de essentie te krijgen.
Maar wegens overweldigend protest...

Door Tweakers user Dorgaldir, vrijdag 5 april 2013 14:33

jbdeiman schreef op vrijdag 05 april 2013 @ 14:29:
Overigens zou ik nog 1 ding aanraden:
- Gebruikt geen $_REQUEST, maar maak een keuze voor OF post, OF get, (post is vaak handiger en kent minder beperkingen) niet beiden ondersteunen met $_REQUEST.

In je Ajax call geef je keurig aan dat het gepost moet worden, alleen de pagina die je met je AJAX call aanroept zal ook keurig reageren als die wordt aangeroepen met een JSON string in de GET key: cat. Ook dat is onveiliger, omdat je dan de controle voor een deel kwijt bent.
a maar dat is een restant van het script te testen met de url, tijdens het testen heb ik enkele keren gewoon de url ingegeven om het resultaat te kunnen bekijken en niet telkens het gehele script uit te moeten voeren om enkel dat deel te testen.

Vergeten te veranderen met andere woorden, geef me een minuutje ;)

Door Tweakers user RobIII, vrijdag 5 april 2013 14:34

Galen schreef op vrijdag 05 april 2013 @ 14:31:
...en graag mijn tutorials zo beknopt mogelijk heb om enkel de essentie te krijgen...
Schrijf dan gewoon pseudo-code voor de niet-ter-zake-doende-delen en niet iets dat kant-en-klaar copy/pasted kan worden:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
// Get records from DB matching $_POST['cat'];

// Iterate results:
$results = array();
if($resultset->num_rows > 0) { 
    while($row = $resultset->fetch_assoc()) { 
       array_push($results, $row);
    } 
} 

// Return JSON result
header('Content-type: application/json'); 
echo json_encode($results);


Dat scheelt al 15 regels t.o.v. jouw code, vereist enig denkwerk van de copy/pastert voordat 't werkt en is ook nog eens een stuk meer gefocust op de essentie van de snippet namelijk een arraytje bouwen a.d.h.v. een resultset en als JSON returnen.

Ik heb in mijn snippet overigens de vrijheid genomen niet een enkel result maar de hele set te returnen; ik zie het nut van de while() loop anders niet zo uit je code :P Dus het was of de while() eruit slopen en uitgaan van 1 record dat returned wordt door de query of de hele set returnen -> wie zegt dat ik altijd alleen 't laatste record wil (wat jouw code effectief doet ;) ).

Ja, op T.net hebben we een kritisch publiekje :P O-)

[Reactie gewijzigd op vrijdag 5 april 2013 14:52]


Door Tweakers user Dorgaldir, vrijdag 5 april 2013 14:45

RobIII schreef op vrijdag 05 april 2013 @ 14:34:
[...]

Schrijf dan gewoon pseudo-code voor de niet-ter-zake-doende-delen en niet iets dat kant-en-klaar copy/pasted kan worden:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
// Get records from DB matching $_POST['cat'];

// Iterate results:
$results = array();
if($resultset->num_rows > 0) { 
    while($row = $resultset->fetch_assoc()) { 
       array_push($results, $row);
    } 
} 

// Return JSON result
header('Content-type: application/json'); 
echo json_encode(results);


Dat scheelt al 15 regels t.o.v. jouw code, vereist enig denkwerk van de copy/pastert voordat 't werkt en is ook nog eens een stuk meer gefocust op de essentie van de snippet namelijk een arraytje bouwen a.d.h.v. een resultset en als JSON returnen.

Ik heb in mijn snippet overigens de vrijheid genomen niet een enkel result maar de hele set te returnen; ik zie het nut van de while() loop anders niet zo uit je code :P Dus het was of de while() eruit slopen en uitgaan van 1 record dat returned wordt door de query of de hele set returnen -> wie zegt dat ik altijd alleen 't laatste record wil (wat jouw code effectief doet ;) ).
Goed plan, heb die even overgenomen
RobIII schreef op vrijdag 05 april 2013 @ 14:34:
Ja, op T.net hebben we een kritisch publiekje :P O-)
Ja, het is weeral even geleden dat ik op tweakers actief was en was vergeten hoe kritisch ;) maar geen probleem, juist is juist en ik verbeter mezelf er ook enkel door

[Reactie gewijzigd op vrijdag 5 april 2013 14:46]


Door Tweakers user YopY, vrijdag 5 april 2013 15:10

Nog een criticus: Je JS kan ook beter, :+. ipv $.ajax kun je $.post gebruiken:


JavaScript:
1
2
3
4
$.ajax('get_slogan.php', { cat : $('#sloganchoise option:selected').val() } , function(response) {
    $('#slogan').val(response['slogan']); 
    $('#sloganurl').val(response['url']);
  });


Door Tweakers user RobIII, vrijdag 5 april 2013 15:58

YopY schreef op vrijdag 05 april 2013 @ 15:10:
Nog een criticus: Je JS kan ook beter, :+. ipv $.ajax kun je $.post gebruiken:


JavaScript:
1
$.ajax(...)

8)7 :+

Reageren is niet meer mogelijk