All packages
Contacts for Laravel
vCard export
use RoundlyConsulting\Contacts\Facades\Contacts;
$user = User::create(['name' => 'Jane Doe']);
$user->addEmail('[email protected]', label: 'Work');
$user->addPhone('+421 900 000 000', label: 'Mobile');
$user->addUrl('example.com', label: 'Office, main');
Contacts::for($user)->vCard(); // a vCard 3.0 string for the owner's contacts
$contact->toVCard(); // a single contactThe owner above exports as:
BEGIN:VCARD
VERSION:3.0
N:Jane Doe;;;;
FN:Jane Doe
EMAIL;TYPE=work:[email protected]
TEL;TYPE=cell:+421900000000
item1.URL:https://example.com
item1.X-ABLabel:Office\, main
END:VCARDThe card is valid vCard 3.0 (RFC 2426), with CRLF line endings:
- N and FN are always present. N is built from the owner’s structured name attributes when it has them — last_name/family_name/surname, first_name/given_name, middle_name/additional_name, name_prefix/honorific_prefix, name_suffix/honorific_suffix. Otherwise the display name fills N’s family-name slot (N:Jane Doe;;;;).
- FN is the owner’s name, else the structured parts joined, else Contact. Only attributes the model actually has are read, so Model::shouldBeStrict() is safe.
- Email, phone, URL and address contacts map to EMAIL, TEL, URL and ADR; social and custom kinds are exported as NOTE.
- Labels: a label naming a registered type for its property (work, home, cell, fax, pager…; mobile becomes cell) is emitted as TYPE=work. Any other label is kept as itemN.X-ABLabel on a grouped property — the custom-label form Apple and Google contacts read.
- Text is escaped (backslash, comma, semicolon, and any line break as \n), URLs are left unescaped, and long lines fold at 75 octets without splitting a UTF-8 character.
Exporter and downloads
VCardExporter builds any set of contacts; a single contact’s toVCard() uses Contact as its name. Serve the string as a download from a controller:
use RoundlyConsulting\Contacts\Support\VCardExporter;
VCardExporter::forOwner($user); // same as Contacts::for($user)->vCard()
VCardExporter::forContacts($user->contactsOfType('email'), 'Jane Doe'); // any set, with a name
return response(Contacts::for($user)->vCard(), 200, [
'Content-Type' => 'text/vcard',
'Content-Disposition' => 'attachment; filename="jane-doe.vcf"',
]);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.