sprintf
Een korte vraag. Ik zie wel eens de functie sprintf voorbij komen en ik vraag me af in welke situatie je die gebruikt. Stel we hebben iemands naam en leeftijd en we willen een zin maken. Zelf zou ik dan dit doen:
Manier A:
Maar er zijn ook mensen die dan dit doen:
Manier B:
Code (php)
Mijn vraag is: doe jij het op Manier A of manier B en waarom?
Meestal manier B omdat dit beter leest en je kunt presentatie afdwingen naar een bepaald datatype :)
Stel dat $leeftijd per se een string moet zijn. Dan zou ik nu zeggen:
$leeftijd = (string) $leeftijd;
echo 'Ik ben ' . $leeftijd . ' jaar.'
Maar met sprintf kun je dan %s gebruiken en hoef je niet eerst te typecasten? Is dat correct?
Met een kleine slag om de arm zeg ik dat het correct is ;)
Mijn vraag is, waarom is het nodig om types mee te geven? Dit werkt namelijk ook prima:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$naam = 'Roel';
$leeftijd = 18;
$geld = 30000;
echo sprintf('%1$s is %2$s jaar en hij zou graag € %3$s op zijn rekening hebben.', $naam, $leeftijd, number_format($geld, 0, ',', '.'));
?>
$naam = 'Roel';
$leeftijd = 18;
$geld = 30000;
echo sprintf('%1$s is %2$s jaar en hij zou graag € %3$s op zijn rekening hebben.', $naam, $leeftijd, number_format($geld, 0, ',', '.'));
?>
Ik weet nog niet precies waarom je voor ieder type een andere type specifier moet gebruiken.
%1$s is uitgepakt:
%s en $1
%s betekend dat het een string is en $1 betekend het eerste argument.
Dat %3$s werkt is omdat number_format een string terug geeft. Mocht je direct een getal in voegen dan MOET je gebruik maken van de positioncharacters ($n), omdat anders de functie niet werkt.
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
$naam = 'Jan';
$leeftijd = 24;
echo sprintf('%s is %d', $naam, $leeftijd);
// Jan is 24 (hierbij wordt 24 gezien als een int en doormiddel van type juggling wordt het automatisch een string
echo sprintf('%s is %s', $naam, $leeftijd);
// Jan is 24 (hierbij wordt 24 getypecast naar een string en dan toegevoegd
echo sprintf('%s is %d', $leeftijd, $naam);
// Jan is 0 (de arguments staan in verkeerde volgorde)
echo sprintf('%$2s is %$1d', $leeftijd, $naam);
// Jan is 24 (doormiddel van positioncharacters wijzen we de positie van het argument aan)
echo sprintf('%$2s is %$2s en %$1d', $leeftijd, $naam);
// Jan is Jan en 24 (met positioncharacters kunnen we ook arguments vaker gebruiken)
echo sprintf('%s is %s en %d', $naam, $leeftijd);
// PHP raakt de weg kwijt en geeft een error: Too few arguments
$naam = 'Jan';
$leeftijd = 24;
echo sprintf('%s is %d', $naam, $leeftijd);
// Jan is 24 (hierbij wordt 24 gezien als een int en doormiddel van type juggling wordt het automatisch een string
echo sprintf('%s is %s', $naam, $leeftijd);
// Jan is 24 (hierbij wordt 24 getypecast naar een string en dan toegevoegd
echo sprintf('%s is %d', $leeftijd, $naam);
// Jan is 0 (de arguments staan in verkeerde volgorde)
echo sprintf('%$2s is %$1d', $leeftijd, $naam);
// Jan is 24 (doormiddel van positioncharacters wijzen we de positie van het argument aan)
echo sprintf('%$2s is %$2s en %$1d', $leeftijd, $naam);
// Jan is Jan en 24 (met positioncharacters kunnen we ook arguments vaker gebruiken)
echo sprintf('%s is %s en %d', $naam, $leeftijd);
// PHP raakt de weg kwijt en geeft een error: Too few arguments
Toevoeging op 07/03/2012 11:40:21:
Oeps... Wouter was me voor :)
Hoe kan het dan dat ik geen error krijg?
number_format geeft zoals je bij Return Values kunt lezen een string terug en geen int.
En anders krijg je als nog geen error, omdat de int dan wordt getypecast naar een string. Het is beter om een %d te gebruiken want dan voeg je hem in als een int en dan wordt er doormiddel van type juggling besloten dat de int een string moet worden, als je een string opgeeft wordt de string eerst getypecast en dan pas toegevoegd.
@Roel, En anders krijg je als nog geen error, omdat de int dan wordt getypecast naar een string. Het is beter om een %d te gebruiken want dan voeg je hem in als een int en dan wordt er doormiddel van type juggling besloten dat de int een string moet worden, als je een string opgeeft wordt de string eerst getypecast en dan pas toegevoegd.
Wouter J op 07/03/2012 11:50:28:
Het is beter om een %d te gebruiken want dan voeg je hem in als een int en dan wordt er doormiddel van type juggling besloten dat de int een string moet worden, als je een string opgeeft wordt de string eerst getypecast en dan pas toegevoegd.
Wouter, kun je hier een voorbeeldje van geven wat precies het verschil is / zou kunnen zijn?
En dit is toch echt een integer die als een string geparsed moet worden:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$naam = 'Roel';
$leeftijd = (int)18;
$geld = 30000;
echo sprintf('%1$s is %2$s jaar en hij zou graag € %3$s op zijn rekening hebben.', $naam, $leeftijd, number_format($geld, 0, ',', '.'));
?>
$naam = 'Roel';
$leeftijd = (int)18;
$geld = 30000;
echo sprintf('%1$s is %2$s jaar en hij zou graag € %3$s op zijn rekening hebben.', $naam, $leeftijd, number_format($geld, 0, ',', '.'));
?>
Wouter J op 07/03/2012 11:59:47:
Tot zover begrijp ik het. Maar wat is het verschil in de uitkomst? Beiden geven toch hetzelfde resultaat? Zijn er situaties waarin het resultaat kan verschillen?
Krijg je niks terug. Als je het als volgt doet:
Krijg je '1' terug, dus in sommige gevallen kan het handig zijn. Of als je een object echo'd:
Maar dit levert toch in beide gevallen hetzelfde op?
* Waarom gebruiken? om onderdelen te scheiden. php uit strings halen.
Ik vind het ideaal bij sql-strings.
bv.
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$sql = "SELECT id, username FROM users WHERE id=%d OR email='%s' ";
$res = mysql_query(sprintf(
$sql,
$_POST['id'],
mysql_real_escape_string($_POST['mail'])
));
...
?>
$sql = "SELECT id, username FROM users WHERE id=%d OR email='%s' ";
$res = mysql_query(sprintf(
$sql,
$_POST['id'],
mysql_real_escape_string($_POST['mail'])
));
...
?>
Het punt is vooral: die $sql is een string die je kan bijhouden.
Je kan dit bijhouden en hergebruiken, onafhankelijk van de variabelen die je nodig zal hebben. De ene keer kan het $_POST['mail'] zijn, de andere keer $_POST['email'] ...
Je ziet ook in 1 oogopslag wat de sql string probeert te doen, zonder je eerst door al die , '". beveilig($var) '" ...
Je kan een generieke INSERT string als commentaar zetten in je mySQL tabel. Gemakkelijk te copy/pasten, weinig aan te passen ... voor hergebruik.
Met die ene functie sprintf heb je al bijna een template engine op zich.
Je maakt een template van je sql strings; op het juiste moment vul je de data in.
Als je dus een argument wil over het waarom ... om de zelfde redenen waarom iemand templates zou gebruiken.
Trouwens, ook bruikbaar op deze manier:
Code (php)
* wanneer?
Op vrij veel plaatsen.
Ik denk dat vrij veel standaard php-functies gewoon sprintf gebruiken.
bv.
money_format, str_pad, datum parsen (bv. zien dat de dag en maand twee karakters bevatten), ...
Al dat soort dingen kan je vervangen door een sprintf.
En: het komt vanuit C. In C was dit zowat de enige manier om een getal als string op je scherm te tonen.
Het is dus vrij generiek, ook buiten php
Gewijzigd op 07/03/2012 13:03:33 door Kris Peeters
Ik zal voortaan dan ook maar sprintf gaan gebruiken overal waar ik een string aan variabelen moet vastknopen. Weer wat geleerd! :)
De mensen gaan dus misschien wel eens vreemd opkijken als ze dat zien staan.
Als dat je niet tegenhoudt ...
Gewijzigd op 07/03/2012 13:38:38 door Kris Peeters
Nee hoor, dat houdt me zeker niet tegen ;)
Ozzie PHP op 07/03/2012 11:57:39:
Wouter, kun je hier een voorbeeldje van geven wat precies het verschil is / zou kunnen zijn?
Wouter J op 07/03/2012 11:50:28:
Het is beter om een %d te gebruiken want dan voeg je hem in als een int en dan wordt er doormiddel van type juggling besloten dat de int een string moet worden, als je een string opgeeft wordt de string eerst getypecast en dan pas toegevoegd.
Wouter, kun je hier een voorbeeldje van geven wat precies het verschil is / zou kunnen zijn?
Ozzie PHP op 07/03/2012 12:05:38:
Tot zover begrijp ik het. Maar wat is het verschil in de uitkomst? Beiden geven toch hetzelfde resultaat? Zijn er situaties waarin het resultaat kan verschillen?
Wouter J op 07/03/2012 11:59:47:
Tot zover begrijp ik het. Maar wat is het verschil in de uitkomst? Beiden geven toch hetzelfde resultaat? Zijn er situaties waarin het resultaat kan verschillen?
Ozzie PHP op 07/03/2012 12:20:46:
Kan iemand hier wellicht nog wat duidelijkheid over verschaffen wat Wouter bedoelt?
Met typecasten wijs je doormiddel van (<type>) een type toe aan een waarde. Je kan hiermee forceren wat voor waarde het wordt:
Code (php)
Type juggling
Type juggling is een leuke bijkomstigheid die in elke taal zit. Type juggling gebruik je als je iets met 2 verschillende types gaat doen. Hierdoor wordt 1 van de 2 types omgewisseld voor het andere type string.bool wordt bijv. string.
Code (php)
Je ziet hier doordat je iets met 2 verschillende types doet (in dit geval optellen en bij elkaar plakken) 1 van de 2 types veranderd in de andere. Welke naar welke veranderd wordt bepaald door de operator en de types.
En nu dit betrekken op het voorbeeld wat ik hiervoor gaf:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Gewijzigd op 12/03/2012 16:14:28 door Wouter J