Telefoonnummer opslaan en weergeven
Hoe slaan jullie telefoonnummers op in een database en hoe geven jullie ze weer?
Sla je het nummer met of zonder opmaak op in de database?
Zo 0031201234567 of zo 0031 20 1234567?
En als je het nummer weergeeft, gebruik je dan opmaak of niet? Als je wel opmaak gebruikt dan lijkt me dat lastig omdat sommige netnummers uit 3 cijfers bestaan en sommige uit 4 cijfers.
Wie heeft er tips?
Nadeel is dat in elk land de telefoonnummers anders zijn dus je kunt niet zeggen dat ze altijd een bepaalde lengte hebben. Ik zou ze dan verder gewoon in een varchar stopppen.
Ben wel benieuwd hoe anderen dit doen. Zelf maak ik me er niet zo druk om. Het wordt pas een punt als je een systeem hebt waarin je na telefoonnummers kunt zoeken bijvoorbeeld.
Gewijzigd op 26/02/2014 13:24:18 door Ozzie PHP
Ozzie PHP op 26/02/2014 13:23:00:
Thanks voor je reactie Michael. Is het nog een idee om landnummer, netnummer en abonneenummer in aparte velden in de database op te slaan?
Lijkt me helemaal afhankelijk van wat je ermee wil doen. Als je je gebruikers per gebied, land, etc wil sorteren om bijvoorbeeld een zoekfunctie te hebben met een optie om alleen in Nederland te zoeken of zelfs in zuid-holland, dan kan dat makkelijk zijn. Anders lijkt het me niet echt een toegevoegde waarde hebben.
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
58
59
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
58
59
<?php
class PhoneNumber
{
private $netNumber;
private $phoneNumber;
private static $netNumberMatch = '(035|0031|...)';
public function __construct($netNumber, $phoneNumber)
{
$this->netNumber = $netNumber;
$this->phoneNumber = $phoneNumber;
}
public static function parse($number)
{
if (false !== strpos($number, '-')) {
list($net, $phone) = explode('-', $number, 2);
} elseif (false !== strpos($number, ' ')) {
list($net, $phone) = explode(' ', $number, 2);
} else {
if (preg_match('/'.self::netNumberMatch.'(.+)/', $number, $data)) {
$net = $data[1];
$phone = $data[2];
} else {
// no net number
$net = null;
$phone = $number;
}
}
$normalize = function ($number) {
return preg_replace('/\D/', '', $number);
};
return new self($normalize($net), $normalize($phone));
}
public function hasNetNumber()
{
return null !== $this->netNumber;
}
public function getNetNumber()
{
return $this->netNumber;
}
public function getPhoneNumber()
{
return $this->phoneNumber;
}
public function __toString()
{
return sprintf('%d-%d', $this->netNumber, $this->phoneNumber);
}
}
?>
class PhoneNumber
{
private $netNumber;
private $phoneNumber;
private static $netNumberMatch = '(035|0031|...)';
public function __construct($netNumber, $phoneNumber)
{
$this->netNumber = $netNumber;
$this->phoneNumber = $phoneNumber;
}
public static function parse($number)
{
if (false !== strpos($number, '-')) {
list($net, $phone) = explode('-', $number, 2);
} elseif (false !== strpos($number, ' ')) {
list($net, $phone) = explode(' ', $number, 2);
} else {
if (preg_match('/'.self::netNumberMatch.'(.+)/', $number, $data)) {
$net = $data[1];
$phone = $data[2];
} else {
// no net number
$net = null;
$phone = $number;
}
}
$normalize = function ($number) {
return preg_replace('/\D/', '', $number);
};
return new self($normalize($net), $normalize($phone));
}
public function hasNetNumber()
{
return null !== $this->netNumber;
}
public function getNetNumber()
{
return $this->netNumber;
}
public function getPhoneNumber()
{
return $this->phoneNumber;
}
public function __toString()
{
return sprintf('%d-%d', $this->netNumber, $this->phoneNumber);
}
}
?>
Nu gaat in dit voorbeeld een beetje tegen de S van SOLID in. Onze VO heeft nu namelijk 2 roles: telnr. normaliseren, telnr. presenteren. Dat laatste gebeurd in de __toString method, die al bepaalt hoe wij het nummer moeten tonen. Dit zou je eigenlijk eruit moeten slopen en in een presenter class moeten stoppen:
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
class InternationalPhoneNumberPresenter
{
public function present(PhoneNumber $number, $country = 'nl')
{
return sprintf(
'%s%s%d',
$this->getCountryNumber($country),
$number->hasNetNumber() ? $this->makeNetNumberInternational($number->getNetNumber()).'-' : '',
$number->getPhoneNumber()
);
}
protected function getCountryNumber($country)
{
return Intl::getCountryNumber($country);
}
protected function makeNetNumberInternational($number)
{
return preg_replace('/^(0*)/', '($1)', $number);
}
}
?>
class InternationalPhoneNumberPresenter
{
public function present(PhoneNumber $number, $country = 'nl')
{
return sprintf(
'%s%s%d',
$this->getCountryNumber($country),
$number->hasNetNumber() ? $this->makeNetNumberInternational($number->getNetNumber()).'-' : '',
$number->getPhoneNumber()
);
}
protected function getCountryNumber($country)
{
return Intl::getCountryNumber($country);
}
protected function makeNetNumberInternational($number)
{
return preg_replace('/^(0*)/', '($1)', $number);
}
}
?>
Leesvoer:
- http://verraes.net/2013/02/casting-value-objects/
- http://verraes.net/2013/11/value-objects-and-user-interfaces/
Gewijzigd op 26/02/2014 13:35:00 door Wouter J
Toevoeging op 26/02/2014 13:36:39:
@Wouter, bedankt voor je voorbeeld.
Ja natuurlijk kan dat, maar dan moet je 100% zeker weten dat alle nummers exact het zelfde resultaat hebben. Niet elk netnummer en landcode zijn altijd even lang. Zo is het netnummer in het westen 3 cijfers en in het oosten 4 cijfers. Zo is de landcode van Canada 1 en die van Jersey 441537 en niet elk telefoonnummer is even lang dus hoe wil je die dan uit elkaar gaan trekken.
Netnummers sla ik zo op in de database:
010 12 34 567
06 nummers:
06 12 34 56 78
Zo worden de nummers ook weergeven op de site.
Wat bedoel je met uit elkaar trekken?
Wat ik bedoelde was of ik een stukje uit het complete nummer kan opzoeken.
Waar ik ook aan zat te denken. Je zou ook ieder nummer in één databaseveld kunnen opslaan, als volgt:
31 020 2345678
31 06 12345678
Het 1e deel is dan de landcode, het 2e deel is het netnummer of 06 en het laatste deel is het abonneenummer. De vraag is of je wil kunnen zoeken op tel.nr. Want dan wordt het met deze opzet, wanwege de spaties wel lastiger natuurlijk.
Ozzie PHP op 26/02/2014 13:48:13:
31 020 2345678
31 06 12345678
Het 1e deel is dan de landcode, het 2e deel is het netnummer of 06 en het laatste deel is het abonneenummer. De vraag is of je wil kunnen zoeken op tel.nr. Want dan wordt het met deze opzet, wanwege de spaties wel lastiger natuurlijk.
31 06 12345678
Het 1e deel is dan de landcode, het 2e deel is het netnummer of 06 en het laatste deel is het abonneenummer. De vraag is of je wil kunnen zoeken op tel.nr. Want dan wordt het met deze opzet, wanwege de spaties wel lastiger natuurlijk.
Je gaat er daarbij van uit dat elk netnummer uit 3 posities bestaat?
Wil je het gebruiksvriendelijk doen, dan zul je of een heel duidelijk sjabloon moeten aangeven waarin een gebruiker zijn nummer moet ingeven of bij de controle moeten controleren of hetgeen is opgegeven een mogelijk telefoonnummer kan zijn (waarbij een gebruiker dus vrij is om () + - . en/of spatie te gebruiken (en mogelijk nog meer varianten).
Voor wie is het uiteindelijk bedoelt? Wereldwijd of Nederland; daar zou je dan je invoer/controle op kunnen afstemmen. Denk dat een eenduidige controle op een willekeurig telefoonnummer ondoenlijk is; daarvoor is er te veel variatie bij gebruiker en in (internationale) telefoonnummers.
>> Je gaat er daarbij van uit dat elk netnummer uit 3 posities bestaat?
Nee, dit kunnen er (in NL) ook 4 zijn. Maar als ik ze dus in aparte velden zou zetten, of in één veld maar spaties zou gebruiken, dan weet ik wat wat is.
Het enige wat dan nog een puntje is, is of je alles in aparte velden gaat opslaan of niet.
Een tel.nr. bestaat toch altijd uit een landcode, netnummer en abonneenummer (en dan tel ik 112 even niet mee)?
>>>> ... dus hoe wil je die dan uit elkaar gaan trekken.
>> Wat bedoel je met uit elkaar trekken?
Jij hebt het erover om te gaan zoeken naar een land of provincie, daarvoor zou je dus dat deel, 31 voor NL of 020 voor Amsterdam. Als ik dan 0031631020000 als telefoonnummer hebt zou je die dus eerst elkaar moeten trekken om te zien wat het netnummer en wat de landcode is.
Opslaan met spaties zou ik niet doen en je kunt dit een gebruiker ook niet afdwingen om het zo in te vullen.
Ah, zo bedoel je. Mijn idee was dan om voor de landcode een drop-downmenu te nemen, of gewoon vast op NL te zetten, en dan een apart veld voor het netnummer en een apart veld voor het abonneenummer. Je krijgt dan dus 3 waardes: landnr. netnr. en abnr. die zou je dan in 3 velden kunnen opslaan. Eventueel zou je dan de landcode als nl kunnen opslaan. Zoiets zat ik te denken.
Dat zou inderdaad kunnen
Oké, thanks voor het meedenken!