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

Somali Phone Laravel Package

novo-connect/somali-phone

A Laravel/PHP package for Somali phone numbers. Validate, normalize, and format local and +252 mobile numbers with carrier-aware parsing for clean, consistent user data.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and check compatibility before anything else:

composer require novo-connect/somali-phone
  • Confirm your app meets the constraints: PHP 8.2+ and Laravel 12 or 13 for the framework integration. If you're on an older LTS, the Laravel-facing pieces (validation rule, string rule, cast) are not guaranteed to work — verify or isolate the core normalizer.
  • Look at these first, in order: the README (rule names, cast class, return types), config/somali-phone.php (if published — prefix/operator tables, default behaviour), and lang/en + lang/so for message keys.
  • Publish config/assets if the package exposes them:
php artisan vendor:publish --tag=somali-phone-config
php artisan vendor:publish --tag=somali-phone-lang

First use case: a registration or checkout form with a Somali mobile number. You want to accept the messy real-world input (+252 61 xxx xxxx, 00252..., 06..., Arabic-Indic digits), reject invalid numbers, then store a single canonical form (E.164, e.g. +2526...) so downstream lookups, SMS routing and reporting are consistent.

Minimal flow:

// FormRequest
public function rules(): array
{
    return [
        'phone' => ['required', 'string', new SomaliPhone()], // confirm exact class name in README
    ];
}

Then normalize and persist the canonical value rather than the raw input. Keep the raw string in a separate column if you need an audit trail of what the user typed.

Implementation Patterns

Validate, then normalize, then store. Treat these as three distinct steps. Validation answers "is this a real Somali mobile number?"; normalization answers "what is the one canonical representation?"; storage should only ever see the canonical form. Doing normalization inside the validator and relying on that side effect is fragile — call the normalizer explicitly before saving.

Use the right rule for the right layer.

  • FormRequest / controller validation → the Laravel validation rule.
  • Livewire, Filament, or any fluent/string-based validation → the string rule.
  • Model persistence → the Eloquent cast, so every write normalizes and every read returns a consistent value.
protected function casts(): array
{
    return [
        'phone' => SomaliPhoneCast::class, // confirm class name
    ];
}

Verify the cast is idempotent: setting an already-normalized +252... value must not double-prefix it. This matters for seeders, factories, imports and updateOrCreate.

Layer operator/wallet metadata on top. After a number is valid and normalized, the operator, virtual network and wallet lookups are cheap enrichment. Typical uses:

  • SMS routing / sender ID selection — pick the gateway route by operator.
  • Mobile money — use the wallet lookup and WAAFI support check to decide whether to offer WAAFI at checkout, and which wallet options to render.
  • Analytics and fraud — segment by operator/virtual network without a third-party HLR lookup.
  • Support tooling — show an agent the operator and wallet behind a number.
$result = $normalizer->parse($request->input('phone'));

// $result->e164, operator, virtual network, wallet, waafiSupported()

Expose this in an API resource as a nested object (phone.e164, phone.operator, phone.wallet) so the frontend never re-parses.

Handle virtual networks explicitly. Somnet, Soltelco and Durdur mean the prefix alone does not always equal the operating MNO. If your business logic keys off "operator" for pricing or routing, decide deliberately whether you mean the host network or the virtual network, and use the corresponding field. Do not assume one implies the other.

Bulk imports. Normalizing a CSV of contacts should collect per-row failures rather than aborting the whole import. Wrap the parse call, catch the exception, and write rejected rows to an error report with the original value and reason. This is the single highest-value pattern for day-to-day use, since imports are where dirty data actually shows up.

Localization. The package ships English and Somali messages. Set the app locale per request (or per user preference) and let the package resolve messages. If you need custom wording, publish the lang files rather than overriding validation messages globally — targeted overrides avoid collateral damage to other rules.

Testing. Build a fixture set from the documented NCA prefixes plus the awkward formats: leading 0, 00252, bare 252, spaces/dashes, Arabic-Indic digits. Assert both the accept/reject outcome and the normalized output. Don't use real subscriber numbers in tests.

Gotchas and Tips

  • The numbering plan is dated December 2024. Prefix allocations change. Pin the package version, and plan a re-validation pass over stored numbers whenever you upgrade — a number that normalized correctly last year may now resolve to a different operator or be invalid.
  • Arabic-Indic digits are a normalization concern, not just parsing. Normalize input before any comparison or storage, but scope it to the phone field. Blanket digit transliteration across a request can silently corrupt other inputs.
  • Pick one canonical format early and enforce it. Mixing +252..., 00252... and 0... in the same column will make operator lookups, deduplication and SMS delivery inconsistent. Backfill existing rows before adding a unique constraint.
  • Casts that throw on read are dangerous. If the cast rejects unparseable legacy values, toArray(), API serialization and queued jobs will blow up on old rows. Either backfill first or make the cast tolerant (return the raw value when parsing fails) and enforce validity at the write path.
  • Remember nullable. The rule will reject null/empty string unless you add nullable (or sometimes) explicitly. This is the most common "why is my optional field failing" issue.
  • WAAFI support check ≠ wallet is active. Treat it as a capability hint for UI, and always confirm with the payment provider at transaction time. Never make it the sole gate on a money movement.
  • Don't rely on client-side validation. The number must be re-validated and re-normalized server-side; the frontend copy of the logic will drift from the package's numbering plan.
  • Operator tables are static data, not a live registry. A correct-looking result can still be wrong for ported numbers. If routing accuracy is business-critical, reconcile against delivery reports rather than assuming the prefix is authoritative.
  • Locale fallback isn't automatic. If Somali messages appear where you expected English (or vice versa), check the app locale and that the so translation files are present and published — missing keys fall back to the key name or the default locale depending on config.
  • First release, so treat the public API as unstable. The core surface (rule class, cast class, result object methods) has no deprecation history yet. Wrap the package behind a thin application-level service (e.g. PhoneService::normalize() / ::lookup()) so a future breaking rename is a one-file change rather than a grep across the codebase.
  • Extension point: the operator/prefix table is where you'd add or correct allocations locally. Prefer patching via config over editing vendor files, and feed corrections upstream so the next release carries them.
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator