Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Vcard Bundle Laravel Package

jeroendesloovere/vcard-bundle

Symfony bundle for generating and downloading vCard (VCF) contact files from PHP objects, wrapping the jeroendesloovere/vcard library with service integration and helpers for Symfony applications.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — Poor for a Laravel codebase, by definition. This is a Symfony2 bundle, not a Laravel package: it ships a *Bundle class extending Symfony\Component\HttpKernel\Bundle\Bundle, XML service definitions, and a DependencyInjection extension. Laravel has no bundle auto-discovery, no AppKernel registration, and no Symfony container compiler pass to hook into. Nothing in the package targets Laravel's service container, facades, config publishing, or package discovery. The only salvageable asset is the framework-agnostic vCard generator it wraps (jeroendesloovere/vcard), which is plain PHP and can be consumed from Laravel — but at that point we are not adopting this package, we are adopting its dependency.

Integration feasibility — Low as-is, moderate via extraction. The composer.json was last touched in 2018 and constrains symfony/framework-bundle to 2.x/3.x. A modern Laravel app (10/11/12) resolves Symfony components at ^6/^7. Those constraints collide, so composer require will either fail outright or force a downgrade of shared Symfony packages that Laravel itself depends on. That is a hard blocker, not a nuisance. Feasibility only becomes real if we target the underlying library directly, or replace it.

Technical risk — High and mostly unbounded.

  • Abandonment: last release 2018-11-30; ~7 years without a commit. No PHP 8.x validation, no security response path, no RFC 6350 (vCard 4.0) work.
  • Ecosystem validation: 16 stars, 0 dependents. Effectively single-maintainer, bus factor of one, and no third party has staked production on it — a strong negative signal for a format that touches customer contact data.
  • Correctness risk: vCard output is consumed by iOS Contacts, Outlook, Google Contacts, and Android. Each is strict in different ways. Failure modes include 75-octet line folding, CRLF handling, quoted-printable vs. base64 encoding, and charset declaration — all easy to get subtly wrong and hard to test without device-level verification.
  • Injection surface: vCard property values are newline-delimited. Unescaped newlines (or \n sequences) in user-supplied fields such as ORG, TITLE, or NOTE allow property injection into the generated card. In any flow where we generate cards from user profile data, this needs explicit sanitization we would have to add ourselves.
  • Compliance: generating contact data may fall under GDPR/data-handling review; an unmaintained dependency in that path is a procurement and audit liability.

Key questions

  1. Is the actual requirement generation only, or do we also need to parse/validate inbound .vcf files? Parsing changes the build-vs-buy calculus entirely and pushes toward sabre/vobject.
  2. What is the consumption target — downloadable single contacts, bulk export for CRM import, or email attachments? Bulk export amplifies encoding and folding bugs.
  3. Do we need vCard 4.0, or is 3.0 sufficient for the target clients? 3.0 is materially safer for Outlook interop.
  4. Who owns the fork if we vendor it? A 300-line generator is cheaper to own than a fork of an abandoned bundle.
  5. Is there any reason to prefer this over sabre/vobject, which is maintained, widely deployed, and handles both generation and parsing?

Verdict: do not adopt the bundle. Treat it as a reference implementation for the underlying generator, and either pull jeroendesloovere/vcard directly behind our own interface or build a thin RFC 6350 writer with sabre/vobject as the parser if inbound handling is in scope.

Integration Approach

Stack fit — The bundle layer is a non-starter; the value is in the generator. In a Laravel app, the correct shape is a first-party VCardService (or VCardBuilder value object) registered as a singleton, injected into the export controller or queued job, and exposed through an optional facade if the team prefers. Configuration — default version, charset, organization defaults — belongs in config/vcard.php and is published via a service provider we write. This is roughly a half-day of scaffolding and gives us a seam to swap the generator later without touching call sites.

Migration path — Two viable routes, in order of preference:

  1. Direct dependency on jeroendesloovere/vcard (the non-Symfony sibling package). Lowest delta from the original intent, plain PHP, no Symfony kernel coupling. We pin it, wrap it, and accept that we own the risk surface ourselves.
  2. Replace with sabre/vobject. Actively maintained, used across calendar/contact infrastructure, handles generation and parsing, and correctly implements line folding and escaping. Cost is a small rewrite of the builder; benefit is a supported dependency and no fork obligation.

If either route stalls on a deadline, the fallback is a ~200–300 line in-house writer targeting vCard 3.0 with explicit escaping and folding — genuinely tractable, and it removes the dependency question permanently.

Compatibility — Verify PHP 8.2/8.3 behavior before committing to option 1: the 2018 code predates typed properties and PHP 8 deprecations, and it will likely emit deprecation notices and may fail on stricter string/array handling. Also confirm UTF-8 handling end-to-end rather than trusting the default charset. For option 2, check the sabre/vobject major version against our PHP floor.

Sequencing

  1. Spike (1–2 days): generate a card from a realistic profile (non-ASCII name, multi-line address, phone, photo) and import into iOS, Outlook, and Google Contacts. Verify folding, escaping, and charset. This test is the decision gate.
  2. Interface first: define VCardGenerator contract with a single generate(ContactData): string method, plus an escaping/sanitization policy for user-supplied fields.
  3. Implement behind the interface using whichever library survived the spike.
  4. Provider + config + facade, then wire one consumer (the lowest-traffic export path) and observe.
  5. Expand to bulk export only after single-card output is verified across devices; add golden-file tests for representative cards.
  6. Record the decision as an ADR covering why the bundle was rejected, so it does not resurface.

Operational Impact

Maintenance — Effectively 100% ours. The upstream is dormant, so any bug fix, PHP compatibility patch, or spec update is a fork we maintain. Budget a few hours per PHP minor upgrade and per dependency-security sweep. Option 2 (sabre/vobject) shifts most of this back to a vendor; that is the primary operational argument for replacing rather than wrapping.

Support — No commercial support, no active maintainer response, no security disclosure channel. Escalation path is "read the source." For a contact-export feature this is tolerable; for anything customer-facing at scale it will be raised in architecture review. Note also that 0 dependents means no community knowledge base — no Stack Overflow answers, no blog posts, no prior art when output looks wrong on a specific device.

Scaling — Generation itself is trivially cheap: string assembly, no I/O, no external calls. A single card is well under a millisecond; tens of thousands in a batch export are CPU-bound but parallelizable across queue workers. The real scaling concern is memory when embedding photos in base64 into bulk archives — stream per-contact rather than building an in-memory collection. The bundle's Symfony DI bootstrapping is irrelevant in Laravel since we will not use that layer at all.

Failure modes

  • Dependency resolution failure — Symfony constraint collision blocks install; surfaces immediately, low blast radius, high annoyance.
  • Silent malformed output — the card imports but with truncated or mojibaked fields; no exception, no log line. Highest-risk mode because it reaches customers before we notice. Mitigated only by device-level golden tests.
  • Property injection — unescaped newlines in user data corrupt the card or inject fields. Must be handled in our wrapper, not delegated to the library.
  • Runtime deprecation/fatal errors post-PHP-upgrade — likely with the 2018 code; caught in CI if we have coverage, otherwise in production.
  • Interop drift — device vendors tighten parsing over time; a frozen library cannot follow. Degrades slowly rather than breaking loudly.

Ramp-up — Low for the mechanics, moderate for the format. Any mid-level PHP engineer can generate a card in an afternoon. Getting it right — folding at 75 octets, escaping backslashes/commas/semicolons/newlines, choosing 3.0 vs 4.0 per target client, verifying against real devices — takes a day or two of spec reading and empirical testing. That knowledge is concentrated in whoever runs the spike, so pair on it and capture the device-matrix results in the ADR. Given the low opportunity score (14.6), treat this as commodity plumbing: buy or build the smallest thing that passes the device matrix, keep it behind an interface, and do not invest in the ecosystem further.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route