Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

Softwareontwikkeling FAQ - PHP

Pagina: 1
Acties:
  • 3.386 views sinds 30-01-2008

Onderwerpen


  • NMe
  • Registratie: februari 2004
  • Laatst online: 22-01 23:06

NMe

Quia Ego Sic Dico.

Topicstarter
Mede-auteur:
  • drm
  • Registratie: februari 2001
  • Laatst online: 01-01 20:15

drm

Softwareontwikkeling FAQ: PHP

Met dank aan drm. :)
Inhoudsopgave
« · ^

Links
« · ^

Boeken
  • Beginning PHP4


    Door: John Blank, WROX author team
    ISBN: 1861003730
    Wrox press
  • PHP4 zonder stress


    Door: Jochen Franke

    ISBN: 9051674643

    Easy Computing
  • MySQL/PHP Database Applications


    Door: Brad Bulger, Jay Greenspan

    ISBN: 0764535374

    Academic Service
  • PHP Bible


    Door: Joyce Park, Tim Converse

    ISBN: 0764549553

    John Wiley and Sons Ltd
  • PHP 4 het complete Handboek


    Door: Tim Converse & Jouce Park

    ISBN: 9039516103

    Academic service
« · ^

FAQ
Mijn POST en GET forms werken niet (meer)
Hoogstwaarschijnlijk ben je onlangs gemigreerd van een oude PHP versie naar een nieuwe, of je bent begonnen aan een PHP tutorial die verouderd is.

In de manual van PHP vind je onder het stukje Predefined variables een en ander over de zogenaamde "superglobals", die in versie 4.1.2 hun intrede deden. Daarnaast werd in versie 4.2.0 de configuration directive 'register_globals' standaard op Off gezet. Dit had als gevolg dat variabelen die van buitenaf komen niet meer automagisch globaal aangemaakt werden.

PHP:
1
2
3
<?
echo 'Welkom ' . $user . ' op mijn coole pagina!';
?>


Dit stukje php werkte voorheen altijd gewoon zonder problemen, als je het aanriep met index.php?user=drm. Tegenwoordig zijn de variabelen terug te vinden in hun respectievelijke superglobals.

PHP:
1
2
3
<?
echo 'Welkom ' . $_GET [ 'user' ] . ' op mijn coole pagina!';
?>


Zie verder de manual voor het gebruik van deze superglobals.

Ik kan de fout echt niet vinden!
Heb je error_reporting op E_ALL staan? Nee? Meteen doen! Deze directive / functie op E_ALL zetten zorgt er namelijk voor dat je veel meer bruikbare debug-informatie krijgt. PHP is namelijk van zichzelf heel erg tolerant met bepaalde constructies, terwijl ze eigenlijk niet helemaal netjes zijn of al min of meer verboden zijn maar nog toegelaten worden wegens backward compatibility.

Als je zogenaamde notices ook toelaat in je error_reporting krijg je o.a. informatie over:
  • het gebruik van niet-bestaande variabelen of elementen uit een array.
    Om te controleren of een bepaalde variabele of element bestaat gebruik je de functie isset().
    Vooral zinvol bij tikfouten en controleren op malafide input.
  • het gebruik van ongequote strings als array-indices.
    Ongequote strings worden enkel nog toegelaten bij wijze van backward compatibility. In principe is dit uit de taal geschrapt vanwege mogelijke conflicten met constanten gedefinieerd met define().
De manual zelf omschrijft het als volgt:
Notices are not printed by default, and indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script. For example, trying to access the value of a variable which has not been set, or calling stat() on a file that doesn't exist.
Schrik dus niet als je je error_reporting ook op E_ALL hebt staan.

Hoe zet ik bepaalde configuratie directives aan/uit?
Vaak komt het voor dat je zelf maar een klein stukje webspace hebt, maar niet alle opgelegde configuraties van de serverbeheerder zo wilt zoals hij ze heeft ingesteld.

Zoek in de manual op welke directive je aan wilt passen, en ga na op welke manieren je ze kunt zetten.

Je vindt ook een tabel terug waarin staat wat de PHP_INI_* waarden betekenen:
PHP_INI_x waardeAls deze erbij staat, betekent dat dat je de waarde kunt setten in:
PHP_INI_USERje script dmv. de functie ini_set().
PHP_INI_PERDIRphp.ini, .htaccess of httpd.conf.
PHP_INI_SYSTEMphp.ini of httpd.conf
PHP_INI_ALLal van bovenstaande mogelijkheden

Zie voor meer informatie dit stuk uit de manual.

"... is not a valid MySQL resource index"
Hoogstwaarschijnlijk heb je een fout staan in je MySQL query. Gebruik de functie mysql_error() om erachter te komen wat de fout precies is.

Een goede gewoonte is het om bij MySQL queries altijd even te kijken of er een fout is opgetreden, en zo ja, wat de fout en de query dan was:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?
$query = "
   SELECT
      woei
   FROM
      table
   WHERE
      woei_id={$_REQUEST [ 'id']}
";
mysql_query ( $query );
if ( mysql_errno () > 0 ) {
   trigger_error ( "MySQL Error!!<br><br>" . mysql_error () . "<br>in query:<br>$query" );
}
?>


Zie voor meer informatie over het effectief gebruik van trigger_error() dit stukje.

Meer informatie over MySQL functies vind je hier.

Mijn sessie-variabelen worden niet opgeslagen
Gebruik session_register() en $_SESSION constructies niet door elkaar.

session_register()

PHP:
1
2
3
4
5
6
7
8
9
10
<?
session_start ();
session_register ( 'blaat' );

if ( !session_registered ( 'blaat' ) ) {
   $blaat = "Blaat";
} else {
   echo 'Blaat was reeds gedefinieerd: ' . $blaat;
}
?>


$_SESSION

PHP:
1
2
3
4
5
6
7
8
9
<?
session_start ();

if ( !isset ( $_SESSION [ 'blaat' ] ) ) {
   $_SESSION [ 'blaat' ] = 'Blaat';
} else {
   echo 'Blaat was reeds gedefinieerd: ' . $_SESSION [ 'blaat' ];
}
?>


Gebruik of de één, of de ander.
Als je beide constructies door elkaar gebruikt, werkt het niet. As simple as that. :)

Sterker nog: sinds register_globals default uit staat, is het gebruik van session_register deprecated:
Caution

If you want your script to work regardless of register_globals, you need to instead use the $_SESSION array as $_SESSION entries are automatically registered. If your script uses session_register(), it will not work in environments where the PHP directive register_globals is disabled.
Mijn sessie-variabelen verdwijnen na sluiten van het browservenster
Uit http://www.php.net/manual/en/ref.session.php:
session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser. The value 0 means "until the browser is closed." Defaults to 0.

See also session_get_cookie_params() and session_set_cookie_params().
Uit http://www.php.net/manual...on-set-cookie-params.php:
void session_set_cookie_params ( int lifetime [, string path [, string domain [, bool secure]]])

Set cookie parameters defined in the php.ini file. The effect of this function only lasts for the duration of the script.
Een stukje code bovenaan elk script zou je sessie dus 30 dagen actief moeten houden:

PHP:
1
session_set_cookie_params(30*24*60*60);


Let daarbij er dus op, dat een lifetime van 0 betekent dat het cookie getrashed wordt bij sluiten van het browservenster.

Mijn file-upload form werkt niet
  1. Controleer of je form-tag juist gedefinieerd hebt:
    method moet "post" zijn
    enctype moet "multipart/form-data" zijn
    Als je de enctype niet goed zet, komt de waarde van het <input type="file"> terug in $_POST, anders kun je hem terugvinden in $_FILES.
  2. Controleer de php-configuratie:
    Controleer de directives file_uploads, upload_max_filesize, upload_tmp_dir en post_max_size op hun waarden.
Ik heb een multiple select of meerdere checkboxes, maar krijg maar 1 variabele binnen in PHP?
Je kunt door achter de naam van je input-veld [] te zetten aan PHP vertellen dat je graag wilt dat alle variabelen die met die naam binnen komen als array behandeld moeten worden:

Voorbeeld:

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<form method="get">

   <input type="checkbox" id="my_check_1" name="my_check[]" value="first_check" />
      <label for="my_check_1">First check</label><br />
   <input type="checkbox" id="my_check_2" name="my_check[]" value="second_check" />
      <label for="my_check_2">Second check</label><br />
   <input type="checkbox" id="my_check_3" name="my_check[]" value="third_check" />
      <label for="my_check_3">Third check</label><br />

   <select name="my_select[]" multiple="multiple">

      <option value="first_option">First option</option>
      <option value="second_option">Second option</option>
      <option value="third_option">Third option</option>
   </select>
   <input type="submit" />
</form>


Het gevolg van een dergelijk formulier is dat in dit geval de $_GET array binnen PHP op zijn beurt weer arrays bevat waarin aangegeven staat welke opties 'aangevinkt' zijn:

Uitvoer:

PHP:
1
print_r($_GET);



code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Array
(
    [my_check] => Array
        (
            [0] => first_check
            [1] => second_check
        )
    [my_select] => Array
        (
            [0] => second_option
            [1] => third_option
        )
)


Eveneens kun je de indices van de array op zichzelf ook namen/nummering geven. Als je dat doet kun je eenvoudig de 'value' van checkboxes achterwege laten:

HTML:
1
2
3
4
5
6
<input type="checkbox" id="my_check_1" name="my_check[first]" />
   <label for="my_check_1">First check</label><br />
<input type="checkbox" id="my_check_2" name="my_check[second]" />
   <label for="my_check_2">Second check</label><br />
<input type="checkbox" id="my_check_3" name="my_check[third]" />
   <label for="my_check_3">Third check</label><br />


Uitvoer:

PHP:
1
print_r($_GET);



code:
1
2
3
4
5
6
7
8
Array
(
    [my_check] => Array
        (
            [first] => on
            [second] => on
        )
)


Met een beetje creatief gebruik van in_array () en/of foreach constructies is het op die manier heel eenvoudig te achterhalen welke opties aangevinkt zijn.

Van mijn <input type="image" ... > kan ik de coordinaten niet terugvinden?
Zoals je in de PHP.net FAQ kunt lezen, worden de namen foo.x en foo.y variabelen in PHP omgezet naar resp. foo_x en foo_y.

Bij een javascript-submit of drukken op enter wordt mijn form niet herkend als 'submitted'?
Als je in je form een <input type="submit"> een name en een value geeft, worden deze in Internet Explorer niet meegegeven als form-waarde.

Je kunt dan beter 1 van de 2 volgende constructies gebruiken om te controleren of je form gesubmit is:

In het geval van een POST formulier:

PHP:
1
2
3
4
5
6
7
<?
if ( strcasecmp ( $_SERVER [ 'REQUEST_METHOD' ], 'post' ) == 0 ) {
   // het post-formulier is verstuurd
} else {
   // het is een 'gewone' (GET-)aanroep.
}
?>


In het geval van een GET formulier:
(Uiteraard kun je deze wijze ook toepassen bij een POST. Het is maar net wat jouw voorkeur geniet.)

HTML:
1
2
3
4
5
<form ...>

   <input type="hidden" name="submitted" value="true" />
   ....
</form>



PHP:
1
2
3
4
5
<?
if ( isset ( $_GET [ 'submitted' ] ) && $_GET [ 'submitted' ] == 'true' ) {
   // ...
}
?>



Spaties van een <input ... value=...> worden niet herkend door de browser
Je moet attributen van een html element om deze reden altijd quoten en de waarde ervan escapen. Zie de volgende voorbeelden:

Waarom quoten?

PHP:
1
2
3
4
5
6
7
<?
$my_value = "This is the value of the field";

echo '<input type=text name=text_input value=';
echo $my_value;
echo '>';
?>


Het resultaat is dan:

HTML:
1
<input type=text name=text_input value=This is the value of the field>


De browser zal enkel het stukje This als waarde van het veld interpreteren. De rest zal de browser proberen als attributen te behandelen. Als dat niet lukt wordt de informatie gewoon genegeerd. Als je echter quotes om de waarde heenzet, heb je daar geen last van.

Waarom escapen?

PHP:
1
2
3
4
5
6
7
<?
$my_value = 'This is a value with a "quoted" part';

echo '<input type="text" name="text_input" value="';
echo $my_value;
echo '">';
?>


Het resultaat is dan:

HTML:
1
<input type="text" name="text_input" value="This is a value with a "quoted part">


Je zal begrijpen dat de browser dit niet anders kan interpreteren dan dat het gedeelte This is value with a de waarde van het attribuut value is.

Gebruik dus htmlspecialchars() of htmlentities() om de values te escapen.

'Escapen' van quotes in queries?
Controleer altijd of get_magic_quotes_gpc() en get_magic_quotes_runtime() aan staan. Als 1 van deze twee aan staat, worden variabelen binnen PHP die enkele (') of dubbele (") quotes of backslashes (\) bevatten automagisch escaped. Dat wil zeggen dat een string die in PHP binnen komt via GET, POST of een cookie (gpc) die een ', " of \ bevat automagisch een \ voor die character krijgt. Bekijk het volgende voorbeeld:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<form method="get">

   <input
      name="test"
      type="text"
      value="Test: ', " and \"
   />
   <input type="submit" />
</form>
<pre>
<?
if ( get_magic_quotes_gpc () ) {
   echo 'Magic quoting with get, post or cookie is enabled', "\n";
}

print_r ( $_GET );
?>
</pre>


Uitvoer met get_magic_quotes_gpc aan, na submit:

code:
1
2
3
4
5
Magic quoting with get, post or cookie is enabled
Array
(
    [test] => Test: \', \" and \\
)


Daarbij is het dus overbodig om nog een addslashes of een andere escape-functie los te laten op die variabelen.

Houd zelf de controle op het escapen.

Het is het overwegen waard om zelf de controle te houden op het escapen van variabelen, om te voorkomen dat je bijvoorbeeld in <input ...> velden een ongewenste backslash krijgt.

Mijn voorkeur heeft het dan ook om in de code te checken of er al ge-escaped is, en zo ja: die escape characters weer te verwijderen:

Uiteraard is het ook een optie om je configuratie helemaal naar je hand te zetten, maar je kunt een reden om dat niet globaal te doen en de magic quotes directives kun je niet altijd per script aan of uit zetten, behalve magic_quotes_runtime (zie set_magic_quotes_runtime(). Daarnaast is het het overwegen waard om je scripts zo portable mogelijk te maken (onafhankelijk van configuraties).

PHP:
1
2
3
4
5
6
7
8
9
10
11
<?
set_magic_quotes_runtime ( 0 );

if ( get_magic_quotes_gpc () ) {
   foreach ( $_POST as $key => $value ) {
      $_POST [ $key ] = stripslashes ( $value );
   }
   foreach ( $_GET as $key => $value )
   // etcetera ...
}
?>


Vervolgens kun je met je eigen escape functies de juiste escapes doen:

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
define ( 'QUOTE_SINGLE',      39 );
define ( 'QUOTE_DOUBLE',      34 );
define ( 'QUOTE_BACKTICK',    96 );
function mysql_escape ( $string, $quote_char_code = QUOTE_SINGLE ) {
   $quote_char = chr ( $quote_char_code );

   return
      $quote_char .
         str_replace (
            array ( '\\', $quote_char ),
            array ( '\\\\', '\\' . $quote_char ),
            $string
         )
      $quote_char;
}
// ....
$query = "
   INSERT INTO
      table(fieldname)
   VALUES(
      " . mysql_escape_string (
         'Dit " is \' een string \\ met wat \ bullshit \\\' '
      ) . "
   );
";


Overigens is het ook te overwegen de ANSI-SQL wijze van escapen te hanteren, door een enkele quote te escapen met een extra enkele quote:

PHP:
1
2
3
function ansi_sql_escape ( $string ) {
   return str_replace ( "'", "''", $string );
}


De testcase voor werking van je escapes:

Om goed te testen of je escaping wel goed werkt, probeer het volgende in te voeren in je database door middel van een formuliertje:

code:
1
' \' '' \\' \\\' " \" "" \\" \\\" ` \` `` \\` \\\`


Wanneer je bij inserten van deze string geen foutmelding krijgt en je krijgt exact dezelfde string terug bij het uitlezen van die string uit je database, werkt je escaping perfect:

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
<?
if ( isset ( $_GET [ 'string' ] ) ) {
   $query = '
      INSERT INTO
         table(fieldname)
      VALUES(
         ' . mysql_escape ( $_GET [ 'string' ] ) . '
      );
   ';
   mysql_query ( $query )
      or trigger_error ( "Fout: " . mysql_error () . "<br>query: " . $query );
   $id = mysql_insert_id ();
   $query = '
      SELECT
         fieldname
      FROM
         table
      WHERE
         field_id=' . $id;
   $res = mysql_query ( $query )
      or trigger_error ( "Fout: " . mysql_error () . "<br>query: " . $query );
   $selected_field = mysql_result ( $res, 0, 0 );
   echo 'inserted: ', $_GET [ 'string' ], '<br>';
   echo 'retrieved: ', $selected_field, '<br>';
   echo 'ok?: ', $selected_field == $_GET [ 'string' ], '<br>';
}
?>

<form method="get">
   <input type="text" name="string" />
   <input type="submit" />
</form>


Maar waarom gebruik je nou in vredesnaam die add- en stripslashes functies niet?

Het probleem met die functies is dat er soms dingen escaped worden die niet ge-escaped hoeven te worden naast dingen die wel escaped moeten worden. Als er dus data ingevoerd die opzichzelf een escape-sequence is, wordt die data in eerste instantie escaped voor bijv. MySQL, maar bevat hij bij uitlezen weer diezelfde escape-sequence die ingevoerd is. Als je daar vervolgens een stripslashes () overheenhaalt, ben je een escape sequence kwijt. Vandaar dat de bovengenoemde testcase de beste is om na te gaan of er niet teveel of te weinig escapes uitgevoerd worden. :)

Ik wil index.php?piet=1&sjaak=3 vervangen door index/1/3. Hoe doe ik dat?
Eigenlijk is dit niet echt een PHP vraag, maar een Apache vraag. Maar op de een of andere manier komt het altijd in een PHP context weer terug, vandaar hier maar een stukje uitleg. ;)

MultiViews

Verreweg de meest eenvoudige manier is om in je Apache configuratie (hetzij in httpd.conf, hetzij in een .htaccess, hetzij nog ergens anders) voor de directory waar je je php'tje hebt staan de MultiViews option aan te zetten:
code:

code:
1
Options +MultiViews


De Apache 1.3 documentatie zegt er het volgende over:
The effect of MultiViews is as follows: if the server receives a request for /some/dir/foo, if /some/dir has MultiViews enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements.
In PHP kun je vervolgens de binnengekomen request afhandelen met de $_SERVER['REQUEST_URI'] variabele.

mod_rewrite

Een veel ingewikkelder maar veel flexibeler oplossing is het gebruik maken van mod_rewrite. Deze module geeft je de beschikking over diverse configuratie directives die vertellen hoe een inkomende request "vertaald" (rewritten) moet worden naar een door jou te bepalen URI.

Een eenvoudig voorbeeld is om bijvoorbeeld de url /rewrite-test/index/1/2 te rewriten naar /rewrite-test/index.php?piet=1&sjaak=2

code:
1
2
3
RewriteEngine On
RewriteBase /rewrite-test/
RewriteRule ^index/([0-9]+)/([0-9]+)$ index.php?piet=$1&sjaak=$2


Je kunt dit natuurlijk zo gek maken als je zelf wilt. Een goed opgezette set rewriterules kan ook zorgen voor goede 'default'-afhandeling en shortcuts naar bepaalde pagina's. Zo zou je bijvoorbeeld een rewriterule kunnen maken die doorverwijst naar een search-engine als een url niet bestaat, of /user/piet doorverwijzen naar een profile.php?user=piet, etcetera. Alles bij elkaar genomen is het zeer zeker de moeite waard mod_rewrite te verkiezen boven MultiViews.

Voor meer informatie over het gebruik van mod_rewrite kun je het beste de URL Rewriting Guide en de mod_rewrite reference van Apache doornemen.

Voor meer informatie over het gebruik van regular expressions kun je hier terecht.

Het bewerken van afbeeldingen in PHP, hoe werkt dat?
Dit is een korte vraag met een uitgebreid antwoord, dat in deze FAQ uitgewerkt is.

NMe wijzigde deze reactie 21-12-2019 18:15 (23%)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Dit topic is gesloten.



Apple iPhone 11 Microsoft Xbox Series X LG OLED C9 Google Pixel 4 CES 2020 Samsung Galaxy S20 Sony PlayStation 5 Nintendo Switch Lite

'14 '15 '16 '17 2018

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2020 Hosting door True