NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Open source

Contacts for Laravel

Install
composer require roundly-consulting/contacts-for-laravel
Requires: PHP ^8.4 · Laravel ^12.0|^13.0

Overview

Typed, validated, primary-aware contacts for any Laravel model. Attach emails, phones, addresses, URLs, social handles and your own custom kinds to a user, a company, an order or anything else — all in one polymorphic contacts table, normalized on the way in, with one primary per kind, ordering, a channel-agnostic verification flow, events, a fluent facade and native vCard 3.0 export. MIT-licensed and dependency-light: Laravel plus a few small Roundly foundation packages — no third-party libraries.

What you get

Typed, normalized contacts

Emails, phones, addresses, URLs, social handles and custom kinds on any model — lower-cased, E.164-ish and scheme-complete on the way in.

One primary per kind

The first contact of a kind becomes primary automatically, promoting another demotes the old one, and when the primary leaves, the next takes over.

Verification without sending

Numeric codes or random tokens, stored only as a hash with an expiry and a wrong-guess limit. An event hands you the plaintext — you deliver it your way.

Reusable validation

ValidContactValue, ContactType::rules() and ready contacts.* array rules drop straight into your FormRequests.

vCard 3.0 & notification routing

Export an owner’s contacts as a valid vCard, and route mail, Vonage and Twilio notifications to its primary contacts.

Addresses & relationships

Structured postal addresses on a contact and a typed relationship graph — works at, spouse of — with invitations.

Built for tests

A recording Contacts::fake() that writes nothing — injected managers included — plus factory states and Pest matchers.

Documentation

Installation

Install via Composer, publish the contacts migration and the two companion migrations, then optionally publish config and translations.

Configuration

Every config key and its default — model, table, key type, auto-primary, country code, verification, custom kinds and relationship kinds.

Database schema & key types

The contacts table column by column, its indexes, soft deletes, and how key_type types owner_id for UUID or ULID owner models.

The HasContacts trait

Add HasContacts to any model for one-line addEmail/addPhone helpers, primary lookups, ordered per-kind collections and the contacts relation.

The Contacts facade

Contacts::for($owner) for an owner’s contact book, verification() for the token flow, flat calls for one contact — plus the builder and ContactData.

DI and actions

Inject ContactsManager for the facade’s API without static calls, or run one of the eight single-purpose contact actions directly.

Contact kinds & normalization

The six built-in ContactType kinds, how each value is normalized and validated, their labels and icons, and the enum helpers for selects.

Custom kinds

Register kinds such as whatsapp in config with their own label, icon and validation rules — each keeps its own primary and query scope.

Primary contacts & ordering

One primary per owner and kind — auto-assigned, swapped in a transaction, handed to the next contact when it leaves — plus per-kind ordering.

Syncing contacts

Reconcile an owner’s contacts of one kind to an exact list — update matches in place, create new ones, delete the rest, order by input.

Verification

Issue a code or token stored only as a hash with an expiry and an attempt limit, deliver it from an event, then confirm it to verify the contact.

Validation

Reuse the package’s validation in your forms: the ValidContactValue rule, ContactType::rules() and ready rules for repeatable contact arrays.

Query scopes

Composable Contact scopes — by owner, category, kind, primary, verification status, free-text search and position order.

Events

Six events for adds, updates, deletes, verification requests, verification and primary changes — react without forking.

Notification routing

Opt a model into routing mail, Vonage and Twilio notifications to its primary email and phone with RoutesNotificationsViaContacts.

vCard export

Export an owner’s contacts or a single contact as a valid vCard 3.0 card that Apple, Google and other address books read.

Structured addresses

Give a contact validated billing, home or work addresses via addresses-for-laravel, with a one-line render that falls back to the value.

Affiliations & relationships

Link contacts to each other and to owners — works at, spouse of — with invitations, expiry and an optional allow-list of relationship kinds.

Exceptions

Every exception the package throws, when it is thrown, and how to catch them all through the ContactException base class.

Testing

Swap in the recording Contacts::fake() and assert every write, build fixtures with per-kind factory states, and assert owners with Pest matchers.

Requirements

PHP 8.4+, Laravel 12 or 13, and five small Roundly foundation packages that Composer installs for you.

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 crypto

By 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.