Contact kinds & normalization
RoundlyConsulting\Contacts\Enums\ContactType is a backed string enum with six kinds: Email, Phone, Address, Url, Social and Custom. Each kind drives normalization, validation, a translatable label and an icon name:
| Kind | Normalization | Default rules | Label | Icon |
|---|---|---|---|---|
email | Lower-cased and trimmed. | required, string, email | envelope | |
phone | Separators stripped, leading + kept, 00 read as +, a (0) after the country code dropped; default_country_code replaces a national number’s trunk 0. | required, string, regex:/^\+?[1-9]\d{6,14}$/ | Phone | phone |
address | Trimmed. | required, string | Address | map-pin |
url | https:// prepended when no scheme is present. | required, string, url | Website | globe-alt |
social | Trimmed. | required, string | Social | at-symbol |
custom | Trimmed. | required, string | Other | identification |
Normalization
Normalization is pure PHP with no external libraries. It runs before validation on every add, update and sync, so the same number is never stored five different ways:
use RoundlyConsulting\Contacts\Enums\ContactType;
ContactType::Email->normalize(' [email protected] '); // '[email protected]'
ContactType::Phone->normalize('+421 (900) 000-000'); // '+421900000000'
ContactType::Phone->normalize('+44 (0)20 7946 0000'); // '+442079460000' — the (0) is dropped
ContactType::Phone->normalize('00421 900 123 456'); // '+421900123456' — 00 reads as +
ContactType::Phone->normalize('0900 123 456'); // '0900123456' — bare digits
// ...or '+421900123456' with CONTACTS_DEFAULT_COUNTRY_CODE=421 (trunk 0 replaced)
ContactType::Url->normalize('example.com'); // 'https://example.com'
ContactType::Url->normalize('ftp://files.example.com'); // unchanged — has a scheme
ContactType::Social->normalize(' @janedoe '); // '@janedoe'Phone normalization is best-effort E.164. A leading 00 is read as +, and a (0) after the country code is dropped. With default_country_code set (for example 421), a national number gets it in place of its trunk 0 — 0900 123 456 becomes +421900123456; Italy and San Marino keep the 0, as their numbers do. Without it, a national number keeps its bare digits.
Rules always run on the normalized value — what gets stored — and every value is capped at 255 characters, the value column’s length. A value that fails either throws InvalidContactValue before anything is written.
Labels, icons and rules
ContactType::Phone->label(); // 'Phone' — config, then translation, then value
ContactType::Phone->icon(); // 'phone'
ContactType::Phone->validationRules(); // ['required', 'string', 'regex:/^\+?[1-9]\d{6,14}$/']
ContactType::Phone->rules(); // ['required', 'string', new ValidContactValue(ContactType::Phone)]
ContactType::fromValueOrCustom('email'); // ContactType::Email
ContactType::fromValueOrCustom('fax'); // ContactType::Customlabel() resolves in order: a label set in contacts.types, then the contacts::types translation, then the capitalized value. Publish contacts-translations to translate the built-in labels.
Enum helpers
ContactType also uses the Helpers trait from enums-for-laravel for select lists and validation. Its own config- and translation-aware label() takes precedence over the trait’s plain one:
ContactType::values(); // Collection: 'email', 'phone', 'address', 'url', 'social', 'custom'
ContactType::options(); // EnumOption DTOs {value, label, name} for selects
ContactType::validationRule(); // 'in:email,phone,address,url,social,custom'
$type->isIn([ContactType::Email, ContactType::Phone]);validationRule() lists the six built-in values only. To accept registered custom kinds too, use ContactRules::kinds() — see Validation.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.